This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE DFU WDT SDK15.2 bug?

Hi all

nrf52840 Development board,sdk is nRF5_SDK_15.2.0_9412b96,PC is windows 10 .My testing master device is cell phone(Huawei HTC and so on,android system),and using "nrf toolbox" APP.

I added watchdog  function in my application,and then when I test the ble dfu ,I found that  the watchdog feeding in the bootloader did not happen during app FW activation.

nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler);

wdt_feed_timer_handler is not called any time.Is this an SDK bug?

Thanks,

mijiale

The log as follosw:

  • Hi ,

    the WDT is started in the nrf_bootloader_init() function if dfu_enter is true. 

    void nrf_bootloader_wdt_init(void)
    {
        static bool initialized = false;
    
        if (initialized)
        {
            return;
        }
    
        if (nrf_wdt_started())
        {
            uint32_t wdt_ticks = nrf_wdt_reload_value_get();
    
            NRF_LOG_INFO("WDT enabled CRV:%d ticks", wdt_ticks);
    
            //wdt_ticks must be reduced to feed the watchdog before the timeout.
            uint32_t reduced_timeout_ticks = MAX((int32_t)wdt_ticks - MAX_FLASH_OP_TIME_TICKS,
                                                 NRF_BOOTLOADER_MIN_TIMEOUT_TICKS);
    
            /* initial watchdog feed */
            wdt_feed();
    
            NRF_LOG_INFO("Starting a timer (%d ticks) for feeding watchdog.", reduced_timeout_ticks);
            nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler);
    
            NVIC_EnableIRQ(WDT_IRQn);
        }
        else
        {
            NRF_LOG_INFO("WDT is not enabled");
        }
    
        initialized = true;
    }
    

    The WDT is also started prior to initiating any image_copy operation

    static uint32_t image_copy(uint32_t dst_addr,
                               uint32_t src_addr,
                               uint32_t size,
                               uint32_t progress_update_step)
    {
        if (src_addr == dst_addr)
        {
            NRF_LOG_DEBUG("No copy needed src_addr: 0x%x, dst_addr: 0x%x", src_addr, dst_addr);
            return NRF_SUCCESS;
        }
    
        ASSERT(src_addr >= dst_addr);
        ASSERT(progress_update_step > 0);
        ASSERT((dst_addr % CODE_PAGE_SIZE) == 0);
    
        uint32_t max_safe_progress_upd_step = (src_addr - dst_addr)/CODE_PAGE_SIZE;
        ASSERT(max_safe_progress_upd_step > 0);
    
        uint32_t ret_val = NRF_SUCCESS;
        uint32_t pages_left = CEIL_DIV(size, CODE_PAGE_SIZE);
    
        //Firmware copying is time consuming operation thus watchdog handling is started
        nrf_bootloader_wdt_init();
    
        progress_update_step = MIN(progress_update_step, max_safe_progress_upd_step);
    
        while (size > 0)
        {
            uint32_t pages;
            uint32_t bytes;
            if (pages_left <= progress_update_step)
            {
                pages = pages_left;
                bytes = size;
            }
            else
            {
                pages = progress_update_step;
                bytes = progress_update_step * CODE_PAGE_SIZE;
            }
            // Erase the target pages
            ret_val = nrf_dfu_flash_erase(dst_addr, pages, NULL);
            if (ret_val != NRF_SUCCESS)
            {
                return ret_val;
            }
    
            // Flash one page
            NRF_LOG_DEBUG("Copying 0x%x to 0x%x, size: 0x%x", src_addr, dst_addr, bytes);
            ret_val = nrf_dfu_flash_store(dst_addr,
                                          (uint32_t *)src_addr,
                                          ALIGN_NUM(sizeof(uint32_t), bytes),
                                          NULL);
            if (ret_val != NRF_SUCCESS)
            {
                return ret_val;
            }
    
            pages_left  -= pages;
            size        -= bytes;
            dst_addr    += bytes;
            src_addr    += bytes;
            s_dfu_settings.write_offset += bytes;
    
            //store progress in flash on every successful chunk write
            ret_val = nrf_dfu_settings_write_and_backup(NULL);
            if (ret_val != NRF_SUCCESS)
            {
                NRF_LOG_ERROR("Failed to write image copying progress to settings page.");
                return ret_val;
            }
        }
    
        return ret_val;
    }

    The image_copy() function is used by app_activate()

    static uint32_t app_activate(void)
    {
        // This function is only in use when new app is present in Bank 1
        uint32_t const image_size  = s_dfu_settings.bank_1.image_size;
    
        uint32_t src_addr    = s_dfu_settings.progress.update_start_address;
        uint32_t ret_val     = NRF_SUCCESS;
        uint32_t target_addr = nrf_dfu_bank0_start_addr() + s_dfu_settings.write_offset;
        uint32_t length_left = (image_size - s_dfu_settings.write_offset);
        uint32_t crc;
    
        NRF_LOG_DEBUG("Enter nrf_dfu_app_continue");
    
        src_addr += s_dfu_settings.write_offset;
    
        if (src_addr == target_addr)
        {
            length_left = 0;
        }
    
        ret_val = image_copy(target_addr, src_addr, length_left, NRF_BL_FW_COPY_PROGRESS_STORE_STEP);
        if (ret_val != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed to copy firmware.");
            return ret_val;
        }
    
        // Check the CRC of the copied data. Enable if so.
        crc = crc32_compute((uint8_t*)nrf_dfu_bank0_start_addr(), image_size, NULL);
    
        if (crc == s_dfu_settings.bank_1.image_crc)
        {
            NRF_LOG_DEBUG("Setting app as valid");
            s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_VALID_APP;
            s_dfu_settings.bank_0.image_crc = crc;
            s_dfu_settings.bank_0.image_size = image_size;
        }
        else
        {
            NRF_LOG_ERROR("CRC computation failed for copied app: "
                          "src crc: 0x%08x, res crc: 0x%08x",
                          s_dfu_settings.bank_1.image_crc,
                          crc);
        }
    
        return ret_val;
    }

    So the WDT should fire during the Application activation phase. The log you attached does not seem to be in the case, can you attach it again? Is the DFU update failing or does it go through with no errors or issues? If it is very small application then it could be that its written to flash before the WDT timer fires?

    Best regards

    Bjørn

  • wdt_feed_timer_handler is not called when in image_copy() 

  • nrf_bootloader_wdt_init() function is called twice

    The first is in nrf_bootloader_init() functon

    The second in image_copy() function

    I have test that the timeout of rtc timer can feed wdt when nrf_bootloader_wdt_init() function is called in  nrf_bootloader_init() functon

    But the timeout of rtc timer can not feed wdt when nrf_bootloader_wdt_init() function is called

    in  image_copy() function

  • wdt_feed_timer_handler() function is not called, This causes timeout for timer to reset the device

  • Can you add check if nrf_bootloader_wdt_init() called in image_copy() is returning due to it already being initialized, i.e. 

    if (initialized)
    {
         return;
    }

    if not then see if it enters the if (nrf_wdt_started()) statement or not, i.e. if the WDT is running or not. 

    The WDT is not reset by a SoftReset, i.e. SystemReset() so if the WDT was running in your application, then it should be active all the time. 

    You can also take a look at the RTC2 registers in the debug view to see if the RTC is configured correctly, this should be done in timer_init() which is called by timer_start which in turn is called by nrf_bootloader_wdt_feed_timer_start.

Related