diff --git a/README.md b/README.md index b3fc0e2c..134065fd 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,13 @@ For 64-bit Linux users, ```libc6:i386```, ```libstdc++6:i386```, ```libncurses5 __NOTE__: To roll back to the original driver go to: Device Manager -> Right click on device -> Check box for "Delete the driver software for this device" and click Uninstall +###### Driver Setup for Black Magic Probe +1. Download .inf file drivers from [blacksphere github](https://github.com/blacksphere/blackmagic/tree/master/driver) +2. Plugin Black Magic Probe +3. Point the installer to the folder containing blackmagic.inf + +__NOTE__: If using Windows 10 or Linux then two UART COM ports will be visible without requiring additional drivers + ### Selecting a SoftDevice SoftDevices contain the BLE stack and housekeeping, and must be downloaded once before a sketch using BLE can be loaded. The SD consumes ~5k of Ram + some extra based on actual BLE configuration. diff --git a/cores/nRF5/wiring_analog_nRF51.c b/cores/nRF5/wiring_analog_nRF51.c index f22a8b5d..0feda151 100644 --- a/cores/nRF5/wiring_analog_nRF51.c +++ b/cores/nRF5/wiring_analog_nRF51.c @@ -28,27 +28,16 @@ extern "C" { #endif -#define PWM_COUNT 3 -#define PIN_FREE 0xffffffff - -struct PWMContext { - uint32_t pin; - uint32_t value; - uint32_t channel; - uint32_t mask; - uint32_t event; -}; +static uint32_t adcReference = ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling; +static uint32_t adcPrescaling = ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling; -static struct PWMContext pwmContext[PWM_COUNT] = { +struct PWMContext pwmContext[PWM_COUNT] = { { PIN_FREE, 0, 1, TIMER_INTENSET_COMPARE1_Msk, 1 }, { PIN_FREE, 0, 2, TIMER_INTENSET_COMPARE2_Msk, 2 }, { PIN_FREE, 0, 3, TIMER_INTENSET_COMPARE3_Msk, 3 } }; -static int timerEnabled = 0; - -static uint32_t adcReference = ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling; -static uint32_t adcPrescaling = ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling; +struct PWMStatus pwmStatus[PWM_TIMER_COUNT] = {0, TIMER1_IRQn}; static uint32_t readResolution = 10; static uint32_t writeResolution = 8; @@ -229,7 +218,7 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) ulPin = g_ADigitalPinMap[ulPin]; - if (!timerEnabled) { + if (pwmStatus[0].numActive == 0) { NVIC_SetPriority(TIMER1_IRQn, 3); NVIC_ClearPendingIRQ(TIMER1_IRQn); NVIC_EnableIRQ(TIMER1_IRQn); @@ -245,8 +234,6 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Msk; NRF_TIMER1->TASKS_START = 0x1UL; - - timerEnabled = true; } for (int i = 0; i < PWM_COUNT; i++) { @@ -259,17 +246,25 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos); - ulValue = mapResolution(ulValue, writeResolution, 8); - pwmContext[i].value = ulValue; NRF_TIMER1->CC[pwmContext[i].channel] = ulValue; NRF_TIMER1->INTENSET = pwmContext[i].mask; - - break; + pwmStatus[0].numActive++; + return; } } + + // fallback to digitalWrite if no available PWM channel + if (ulValue < 128) + { + digitalWrite(ulPin, LOW); + } + else + { + digitalWrite(ulPin, LOW); + } } void TIMER1_IRQHandler(void) diff --git a/cores/nRF5/wiring_analog_nRF52.c b/cores/nRF5/wiring_analog_nRF52.c index b6999468..e62582f7 100644 --- a/cores/nRF5/wiring_analog_nRF52.c +++ b/cores/nRF5/wiring_analog_nRF52.c @@ -31,20 +31,19 @@ extern "C" { static uint32_t saadcReference = SAADC_CH_CONFIG_REFSEL_Internal; static uint32_t saadcGain = SAADC_CH_CONFIG_GAIN_Gain1_5; -#define PWM_COUNT 3 - -static NRF_PWM_Type* pwms[PWM_COUNT] = { +NRF_PWM_Type* pwms[PWM_COUNT] = { NRF_PWM0, NRF_PWM1, NRF_PWM2 }; -static uint32_t pwmChannelPins[PWM_COUNT] = { - 0xFFFFFFFF, - 0xFFFFFFFF, - 0xFFFFFFFF +struct PWMContext pwmContext[PWM_COUNT] = { + { PIN_FREE, 0 }, + { PIN_FREE, 0 }, + { PIN_FREE, 0 } }; -static uint16_t pwmChannelSequence[PWM_COUNT]; + +struct PWMStatus pwmStatus[PWM_TIMER_COUNT] = {0, 0}; static int readResolution = 10; static int writeResolution = 8; @@ -220,9 +219,9 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) ulPin = g_ADigitalPinMap[ulPin]; for (int i = 0; i < PWM_COUNT; i++) { - if (pwmChannelPins[i] == 0xFFFFFFFF || pwmChannelPins[i] == ulPin) { - pwmChannelPins[i] = ulPin; - pwmChannelSequence[i] = ulValue | bit(15); + if (pwmContext[i].pin == PIN_FREE || pwmContext[i].pin == ulPin) { + pwmContext[i].pin = ulPin; + pwmContext[i].value = ulValue; NRF_PWM_Type* pwm = pwms[i]; @@ -236,15 +235,25 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) pwm->COUNTERTOP = (1 << writeResolution) - 1; pwm->LOOP = 0; pwm->DECODER = ((uint32_t)PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | ((uint32_t)PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos); - pwm->SEQ[0].PTR = (uint32_t)&pwmChannelSequence[i]; + pwm->SEQ[0].PTR = (uint32_t)&(pwmContext[i].value); pwm->SEQ[0].CNT = 1; pwm->SEQ[0].REFRESH = 1; pwm->SEQ[0].ENDDELAY = 0; pwm->TASKS_SEQSTART[0] = 0x1UL; - - break; + pwmStatus[0].numActive++; + return; } } + + // fallback to digitalWrite if no available PWM channel + if (ulValue < 128) + { + digitalWrite(ulPin, LOW); + } + else + { + digitalWrite(ulPin, LOW); + } } #ifdef __cplusplus diff --git a/cores/nRF5/wiring_digital.c b/cores/nRF5/wiring_digital.c index 1d9c27fd..8b9df904 100644 --- a/cores/nRF5/wiring_digital.c +++ b/cores/nRF5/wiring_digital.c @@ -20,6 +20,13 @@ #include "nrf.h" #include "Arduino.h" +#include "wiring_private.h" + +extern struct PWMContext pwmContext[PWM_COUNT]; +extern struct PWMStatus pwmStatus[PWM_TIMER_COUNT]; +#ifdef NRF52 +extern NRF_PWM_Type* pwms[PWM_COUNT]; +#endif #ifdef __cplusplus extern "C" { @@ -86,18 +93,42 @@ void digitalWrite( uint32_t ulPin, uint32_t ulVal ) ulPin = g_ADigitalPinMap[ulPin]; + for (uint8_t i = 0; i < PWM_COUNT; i++) + { + if (pwmContext[i].pin == ulPin) + { + pwmContext[i].pin = PIN_FREE; + #ifdef NRF52 + // Disable the PWM + NRF_PWM_Type* pwm = pwms[i]; + pwm->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos); + #endif + pwmStatus[0].numActive--; + } + } + + #ifdef NRF51 + // Turn off the Timer if no pwm signals are allocated + for (uint8_t i = 0; i < PWM_TIMER_COUNT; i++) + { + if (pwmStatus[i].numActive == 0) + { + NVIC_ClearPendingIRQ(pwmStatus[i].irqNumber); + NVIC_DisableIRQ(pwmStatus[i].irqNumber); + } + } + #endif + switch ( ulVal ) { case LOW: NRF_GPIO->OUTCLR = (1UL << ulPin); - break ; + break; default: NRF_GPIO->OUTSET = (1UL << ulPin); - break ; + break; } - - return ; } int digitalRead( uint32_t ulPin ) diff --git a/cores/nRF5/wiring_private.h b/cores/nRF5/wiring_private.h index 1907c234..ff85af11 100644 --- a/cores/nRF5/wiring_private.h +++ b/cores/nRF5/wiring_private.h @@ -26,9 +26,26 @@ extern "C" { #endif - #include "wiring_constants.h" +#define PWM_COUNT 3 +#define PWM_TIMER_COUNT 1 // 3 channels of TIMER1 are used. TIMER2 also could be used for PWM +#define PIN_FREE 0xffffffff + +struct PWMContext { + uint32_t pin; + uint32_t value; + #ifdef NRF51 + uint32_t channel; + uint32_t mask; + uint32_t event; + #endif +}; + +struct PWMStatus { + int8_t numActive; + int8_t irqNumber; +}; #ifdef __cplusplus } // extern "C" diff --git a/platform.txt b/platform.txt index 8fc5e800..e5241f01 100644 --- a/platform.txt +++ b/platform.txt @@ -129,3 +129,27 @@ tools.openocd.erase.pattern= tools.openocd.bootloader.params.verbose=-d2 tools.openocd.bootloader.params.quiet=-d0 tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -f interface/{program.protocol}.cfg -c "{program.setup_command}" -f target/{upload.target}.cfg -c "init; halt; nrf51 mass_erase; program {{{runtime.platform.path}/cores/nRF5/SDK/components/softdevice/{softdevice}/hex/{softdevice}_{upload.target}_{softdeviceversion}_softdevice.hex}} verify reset; shutdown;" + +# +# blackmagic probe upload +# +tools.blackmagicprobe.path={runtime.tools.gcc-arm-none-eabi-5_2-2015q4.path}/bin/ +tools.blackmagicprobe.cmd=arm-none-eabi-gdb + +tools.blackmagicprobe.upload.speed=230400 + +tools.blackmagicprobe.erase.params.verbose= +tools.blackmagicprobe.erase.params.quiet=-q --batch-silent +tools.blackmagicprobe.erase.pattern="{path}{cmd}" -quiet -cd "{build.path}" -ex "target extended-remote \\.\{serial.port}" -ex "monitor swdp_scan" -ex "attach 1" -ex "monitor erase mass" -ex "echo \nErase finished!\n" -ex "detach" -ex "quit" + +tools.blackmagicprobe.upload.params.verbose= +tools.blackmagicprobe.upload.params.quiet=-q --batch-silent +tools.blackmagicprobe.upload.pattern="{path}{cmd}" -quiet -cd "{build.path}" -b {upload.speed} -l 10 -ex "set debug remote 0" -ex "set target-async off" -ex "set remotetimeout 10" -ex "set mem inaccessible-by-default off" -ex "set confirm off" -ex "set height 0" -ex "target extended-remote \\.\{serial.port}" -ex "monitor swdp_scan" -ex "attach 1" -ex "file {build.project_name}.elf" -ex "load" -ex "tbreak main" -ex "run" -ex "echo \nUpload complete!\n" -ex "quit" + +tools.blackmagicprobe.program.params.verbose= +tools.blackmagicprobe.program.params.quiet=-q --batch-silent +tools.blackmagicprobe.program.pattern="{path}{cmd}" -quiet -cd "{build.path}" -b {upload.speed} -l 10 -ex "set debug remote 0" -ex "set target-async off" -ex "set remotetimeout 10" -ex "set mem inaccessible-by-default off" -ex "set confirm off" -ex "set height 0" -ex "target extended-remote \\.\{serial.port}" -ex "monitor swdp_scan" -ex "attach 1" -ex "file {build.project_name}.elf" -ex "load" -ex "tbreak main" -ex "run" -ex "echo \nProgram complete!\n" -ex "quit" + +tools.blackmagicprobe.bootloader.params.verbose= +tools.blackmagicprobe.bootloader.params.quiet=-q --batch-silent +tools.blackmagicprobe.bootloader.pattern="{path}{cmd}" -quiet -cd "{runtime.platform.path}/cores/nRF5/SDK/components/softdevice/{softdevice}/hex/" -ex "target extended-remote \\.\{serial.port}" -ex "monitor swdp_scan" -ex "attach 1" -ex "monitor erase mass" -ex "load {softdevice}_{upload.target}_{softdeviceversion}_softdevice.hex" -ex "echo \nSoftdevice upload complete!\n" -ex "detach" -ex "quit" \ No newline at end of file diff --git a/programmers.txt b/programmers.txt index 45663a61..31aa30be 100644 --- a/programmers.txt +++ b/programmers.txt @@ -18,3 +18,13 @@ cmsisdap.protocol=cmsis-dap cmsisdap.program.protocol=cmsis-dap cmsisdap.program.tool=openocd cmsisdap.program.setup_command=; + +bmp.name=Black Magic Probe (GDB) +bmp.communication=USB +bmp.protocol= +bmp.program.protocol= +bmp.erase.tool=blackmagicprobe +bmp.upload.tool=blackmagicprobe +bmp.program.tool=blackmagicprobe +bmp.bootloader.tool=blackmagicprobe +bmp.program.extra_params=;