nRF52840 ncs Watchdog resets

I have not been able to get the nRF52840 ncs v2.0.2 watchdog not to reset.

I tried kicking the watchdog every second and can set a break point and see that the kick does not return an error.

After a couple of minutes the board resets with the debugger with a reset pin error.

     [ami_main.c: 676] ResetCause:1

I tried using the both channel ids and also only the first channel.

   

//-----------------------------------------------------------------------------
// ami_main_RdClrReset
//  Description
//  b0-
//    RESETPIN Reset from pin-reset detected
//  b1-
//    DOG      Reset from watchdog detected
//  b2-
//    SREQ     Reset from soft reset detected
//  b3-
//    LOCKUP   Reset from CPU lock-up detected
//  Parameters
//  Returns
//-----------------------------------------------------------------------------
void ami_main_RdClrReset(void)
{
  gResetInfo = NRF_POWER->RESETREAS;
  NRF_POWER->RESETREAS = 0;
  if (gResetInfo & 0x02){
    atomic_set_bit(&avdFlags,AMI_BT_ADV_FLAGS_INDEX_WATCHDOG_ERR);
  }
} // ami_main_RdClrReset

//-----------------------------------------------------------------------------
// ami_main_SecHandler
//  Description
//
//  Parameters
//  Returns
//-----------------------------------------------------------------------------
void ami_main_SecHandler(struct k_work *work)
{
  static int  secs = 0;
#if CONFIG_WATCHDOG    
  //-------------------------------------------------------------------------
  // Kick watchdog
  //-------------------------------------------------------------------------
  ami_watchdog_feed();
#endif  
  //-------------------------------------------------------------------------
  // Another second has passed
  //-------------------------------------------------------------------------
  secsFrom2004.ulong++;

Here is my watchdog code:

/*
 * Copyright (c) 2015 Intel Corporation
 * Copyright (c) 2018 Nordic Semiconductor
 * Copyright (c) 2019 Centaur Analytics, Inc
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>
#include <drivers/watchdog.h>
#include <sys/printk.h>
#include <stdbool.h>
#include "d_printf.h"
#include "ami_watchdog.h"

#if CONFIG_WATCHDOG

#define USE_WATCHDOG_2ND_CHANNEL

static int wdt_channel_id1;
#ifdef USE_WATCHDOG_2ND_CHANNEL
static int wdt_channel_id2;
#endif

static const struct device *wdt;

static void wdt_callback(const struct device *wdt_dev, int channel_id)
{
	static bool handled_event = false;

	if (handled_event) {
		return;
	}
	wdt_feed(wdt_dev, channel_id);
	d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"Handled things..ready to reset");
	handled_event = true;
} // wdt_callback

void ami_watchdog_Init(void)
{
	int err;
	struct wdt_timeout_cfg wdt_config;

	wdt = device_get_binding("WDT");
	if (!wdt) {
		d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"Cannot get WDT device");
		return;
	}
	/* Reset SoC when watchdog timer expires. */
	wdt_config.flags = WDT_FLAG_RESET_SOC;
	/* Expire watchdog after 120000 milliseconds. */
	wdt_config.window.min = 0U;
	wdt_config.window.max = 120000U;
	/* Set up watchdog callback. Jump into it when watchdog expired. */
	wdt_config.callback = wdt_callback;
	wdt_channel_id1 = wdt_install_timeout(wdt, &wdt_config);
	if (wdt_channel_id1 == -ENOTSUP) {
		wdt_config.callback = NULL;
		wdt_channel_id1 = wdt_install_timeout(wdt, &wdt_config);
	}
	if (wdt_channel_id1 < 0) {
		d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"Watchdog install error");
		return;
	}
#ifdef USE_WATCHDOG_2ND_CHANNEL	
	wdt_channel_id2 = wdt_install_timeout(wdt, &wdt_config);
	if (wdt_channel_id1 == -ENOTSUP) {
		wdt_config.callback = NULL;
		wdt_channel_id2 = wdt_install_timeout(wdt, &wdt_config);
	}
	if (wdt_channel_id2 < 0) {
		d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"Watchdog install error");
		return;
	}
#endif	
	err = wdt_setup(wdt, 0);
	if (err < 0) {
		d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"Watchdog setup error");
		return;
	}

} // ami_watchdog_Init

void ami_watchdog_feed(void)
{
  int err = wdt_feed(wdt, wdt_channel_id1);
  if (err){
	d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"WDT#1 FeedErr:",err);
  }
#ifdef USE_WATCHDOG_2ND_CHANNEL	  
  err = wdt_feed(wdt, wdt_channel_id2);
  if (err){
	d_printf(LINE_INFO,kDbg_Error|kDbg_Display,"WDT#2 FeedErr:",err);
  }
#endif  
} // ami_watchdog_feed

#endif

Also another question:

I use in production the nRF52 SDK Soft device in my previous Central project.

I used the serial Nordic DFU protocol to upgrade the Central's code from our host.

I did not see any bootloader in the nRF52840's pdf, so I must use the SMP protocol or do things myself with the Zephyr code?

I think I saw mcu boot serial update somewhere.

Thanks David

  • Hi,

    I do not see enough of your code to be sure that you are seeing a WDT reset. Have you confirmed that? I ask as you print ResetCause:1, and if that means that RESETREAS is 1, that is pinreset. Perhaps you can explain where this number comes from?

    Regarding the WDT code snippets you have include that looks sensible (though I do not have a full overview of the other code and I might have overlooked something) It looks like you have based it on the Watchdog Driver Sample, which is a sensible starting point, and this runs out of the box on a nRF52840 DK.

    I did not see any bootloader in the nRF52840's pdf, so I must use the SMP protocol or do things myself with the Zephyr code?

    We provide DFU capability in the nRF Connect SDK as well, based on the MCUboot bootloader. You can read more about it under Bootloaders and Device Firmware Updates. You may also find these unofficial bootloader samples useful.

  • Thanks for your quick response.

    I could see when I connect BLE to the peripheral, that my seconds variable increments every second, so the watchdog kick is being called.
    After looking at the watchdog sample, I saw that the watchdog options parameter was set for debug.

    I was also calling my ami_watchdog_Init() function twice in my initialization proceed by mistake which could be the real reason for the resets (I do not know since I did not investigate the Zephyr Nordic code).

    After these changes, the peripheral does not reset with the debugger connected.

    I will test it without the debugger and also in my Central code which had the same mistakes.

        err = wdt_setup(wdt,WDT_OPT_PAUSE_HALTED_BY_DBG);
    About the DFU, I can see that it looks like it uses ZCBOR & SMP which greatly complicates my Central's host code which is currently not a Nordic chip.
    Thank you again, David
  • Hi,

    Good to hear about the WDT issue.

    Regarding DFU, I see your point, but that is what we provide. Note that a colleague of mine is also working on a unofficial SMP client to do DFU from an MCU, which you can look at: central_smp_client_dfu. I suggest opening a new case for DFU if needed though.

Related