use PWM0 & PWM1 for led blinky fix #14

This commit is contained in:
hathach 2018-08-14 00:56:51 +07:00
parent 1c2911a63c
commit 4eee219b5a
2 changed files with 111 additions and 79 deletions

View File

@ -117,7 +117,7 @@ static void forced_startup_dfu_timer_handler(void * p_context)
*/ */
static void wait_for_events(void) static void wait_for_events(void)
{ {
for (;;) for ( ;; )
{ {
// Wait in low power state for any events. // Wait in low power state for any events.
// uint32_t err_code = sd_app_evt_wait(); // uint32_t err_code = sd_app_evt_wait();
@ -127,20 +127,24 @@ static void wait_for_events(void)
app_sched_execute(); app_sched_execute();
#ifdef NRF52840_XXAA #ifdef NRF52840_XXAA
// usb is not enabled in OTA
if ( !is_ota() )
{
tusb_task(); tusb_task();
tud_cdc_write_flush(); tud_cdc_write_flush();
}
#endif #endif
if ((m_update_status == BOOTLOADER_COMPLETE) || if ((m_update_status == BOOTLOADER_COMPLETE) ||
(m_update_status == BOOTLOADER_TIMEOUT) || (m_update_status == BOOTLOADER_TIMEOUT) ||
(m_update_status == BOOTLOADER_RESET)) (m_update_status == BOOTLOADER_RESET) )
{ {
// When update has completed or a timeout/reset occured we will return. // When update has completed or a timeout/reset occured we will return.
return; return;
} }
// Forced startup dfu mode timeout without any received packet // Forced startup dfu mode timeout without any received packet
if (_terminate_startup_dfu) return; if ( _terminate_startup_dfu ) return;
} }
} }

View File

