Softdevice - WDT event not occurring when it hangs

Hello,

I am using nRF52833 based BE33 (Celium Devices) and using nRF52SDK17.0.2. I am trying to implement WDT and expecting to occur its event when the module becomes hang or any unexpected error occurred. I am purposely written the code where BLE is advertising and after every 1 second I am trying to update BLE advertise data below is the code that does this.

void advertising_update(uint8_t loadcellnumber,uint8_t loadcell_data[])
{
uint32_t err;
  err=  sd_ble_gap_adv_stop(m_advertising.adv_handle);
    APP_ERROR_CHECK(err);
    switch(loadcellnumber){
    case 1:{
      loadcellData[0]=loadcell_data[0];
      loadcellData[1]=loadcell_data[1];
      loadcellData[2]=loadcell_data[2];
      loadcellData[3]=loadcell_data[3];
      break;
      }
    case 2:{
      loadcellData[4]=loadcell_data[0];
      loadcellData[5]=loadcell_data[1];
      loadcellData[6]=loadcell_data[2];
      loadcellData[7]=loadcell_data[3];
      break;
      }
    case 3:{
      loadcellData[8]=loadcell_data[0];
      loadcellData[9]=loadcell_data[1];
      loadcellData[10]=loadcell_data[2];
      loadcellData[11]=loadcell_data[3];
      break;
      }
   }

advertising_init();
advertising_start();
}

WDT code in main.c

#include "nrf_drv_wdt.h"
nrf_drv_wdt_channel_id m_channel_id;

int main(void)
{

//Configure WDT.
    nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
    APP_ERROR_CHECK(err_code);
    nrf_drv_wdt_enable();
    
    
for (;;)
   {
       idle_state_handle();
       nrf_drv_wdt_feed();
   }
}

I have added below in sdk_config.h file:

// <e> NRFX_WDT_ENABLED - nrfx_wdt - WDT peripheral driver
//==========================================================
#ifndef NRFX_WDT_ENABLED
#define NRFX_WDT_ENABLED 1
#endif
// <o> NRFX_WDT_CONFIG_BEHAVIOUR  - WDT behavior in CPU SLEEP or HALT mode
 
// <1=> Run in SLEEP, Pause in HALT 
// <8=> Pause in SLEEP, Run in HALT 
// <9=> Run in SLEEP and HALT 
// <0=> Pause in SLEEP and HALT 

#ifndef NRFX_WDT_CONFIG_BEHAVIOUR
#define NRFX_WDT_CONFIG_BEHAVIOUR 1
#endif

// <o> NRFX_WDT_CONFIG_RELOAD_VALUE - Reload value in ms  <1-131072000> 


#ifndef NRFX_WDT_CONFIG_RELOAD_VALUE
#define NRFX_WDT_CONFIG_RELOAD_VALUE 20000
#endif

// <o> NRFX_WDT_CONFIG_NO_IRQ  - Remove WDT IRQ handling from WDT driver
 
// <0=> Include WDT IRQ handling 
// <1=> Remove WDT IRQ handling 

#ifndef NRFX_WDT_CONFIG_NO_IRQ
#define NRFX_WDT_CONFIG_NO_IRQ 0
#endif

// <o> NRFX_WDT_CONFIG_IRQ_PRIORITY  - Interrupt priority
 
// <0=> 0 (highest) 
// <1=> 1 
// <2=> 2 
// <3=> 3 
// <4=> 4 
// <5=> 5 
// <6=> 6 
// <7=> 7 

#ifndef NRFX_WDT_CONFIG_IRQ_PRIORITY
#define NRFX_WDT_CONFIG_IRQ_PRIORITY 6
#endif

// <e> NRFX_WDT_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef NRFX_WDT_CONFIG_LOG_ENABLED
#define NRFX_WDT_CONFIG_LOG_ENABLED 0
#endif
// <o> NRFX_WDT_CONFIG_LOG_LEVEL  - Default Severity level
 
