DFU target library and task WDT not work together

Hi,

I work on a project that uses the dfu target library for firmware updates. This has been working flawless until I added task watchdogs.

The problem that I see is that after a task wdt has been added, the dfu_target_mcuboot_write causes the zephyr system to reboot. Through debugging I see that it happens when the first page in flash is erased. If i disable the task wdt add function, I see no problems.

More information:

  • I have tried to use a long timeout and regularly feed the watchdog to ensure that it is not the reason why the reboot occur.
  • I have tried to call the task wdt delete function before the dfu_target_mcuboot_write function but this still reboots the system.
  • SDK 1.8.0 
Parents Reply Children
  • 200s (normally 20s) changing the timeout has no impact on when the reset occurs.

    I have added a task watchdog for each thread, feeding it regulary with half the frequence of the timeout period.

    I use it on 7 threads, but have also tried with just 1.

    I have a WDT callback which does not get triggered. It is a zephyr hard fault that causes the reboot.

    I don't think it is a wdt reset, but the use of a task wdt that causes the flash erase function to reset the system.

  • Hi,

    I see. Can you enable logging (if not allready) and show what is printed when the fault occurs, before the reset? Can you share a minimal example that reproduce the issue on a DK?

  • /*
     * Copyright (c) 2020 Libre Solar Technologies GmbH
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <device.h>
    #include <drivers/watchdog.h>
    #include <sys/reboot.h>
    #include <task_wdt/task_wdt.h>
    #include <sys/printk.h>
    #include <stdbool.h>
    #include <dfu/dfu_target_mcuboot.h>
    
    /*
     * To use this sample, either the devicetree's /aliases must have a
     * 'watchdog0' property, or one of the following watchdog compatibles
     * must have an enabled node.
     *
     * If the devicetree has a watchdog node, we get the watchdog device
     * from there. Otherwise, the task watchdog will be used without a
     * hardware watchdog fallback.
     */
    #if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay)
    #define WDT_NODE DT_ALIAS(watchdog0)
    #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_window_watchdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_window_watchdog)
    #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_watchdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_watchdog)
    #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_watchdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nordic_nrf_watchdog)
    #elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_watchdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(espressif_esp32_watchdog)
    #elif DT_HAS_COMPAT_STATUS_OKAY(silabs_gecko_wdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(silabs_gecko_wdog)
    #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_wdog32)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_kinetis_wdog32)
    #elif DT_HAS_COMPAT_STATUS_OKAY(microchip_xec_watchdog)
    #define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(microchip_xec_watchdog)
    #endif
    
    uint8_t buf[244] = {0};
    
    static void task_wdt_callback(int channel_id, void *user_data)
    {
    	printk("Task watchdog channel %d callback, thread: %s\n",
    		channel_id, k_thread_name_get((k_tid_t)user_data));
    
    	/*
    	 * If the issue could be resolved, call task_wdt_feed(channel_id) here
    	 * to continue operation.
    	 *
    	 * Otherwise we can perform some cleanup and reset the device.
    	 */
    
    	printk("Resetting device...\n");
    
    	sys_reboot(SYS_REBOOT_COLD);
    }
    
    void main(void)
    {
    #ifdef WDT_NODE
    	const struct device *hw_wdt_dev = DEVICE_DT_GET(WDT_NODE);
    #else
    	const struct device *hw_wdt_dev = NULL;
    #endif
    
    	printk("Task watchdog sample application.\n");
    
    	if (!device_is_ready(hw_wdt_dev)) {
    		printk("Hardware watchdog %s is not ready; ignoring it.\n",
    		       hw_wdt_dev->name);
    		hw_wdt_dev = NULL;
    	}
    
    	task_wdt_init(hw_wdt_dev);
    
    	/* passing NULL instead of callback to trigger system reset */
    	int task_wdt_id = task_wdt_add(1100U, NULL, NULL);
    
    	while (true) {
    		printk("Main thread still alive...\n");
    		task_wdt_feed(task_wdt_id);
    		k_sleep(K_MSEC(1000));
    	}
    }
    
    /*
     * This high-priority thread needs a tight timing
     */
    void control_thread(void)
    {
    	int task_wdt_id;
    	int count = 0;
    
    	printk("Control thread started.\n");
    
    	uint8_t imageData[244] = {5};
    
    	dfu_target_mcuboot_set_buf(buf, sizeof(buf));
    	dfu_target_mcuboot_init(10000, NULL);
    	// Works if below is removed
    	dfu_target_mcuboot_write(imageData, sizeof(imageData));
    
    	printk("We did it!\n");
    
    	while(1);
    
    	// /*
    	//  * Add a new task watchdog channel with custom callback function and
    	//  * the current thread ID as user data.
    	//  */
    	// task_wdt_id = task_wdt_add(10000U, task_wdt_callback,
    	// 	(void *)k_current_get());
    		
    
    	// while (true) {
    	// 	if (count == 50) {
    	// 		printk("Control thread getting stuck...\n");
    	// 		k_sleep(K_FOREVER);
    	// 	}
    
    	// 	task_wdt_feed(task_wdt_id);
    	// 	k_sleep(K_MSEC(50));
    	// 	count++;
    	// }
    }
    
    K_THREAD_DEFINE(control, 1024, control_thread, NULL, NULL, NULL, 5, 0, 1000);
    

  • CONFIG_LOG=y
    
    CONFIG_WATCHDOG=y
    CONFIG_WDT_LOG_LEVEL_DBG=y
    CONFIG_WDT_DISABLE_AT_BOOT=y
    
    CONFIG_TASK_WDT=y
    CONFIG_TASK_WDT_MIN_TIMEOUT=100
    
    # Ensure an MCUboot-compatible binary is generated.
    CONFIG_FLASH=y
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_IMG_MANAGER=y
    CONFIG_THREAD_NAME=y
    CONFIG_DFU_TARGET=y
    CONFIG_DFU_TARGET_MCUBOOT=y
    CONFIG_STREAM_FLASH_ERASE=y

  • Thanks, I will look at it.

    In the mean time, I must admit I do not see the benefit on the task WDT on nRF HW, at lest for most projects, as the hardware WDT support multiple channels. May I ask why you are using it?

Related