Can't enable Watchdog on nrf52840

Hello everyone!

I am having linker issues when compiling my code with a Watchdog.
I am using the target nRF52840_DK.

This is my mbed_app.json file:

{
    "target_overrides": {
      "*": {
        "target.mbed_app_start": "0x27000",
        "target.mbed_app_size": "0xC6000",
        "target.bootloader_img": null,
        "target.macros_add": ["DEVICE_WATCHDOG"]
      }
    }
}

As I understand, I need to define "DEVICE_WATCHDOG" but I might be mistaken. If I don’t define it, I get compiler errors. With the configuration shown above, I get the following linker errors:

    Error: L6218E: Undefined symbol nrfx_wdt_channel_alloc (referred from BUILD/NRF52840_DK/ARMC6/mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/watchdog_api.o).
    Error: L6218E: Undefined symbol nrfx_wdt_enable (referred from BUILD/NRF52840_DK/ARMC6/mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/watchdog_api.o).
    Error: L6218E: Undefined symbol nrfx_wdt_feed (referred from BUILD/NRF52840_DK/ARMC6/mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/watchdog_api.o).
    Error: L6218E: Undefined symbol nrfx_wdt_init (referred from BUILD/NRF52840_DK/ARMC6/mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/watchdog_api.o).

For reference, this is my main.cpp code:

#include <mbed.h>
#include "MainController.h"
#include "Configuration.h"
#include "BLE.h"

static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE);
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context);

int main(){
    Watchdog &watchdog = Watchdog::get_instance();
    loglnInfo("WDT max: %d\n", Watchdog::get_instance().get_max_timeout());

    BLE &ble = BLE::Instance();
    MainController m(ble, event_queue);
    ble.onEventsToProcess(schedule_ble_events); 
    return 0;
}

/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context){
    event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents)); 
}

Am I missing something? Is this a bug?
Any input is greatly appreciated!

Bruno

Hello @brunoinuggi
currently I’m working with nrf52840 using mbed OS 5.14 and i got the same problem, which i cannot use watchdog using mbed OS API. So after i check in target.json file in mbed-os/target folder.
Especially in NRF52840_DK section which inherits all config from MCU_NRF52840. which looks like this:

  "device_has": [
            "ANALOGIN",
            "FLASH",
            "I2C",
            "I2C_ASYNCH",
            "INTERRUPTIN",
            "ITM",
            "LPTICKER",
            "PORTIN",
            "PORTINOUT",
            "PORTOUT",
            "PWMOUT",
            "SERIAL",
            "SERIAL_ASYNCH",
            "SERIAL_FC",
            "SLEEP",
            "SPI",
            "SPI_ASYNCH",
            "SYSTICK_CLK_OFF_DURING_SLEEP",
            "TRNG",
            "USTICKER",
            "QSPI",
            "USBDEVICE"
        ],

from above config, we could see that currently there is no porting to access watchdog from SDK_15 Nordic, so you can manually enable them.
Here you can try this method to enable the watchdog function from SDK_15 Nordic (fyi this SDK_15 module already included in mbed-os, so we don’t need to download another one from nordic):

  1. enabling the watchdog function in sdk_config.h that locate in mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/config/sdk_config.h
    first, search this line
// <e> NRFX_WDT_ENABLED - nrfx_wdt - WDT peripheral driver
//==========================================================
#ifndef NRFX_WDT_ENABLED
#define NRFX_WDT_ENABLED 0
#endif

the default value from mbed-os 5.14 for NRFX_WDT_ENABLED macro is 0 (Zero) so you need to change it to 1 (One) to enable the wdt function

  1. include the wdt header file
#include "mbed.h"      // mbed os header file
#include "nrfx_wdt.h" // wdt header file
  1. you can configure your watchdog with this code
int main(void) {
    /* watchdog init */
    nrfx_wdt_config_t config;                        
    config.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT; 
    config.reload_value = 5000;                         
    config.interrupt_priority = 7;                        
    nrfx_wdt_init(&config, wdt_event_handler);
    nrfx_wdt_channel_alloc(&m_channel_id);
    /* start watchdog */
    nrfx_wdt_enable();
    . . . }

well, here some explanation i got from their documentation
-> the config.behaviour set the watchdog operates at, here i choose NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT to run on sleep and halt mode. (because i don’t really understand both mode, so i choose both of them, because i just want to access the wdt first before going deeper into it).
-> the config.reload_value is how long your time out will be, the value type is uint32_t in micro second
-> the config.interrupt_priority is uint8_t type, ranges from 0-7, with 0 is the highest priority
-> the nrfx_wdt_init takes nrfx_wdt_config_t as parameter, and a function handler
-> the nrfx_wdt_channel_alloc takes pointer of nrfx_wdt_channel_id as parameter
-> and last the nrfx_wdt_enable which start the watchdog

  1. Feed the wathcdog with this line
        /*  feed the watchdog to corresponding channel*/
        nrfx_wdt_channel_feed(m_channel_id);
  1. for reference this is my full code
/* native mbed lib */
#include "mbed.h"
#include "nrfx_wdt.h"

/* Channel id object */
nrfx_wdt_channel_id m_channel_id;

/**
 * @brief WDT events handler.
 */
void wdt_event_handler(void) {
    //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
}

int main(void) {
    /* watchdog init */
    nrfx_wdt_config_t config;
    config.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT;
    config.reload_value = 5000;
    config.interrupt_priority = 7;
    nrfx_wdt_init(&config, wdt_event_handler);
    nrfx_wdt_channel_alloc(&m_channel_id);
    /* start watchdog */
    nrfx_wdt_enable();

    while (true) {
        /*  feed the watchdog to corresponding channel*/
        nrfx_wdt_channel_feed(m_channel_id);

        wait_us(1000000);
    }
}

NOTE
and this is my mbed_app.json

{
	"target_overrides": {
        "*": {
            "target.lf_clock_src" : "NRF_LF_SRC_RC"
        }
    }
}

my mbed_app.json file just config about clock that used in system

You can search the function documentation in the header file and nordic sdk15 example wdt documentation
mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_15_0/modules/nrfx/drivers/include/nrfx_wdt.h
mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_15_0/modules/nrfx/hal/nrf_wdt.h
https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/ -> download link

hope this will help you sort out the problem

1 Like

Hi @ilhamidin!

Thank you so much for the very detailed explanation!
I am working on other things at the moment but I’ll make sure to test this approach and report back here.

Thanks again!
Bruno