// <0=> Off 
// <1=> Error 
// <2=> Warning 
// <3=> Info 
// <4=> Debug 

#ifndef NRFX_WDT_CONFIG_LOG_LEVEL
#define NRFX_WDT_CONFIG_LOG_LEVEL 3
#endif

// <o> NRFX_WDT_CONFIG_INFO_COLOR  - ANSI escape code prefix.
 
// <0=> Default 
// <1=> Black 
// <2=> Red 
// <3=> Green 
// <4=> Yellow 
// <5=> Blue 
// <6=> Magenta 
// <7=> Cyan 
// <8=> White 

#ifndef NRFX_WDT_CONFIG_INFO_COLOR
#define NRFX_WDT_CONFIG_INFO_COLOR 0
#endif

// <o> NRFX_WDT_CONFIG_DEBUG_COLOR  - ANSI escape code prefix.
 
// <0=> Default 
// <1=> Black 
// <2=> Red 
// <3=> Green 
// <4=> Yellow 
// <5=> Blue 
// <6=> Magenta 
// <7=> Cyan 
// <8=> White 

#ifndef NRFX_WDT_CONFIG_DEBUG_COLOR
#define NRFX_WDT_CONFIG_DEBUG_COLOR 0
#endif

// </e>

When when I try to connect to BLE from nRF connect App immediately after 1 seconds below error occurs.

<info> app: GATT ATT MTU on connection 0x0 changed to 247.
<error> app: ERROR 8 [NRF_ERROR_INVALID_STATE] at /home/neeraj/Applications/EmbeddedStudio_ARM_Nordic_v568_linux_x64/nRF5SDK1702d674dde/nRF5_SDK_17.0.2_d674dde/examples/peripheral/iotians_device_loadcell/IG_BLE.c:524 (line number 524 is line number 5 in above example)
PC at: 0x0002B885
<error> app: End of error report

Here was I expecting that the WDT event should occur but it was not.

Please help me. Am I expecting wrong? Please correct me if I am wrong.

Thanks and regards,