@ -34,6 +34,7 @@
#include "nrfx.h" #include "nrfx.h"
#include "nrfx_power.h" #include "nrfx_power.h"
#include "nrfx_pwm.h"
#include "nordic_common.h" #include "nordic_common.h"
#include "sdk_common.h" #include "sdk_common.h"
@ -124,9 +125,14 @@ STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
void adafruit_factory_reset(void); void adafruit_factory_reset(void);
/*
// Adafruit for Blink pattern * Blinking patterns:
bool _fast_blink = false; * - DFU Serial : LED Status blink
* - DFU OTA : LED Status & Conn blink at the same time
* - DFU Flashing : LED Status blink 2x fast
* - Factory Reset : LED Status blink 2x fast
* - Fatal Error : LED Status & Conn blink one after another
*/
bool _ota_connected = false; bool _ota_connected = false;
// true if ble, false if serial // true if ble, false if serial
@ -134,55 +140,68 @@ bool _ota_update = false;
bool is_ota(void) { return _ota_update; } bool is_ota(void) { return _ota_update; }
#define PWM_MAXCOUNT 25000
uint16_t _pwm_red_seq0 [NRF_PWM_CHANNEL_COUNT] = { PWM_MAXCOUNT/2, 0, 0 , 0 };
/* uint16_t _pwm_blue_seq0[NRF_PWM_CHANNEL_COUNT] = { PWM_MAXCOUNT/2, 0, 0 , 0 };
* Blinking function, there are a few patterns
* - DFU Serial : LED Status blink
* - DFU OTA : LED Status & Conn blink at the same time
* - DFU Flashing : LED Status blink 2x fast
* - Factory Reset : LED Status blink 2x fast
* - Fatal Error : LED Status & Conn blink one after another
*/
static void blinky_handler(void)
{
static uint8_t state = 0;
static uint32_t count = 0;
count++;
// if not uploading then blink slow (interval/2)
if ( !_fast_blink && count%2 ) return;
state = 1-state;
led_control(LED_RED, state);
// Blink LED BLUE if OTA mode and not connected
if (is_ota() && !_ota_connected)
{
led_control(LED_BLUE, state);
}
// Feed all Watchdog just in case application enable it (WDT last through a jump from application to bootloader)
if ( nrf_wdt_started() )
{
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(i);
}
}
void SysTick_Handler(void)
{
blinky_handler();
}
void led_blink_fast(bool enable) void led_blink_fast(bool enable)
{ {
_fast_blink = enable; if ( enable )
{
NRF_PWM0->MODE = PWM_MODE_UPDOWN_Up;
}else
{
NRF_PWM0->MODE = PWM_MODE_UPDOWN_UpAndDown;
}
}
/* use PWM for blinky to prevent inconsistency due to MCU blocking in flash operation
* clock = 125khz --> resolution = 8us
* top value = 25000 -> period = 200 ms (fast blink) --> up and down mode = 400 ms ( slow blink )
*/
void led_pwm_init(NRF_PWM_Type* pwm, uint32_t led_pin)
{
pwm->MODE = PWM_MODE_UPDOWN_UpAndDown;
pwm->COUNTERTOP = PWM_MAXCOUNT;
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_128;
pwm->DECODER = PWM_DECODER_LOAD_Individual;
pwm->LOOP = 0;
pwm->SEQ[0].PTR = (uint32_t) (led_pin == LED_RED ? _pwm_red_seq0 : _pwm_blue_seq0);
pwm->SEQ[0].CNT = NRF_PWM_CHANNEL_COUNT; // default mode is Individual --> count must be 4
pwm->SEQ[0].REFRESH = 0;
pwm->SEQ[0].ENDDELAY = 0;
pwm->PSEL.OUT[0] = led_pin;
pwm->ENABLE = 1;
pwm->TASKS_SEQSTART[0] = 1;
}
void led_pwm_teardown(NRF_PWM_Type* pwm)
{
pwm->TASKS_SEQSTART[0] = 0;
pwm->ENABLE = 0;
pwm->PSEL.OUT[0] = 0xFFFFFFFF;
pwm->MODE = 0;
pwm->COUNTERTOP = 0x3FF;
pwm->PRESCALER = 0;
pwm->DECODER = 0;
pwm->LOOP = 0;
pwm->SEQ[0].PTR = 0;
pwm->SEQ[0].CNT = 0;
} }
void board_init(void) void board_init(void)
{ {
// stop WDT if started by application, when jumping from application using BLE DFU
if ( NRF_WDT->RUNSTATUS )
{
NRF_WDT->TASKS_START = 0;
}
button_init(BUTTON_DFU); button_init(BUTTON_DFU);
button_init(BUTTON_FRESET); button_init(BUTTON_FRESET);
NRFX_DELAY_US(100); // wait for the pin state is stable NRFX_DELAY_US(100); // wait for the pin state is stable
@ -193,21 +212,19 @@ void board_init(void)
led_off(LED_RED); led_off(LED_RED);
led_off(LED_BLUE); led_off(LED_BLUE);
// use PMW0 for LED RED
led_pwm_init(NRF_PWM0, LED_RED);
// Init scheduler // Init scheduler
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
// Init app timer (use RTC1)
app_timer_init();
// Configure Systick for led blinky
extern uint32_t SystemCoreClock;
SysTick_Config(SystemCoreClock/(1000/LED_BLINK_INTERVAL));
} }
void board_teardown(void) void board_teardown(void)
{ {
// Disable systick, turn off LEDs // Disable and reset PWM for LED
SysTick->CTRL = 0; led_pwm_teardown(NRF_PWM0);
if ( is_ota() ) led_pwm_teardown(NRF_PWM1);
led_off(LED_BLUE); led_off(LED_BLUE);
led_off(LED_RED); led_off(LED_RED);
@ -235,7 +252,7 @@ void softdev_mbr_init(void)
* be initialized if a chip reset has occured. Soft reset (jump ) from * be initialized if a chip reset has occured. Soft reset (jump ) from
* application must not reinitialize the SoftDevice. * application must not reinitialize the SoftDevice.
*/ */
uint32_t softdev_init(bool init_softdevice) static uint32_t softdev_init(bool init_softdevice)
{ {
if (init_softdevice) softdev_mbr_init(); if (init_softdevice) softdev_mbr_init();
@ -339,14 +356,25 @@ int main(void)
if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) )
{ {
// Enable BLE if in OTA
if ( _ota_update ) if ( _ota_update )
{ {
// Enable BLE if in OTA
led_pwm_init(NRF_PWM1, LED_BLUE);
softdev_init(!sd_inited); softdev_init(!sd_inited);
sd_inited = true; sd_inited = true;
}
// Init app timer (use RTC1)
app_timer_init();
}
else
{
// Init app timer (use RTC1)
app_timer_init();
// otherwise USB for Serial & UF2
usb_init(); usb_init();
}
// Initiate an update of the firmware. // Initiate an update of the firmware.
APP_ERROR_CHECK( bootloader_dfu_start(_ota_update, 0) ); APP_ERROR_CHECK( bootloader_dfu_start(_ota_update, 0) );
@ -453,12 +481,12 @@ uint32_t proc_ble(void)
{ {
case BLE_GAP_EVT_CONNECTED: case BLE_GAP_EVT_CONNECTED:
_ota_connected = true; _ota_connected = true;
led_on(LED_BLUE); _pwm_blue_seq0[0] = PWM_MAXCOUNT;
break; break;
case BLE_GAP_EVT_DISCONNECTED: case BLE_GAP_EVT_DISCONNECTED:
_ota_connected = false; _ota_connected = false;
led_off(LED_BLUE); _pwm_blue_seq0[0] = PWM_MAXCOUNT/2;
break; break;
default: break; default: break;