Hi all,
I am using a nRF52840 with SDK v16.0 on SES. I am trying to understand the flow of code in the secure Booloader(/SDK_v16\examples\dfu\secure_bootloader\pca10056_s140_ble\ses\)
I have a application with buttonless DFU implemented. Application also has a watchdog timer which will check and reset the device every 120seconds if there is a software fault. An app_timer feeds the device every 100seconds to prevent the reset. I am able to do DFU OTA without any issues on the bootloader hex file generated via the normal unedited secure Bootloader project. In the app, I also have connected an external button to soft reset the device when it is pressed via sd_nvic_SystemReset()
I came to know that Bootloader needs to be also edited to implement WDT. This is where my troubles start. I added the following lines of code to the secure bootloader in the main.c right after the NRF_LOG_INFO("Inside main") and WATCHDOG_TIMER_DELAY_MS is set to 120000 (For 120 second timeout). (I have attached the main.c for reference)
// WDT Block Begin uint64_t ticks = (WATCHDOG_TIMER_DELAY_MS * 32768ULL) / 1000; NRFX_ASSERT(ticks <= UINT32_MAX); NRF_WDT->CRV = (uint32_t) ticks; // Initial loading of the watchdog timer nrf_bootloader_wdt_init(); // WDT Block End
Once I compile and generate the hex file and program the device with the new bootloader something weird is happening.
First time when I reset device via the external button, the watchdog timer is resetting the device after exactly 220seconds(100 +120) and only once. After this WDT doesnt trigger and the value is reset by the app_timer and application functions normally. Only when its reset(or power on bootup first time)WDT resets the device and then everything goes back to normal. This issue is only there when I use the edited bootloader with WDT code, functions fine with the normal bootloader hex file. Hence I suspecting that WDT code in my bootloader is the culprit.
1. Can anyone help in figuring out what seems to the bug which is causing the device to get reset once?
2. Will someone be able to explain the code flow for the bootloader? I mean how does the bootloader transfer the control to app and how does WDT work in between?
Thanking you in advance.
/** * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** @file * * @defgroup bootloader_secure_ble main.c * @{ * @ingroup dfu_bootloader_api * @brief Bootloader project main file for secure DFU. * */ #include <stdint.h> #include "boards.h" #include "nrf_mbr.h" #include "nrf_bootloader.h" #include "nrf_bootloader_app_start.h" #include "nrf_bootloader_dfu_timers.h" #include "nrf_dfu.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "app_error.h" #include "app_error_weak.h" #include "nrf_bootloader_info.h" #include "nrf_delay.h" // WDT Begin #include "nrf_bootloader_wdt.h" #define WATCHDOG_TIMER_DELAY_MS 120000 // Watchdog will reset the device every this delay as long as its not reloaded. In Milliseconds. // WDT End static void on_error(void) { NRF_LOG_FINAL_FLUSH(); #if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) // To allow the buffer to be flushed by the host. nrf_delay_ms(100); #endif #ifdef NRF_DFU_DEBUG_VERSION NRF_BREAKPOINT_COND; #endif NVIC_SystemReset(); } void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { NRF_LOG_ERROR("%s:%d", p_file_name, line_num); on_error(); } void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { NRF_LOG_ERROR("Received a fault! id: 0x%08x, pc: 0x%08x, info: 0x%08x", id, pc, info); on_error(); } void app_error_handler_bare(uint32_t error_code) { NRF_LOG_ERROR("Received an error: 0x%08x!", error_code); on_error(); } /** * @brief Function notifies certain events in DFU process. */ static void dfu_observer(nrf_dfu_evt_type_t evt_type) { switch (evt_type) { case NRF_DFU_EVT_DFU_FAILED: case NRF_DFU_EVT_DFU_ABORTED: case NRF_DFU_EVT_DFU_INITIALIZED: bsp_board_init(BSP_INIT_LEDS); bsp_board_led_on(BSP_BOARD_LED_0); bsp_board_led_on(BSP_BOARD_LED_1); bsp_board_led_off(BSP_BOARD_LED_2); break; case NRF_DFU_EVT_TRANSPORT_ACTIVATED: bsp_board_led_off(BSP_BOARD_LED_1); bsp_board_led_on(BSP_BOARD_LED_2); break; case NRF_DFU_EVT_DFU_STARTED: break; default: break; } } /**@brief Function for application main entry. */ int main(void) { uint32_t ret_val; // Must happen before flash protection is applied, since it edits a protected page. nrf_bootloader_mbr_addrs_populate(); // Protect MBR and bootloader code from being overwritten. ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE, false); APP_ERROR_CHECK(ret_val); ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE, false); APP_ERROR_CHECK(ret_val); (void) NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("Inside main"); // WDT Block Begin uint64_t ticks = (WATCHDOG_TIMER_DELAY_MS * 32768ULL) / 1000; NRFX_ASSERT(ticks <= UINT32_MAX); //nrf_wdt_reload_value_set((uint32_t) ticks); NRF_WDT->CRV = (uint32_t) ticks; // Initial loading of the watchdog timer nrf_bootloader_wdt_init(); // WDT Block End ret_val = nrf_bootloader_init(dfu_observer); APP_ERROR_CHECK(ret_val); NRF_LOG_FLUSH(); NRF_LOG_ERROR("After main, should never be reached."); NRF_LOG_FLUSH(); APP_ERROR_CHECK_BOOL(false); } /** * @} */