Neeraj Dhekale

  • Hello Simanr,

    Thanks for the reply.

    Where have you implemented the Watchdog in your application

    I am attaching modified code of WDT example code from SDK location /nRF5_SDK_17.0.2_d674dde/examples/peripheral/wdt

    
    #include <stdbool.h>
    #include <stdint.h>
    
    #include "nrf.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "app_error.h"
    #include "nrf_drv_wdt.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_pwr_mgmt.h"
    
    nrf_drv_wdt_channel_id m_channel_id;
    
    /**
     * @brief WDT events handler.
     */
    void wdt_event_handler(void)
    {
       
    printf("wdt_event_handler");
    
        //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
    }
    
    static void log_init(void)
    {
       ret_code_t err_code = NRF_LOG_INIT(NULL);
       APP_ERROR_CHECK(err_code);
       NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    /**
     * @brief Function for main application entry.
     */
     void feed(){
      nrf_drv_wdt_channel_feed(m_channel_id);
     }
    
     static void power_management_init(void)
    {
       ret_code_t err_code;
       err_code = nrf_pwr_mgmt_init();
       APP_ERROR_CHECK(err_code);
    }
    static void idle_state_handle(void)
    {
       UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
       nrf_pwr_mgmt_run();
    }
    int main(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    log_init();
    
    printf("test");
    
        //Configure WDT.
        nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
        err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
        APP_ERROR_CHECK(err_code);
        nrf_drv_wdt_enable();
    int i=0;
      while(1){
    
            if(i<30){
    
            printf("\nhello %d\n",i);
              nrf_delay_ms(1000);
          feed();
          }
    i++;
      }
    }
    
    

    sdk_config.h file

    // <e> WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver - legacy layer
    //==========================================================
    #ifndef WDT_ENABLED
    #define WDT_ENABLED 1
    #endif
    // <o> WDT_CONFIG_BEHAVIOUR  - WDT behavior in CPU SLEEP or HALT mode
     
    // <1=> Run in SLEEP, Pause in HALT 
    // <8=> Pause in SLEEP, Run in HALT 
    // <9=> Run in SLEEP and HALT 
    // <0=> Pause in SLEEP and HALT 
    
    #ifndef WDT_CONFIG_BEHAVIOUR
    #define WDT_CONFIG_BEHAVIOUR 1
    #endif
    
    // <o> WDT_CONFIG_RELOAD_VALUE - Reload value  <15-4294967295> 
    
    
    #ifndef WDT_CONFIG_RELOAD_VALUE
    #define WDT_CONFIG_RELOAD_VALUE 2000
    #endif
    
    // <o> WDT_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    
    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef WDT_CONFIG_IRQ_PRIORITY
    #define WDT_CONFIG_IRQ_PRIORITY 6
    #endif
    
    // </e>
    

    have you checked out the Watchdog API on the Infocenter explaining how the various Watchdog functions work and should be implemented?

    Yes, I have some doubts regarding WDT_IRQ_CONFIG. Do I need to register IRQ for wdt_event_handler? and NRF_WDT_EVENT_TIMEOUT. How and where I can set NRF_WDT_EVENT_TIMEOUT?

    Please let me know if I did anything wrong.

    Thanks and regards,

    Neeraj Dhekale

  • Hi

    The Watchdog is configured in the following snippet, with the interrupt priority configured there as well, so it shouldn't be necessary to do more there. 

    The NRF_WDT_EVENT_TIMEOUT is an event that occurs when the watchdog timer times out. I'm not sure what you mean by setting this? as it is already set in the nrfx_wdt.c driver and the nrf_bootloader_wdt.c library.

    Can you try to explain what you are trying to implement and what you expect is going to happen in your application? It still seems like you're feeding the watchdog in your main loop for 30 seconds and then do nothing afterwards.

    Best regards,

    Simon

  • Hello Simanr,

    Can you try to explain what you are trying to implement and what you expect is going to happen in your application? It still seems like you're feeding the watchdog in your main loop for 30 seconds and then do nothing afterwards.

    We have already implemented the firmware with different kinds of sensors integrated. Consider a worst-case if there is an issue with I2C based sensor in between and then execution gets stuck, then further its BLE advertisement will also stop transmitting data until and unless someone physically checks it. We expect WDT should work in such a scenario. if there is any error or stuck in execution and if WDT does not get the feed, there should be an event that occurs (can be used to set controller into emergency mode and transmits necessary data only to indicate something went wrong with sensor) and then reboot itself.

    In above the last example I was trying to implement a similar scenario where we are feeding WDT for consecutive 30 seconds and after that considered something went wrong and WDT will not get the next feeds. Here I was expecting WDT wdt_event_handler() function should have executed and then it should reboot ( or we can write NVIC_SystemReset(); in the wdt_event_handler() at the end).

    But currently, In the above example, WDT is working and directly getting rebooted without executing wdt_event_handler().

    I hope you got my purpose of implementing WDT in my firmware.

    Thanks and regards,

    Neeraj Dhekale

  • Hi

    I see, thank you for explaining. It could be that the WDT is getting blocked by another interrupt. The WDT driver uses the same interrupt priority as the other SDK drivers by default, so you can try setting the priority to 0 after enabling the SoftDevice to see if that helps.

    NVIC_SetPriority(WDT_IRQn, 0); // The Softdevice will check if the app is using any of the reserved interrupt priorities during initialization so set the WDT IRQ priority after enabling the stack as a workaround

    Best regards,

    Simon

  • Hello Simanr,

    I have tried to call NVIC_SetPriority(WDT_IRQn, 0);  but it is still not executing the event handler function. Also, I have tried to set NRFX_WDT_CONFIG_IRQ_PRIORITY and WDT_CONFIG_IRQ_PRIORITY to 0. But same result.

    Thanks and regards,

    Neeraj Dhekale

Related