From cfe6b695340382f77307625b87869b2b43cbb92c Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Sat, 18 Jan 2020 20:56:08 +0000 Subject: [PATCH] boards/main: Enable the WDT and related entry modes --- src/boards.c | 30 ++++++++++++++++++++++++++++++ src/boards.h | 4 ++++ src/main.c | 28 +++++++++++++++++++--------- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/boards.c b/src/boards.c index 7ad305a..548fcaf 100644 --- a/src/boards.c +++ b/src/boards.c @@ -24,6 +24,7 @@ #include "boards.h" #include "nrf_pwm.h" +#include "nrf_wdt.h" #include "app_scheduler.h" #include "app_timer.h" @@ -126,12 +127,26 @@ void board_teardown(void) } static uint32_t _systick_count = 0; +static uint32_t _long_press_count = 0; void SysTick_Handler(void) { _systick_count++; #if LEDS_NUMBER > 0 led_tick(); #endif + + /* + * Detect a long press of the DFU button. When found try to launch the + * application regardless of the DFU button state. + */ + if (button_pressed(BUTTON_DFU)) { + if (_long_press_count++ > (2 * 1000)) { + NRF_POWER->GPREGRET = BOARD_MAGIC_FORCE_APP_BOOT; + NVIC_SystemReset(); + } + } else { + _long_press_count = 0; + } } @@ -453,3 +468,18 @@ void neopixel_write (uint8_t *pixels) led_pwm_duty_cycle(LED_RGB_BLUE, pixels[0]); } #endif + +void wdt_init(void) +{ + // 1 => keep running during a sleep, stop during SWD debug + nrf_wdt_behaviour_set(NRF_WDT, 1); + + // timeout after 5 seconds + nrf_wdt_reload_value_set(NRF_WDT, 5 * 32768); + + // enable the 0th channel + nrf_wdt_reload_request_enable(NRF_WDT, NRF_WDT_RR0); + + // set it running + nrf_wdt_task_trigger(NRF_WDT, NRF_WDT_TASK_START); +} diff --git a/src/boards.h b/src/boards.h index 28cc5c6..ac0a798 100644 --- a/src/boards.h +++ b/src/boards.h @@ -60,6 +60,8 @@ #define BOARD_RGB_BRIGHTNESS 0x101010 #endif +#define BOARD_MAGIC_FORCE_APP_BOOT 0x65 + // Helper function #define memclr(buffer, size) memset(buffer, 0, size) #define varclr(_var) memclr(_var, sizeof(*(_var))) @@ -106,6 +108,8 @@ bool button_pressed(uint32_t pin); bool is_ota(void); +void wdt_init(void); + //--------------------------------------------------------------------+ // DEBUG //--------------------------------------------------------------------+ diff --git a/src/main.c b/src/main.c index ec334a3..c854dcb 100644 --- a/src/main.c +++ b/src/main.c @@ -103,6 +103,7 @@ void usb_teardown(void); #define DFU_MAGIC_OTA_RESET 0xA8 #define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e #define DFU_MAGIC_UF2_RESET 0x57 +#define DFU_MAGIC_FORCE_APP_BOOT BOARD_MAGIC_FORCE_APP_BOOT // 0x65 #define DFU_DBL_RESET_MAGIC 0x5A1AD5 // SALADS #define DFU_DBL_RESET_DELAY 500 @@ -155,7 +156,9 @@ int main(void) bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM); // Start Bootloader in BLE OTA mode - _ota_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM) || (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_RESET); + _ota_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM) || + (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_RESET) || + (NRF_POWER->RESETREAS & NRF_POWER_RESETREAS_DOG_MASK); // Serial only mode bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET); @@ -164,8 +167,14 @@ int main(void) bool dfu_start = _ota_dfu || serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET) || (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)); + // override the button status (but not GPREGREG or RESETREAS) + bool force_app_boot = (NRF_POWER->GPREGRET == DFU_MAGIC_FORCE_APP_BOOT); + // Clear GPREGRET if it is our values - if (dfu_start) NRF_POWER->GPREGRET = 0; + if (dfu_start || force_app_boot) { + NRF_POWER->GPREGRET = 0; + nrf_power_resetreas_clear(NRF_POWER, NRF_POWER_RESETREAS_DOG_MASK); + } // Save bootloader version to pre-defined register, retrieved by application BOOTLOADER_VERSION_REGISTER = (MK_BOOTLOADER_VERSION); @@ -191,11 +200,14 @@ int main(void) /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ // DFU button pressed - dfu_start = dfu_start || button_pressed(BUTTON_DFU); + dfu_start = dfu_start || (!force_app_boot && button_pressed(BUTTON_DFU)); -#if BUTTONS_NUMBER > 1 +#if BUTTONS_NUMBER >= 2 // DFU + FRESET are pressed --> OTA _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; +#else + // No FRESET button so set OTA mode unless a magic reset requested serial mode + _ota_dfu = _ota_dfu || !serial_only_dfu; #endif bool const valid_app = bootloader_app_is_valid(DFU_BANK_0_REGION_START); @@ -222,11 +234,6 @@ int main(void) (*dbl_reset_mem) = 0; -#if BUTTONS_NUMBER < 2 - // set BLE/ota DFU by default unless asked for serial as we don't have button to select it - _ota_dfu = _ota_dfu || !serial_only_dfu; -#endif - if ( dfu_start || !valid_app ) { if ( _ota_dfu ) @@ -266,6 +273,9 @@ int main(void) // Jump to application if valid if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress()) { + // Set the watchdog running before we start the payload + wdt_init(); + // MBR must be init before start application if ( !sd_inited ) softdev_mbr_init();