This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2640R2F: Watchdog and Stanby Mode (with event_Pend): Unexpected watchdog reset every 7 minutes

Part Number: CC2640R2F

Tool/software: TI-RTOS

Hi all,

I'm using the watchdog with an event_pend TI-RTOS semaphore. My watchdog reload value is 8 seconds. I observe an unexpected watchdog triggered reset every 7 minutes.

Here are a couple of interesting observation:

  • I don't see any hardware or software component in our system with such a long period.
  • When watchdog is disabled, system works fine and doesn't hang/freeze after 7 minutes
  • I check the reset source register, and I'm 100% sure the reset is triggered by the watchdog
  • Reset only happens when no other event wakes up the CPU for 7 minutes. If any other event occurs in between, it will 'reset' the 7 min counter
  • So far, our workaround is to set the event_pend timeout to a value lower than 7 minutes.

Any idea?

Thanks,

Val

  • Hi Valerian,

    How are you kicking the watchdog in your application?
    I assume the device goes into standby when possible, is this the case?

    When in standby, the watchdog timer is stopped (as this is clocked by the system clock) so it should not time out when inactive unless the system clock remains on for some reason.

    Could you maybe share some code on how you use the watchdog and what you do inside the callback routine?
  • Hi Valerian,

    Can you try to implement your Watchdog code at the unmodified SDK v1.50 Simple Peripheral example program and see if you get the same results.

    -kel
  • Hi,

    @M-W:

    - Yes, the device goes to Standby mode whenever it is possible. Watchdog reload time is 8 seconds, and I can confirm the watchdog stops counting whenever it goes to standby mode. The issue occurs after 7 mins in standby mode without any event wake up the device (and consequently no watchdog clearing)

    - Question: Do I have to initialize ICall, my event_pend and my watchdog in a specific order?

    @kel:

    - Do you have an example using both the watchdog and Icall event_pend and running on the LaunchPad? The example I used is not using a semaphore.

    @all:

    When power profiling my custom device, I noticed a periodic 1 second very short power spike of a couple mA. I believe this is the processor waking up to service the RTC clock and the second Bios module. Would it be possible that the watchdog keeps counting during these power spikes, and then resets when reaching the reload value?

    app_ble.cfg:

    var BIOS = xdc.useModule('xdc.runtime.Timestamp');
    
    var Seconds = xdc.useModule('ti.sysbios.hal.Seconds');

    Thanks,

    Best,

    Val

  • Attached: Device Power consumption with 1 sec periodic power spikes:

    Please ignore the spike @ 0.6s

  • Hi Valerian,

         Sorry forgot to provide you with complete information from your previous posts. Here below are the important points to remember

    • The watchdog will stop counting down in standby mode if advertising is disabled.
    • The watchdog will continue counting down(delayed) in standby mode if advertising is enabled. The countdown is delayed from my current testing a 1 second watchdog reload value will countdown to 0 in 29 seconds using the simple peripheral for testing.

          Checking my previous work using watchdog, the advertising is enabled upon button press. After 1 minute the advertising is disabled. The watchdog reload value is set to 15 seconds so even if advertising is enabled the reset does not happen.

           Regarding the periodic spike, it is normal, from what I remember it is the DC to DC recharge something. Anyway here are SDK v1.50 simple peripheral code for testing. I added watchdog_app.c and watchdog_app.h

    watchdog_app.c

    /* Driver Header files */
    #include <ti/drivers/Watchdog.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include "hal_mcu.h"
    #include "watchdog_app.h"   
    #include "util.h"
    
    #include "Board.h"
    
    /* Led pin table */
    PIN_Config LedPinTable[] =
    {
        Board_PIN_LED0    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
        Board_PIN_LED1    | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
        PIN_TERMINATE                                                                      /* Terminate list */
    };
    
    PIN_State   pinState;
    PIN_Handle  ledPinHandle;
    
    Watchdog_Handle WatchdogHandle;
    
    void led_delay(void)
    {
        short i = 0;
    
        for(i = 0; i < 10000; i++);
        for(i = 0; i < 10000; i++);
        for(i = 0; i < 10000; i++);
        for(i = 0; i < 10000; i++);
    
    }
    
    void WatchdogApp_Callback(uintptr_t unused)
    {
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, ~PIN_getOutputValue(Board_PIN_LED0));
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, ~PIN_getOutputValue(Board_PIN_LED1));
        led_delay();
        led_delay();
        led_delay();
        led_delay();
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, ~PIN_getOutputValue(Board_PIN_LED1));
    
        HAL_SYSTEM_RESET();
    }
    
    
    void WatchdogApp_Clear(void)
    {
        Watchdog_clear(WatchdogHandle);
    }  
    
    
    void WatchdogApp_Init(void)
    {
        Watchdog_Params params;
    
        /* Allocate LED pins */
        ledPinHandle = PIN_open(&pinState, LedPinTable);
            
        Watchdog_init();
        
        Watchdog_Params_init(&params);
        params.callbackFxn = (Watchdog_Callback)WatchdogApp_Callback;
        params.resetMode = Watchdog_RESET_ON;
        WatchdogHandle = Watchdog_open(Board_WATCHDOG0, &params);
            
        if (WatchdogHandle == NULL) {
            /* Error opening Watchdog */
            while (1);
        }
    }

    watchdog_app.h

    #ifndef WATCHDOGAPP_H
    #define WATCHDOGAPP_H
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    extern void WatchdogApp_Init(void);
    extern void WatchdogApp_Clear(void);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* WATCHDOGAPP_H */

    simple_peripheral.c

    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Queue.h>
    #include <ti/display/Display.h>
    
    #if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
    #include <driverlib/ioc.h>
    #endif // USE_FPGA | DEBUG_SW_TRACE
    
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "devinfoservice.h"
    #include "simple_gatt_profile.h"
    #include "ll_common.h"
    
    #include "peripheral.h"
    #include "watchdog_app.h"
    
    #ifdef USE_RCOSC
    #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    #include "board_key.h"
    
    #include "board.h"
    
    #include "simple_peripheral.h"
    static void SimpleBLEPeripheral_init(void)
    {
      // ******************************************************************
      // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
      // ******************************************************************
      // Register the current thread as an ICall dispatcher application
      // so that the application can send and receive messages.
      ICall_registerApp(&selfEntity, &syncEvent);
    
    #ifdef USE_RCOSC
      RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
    #if defined( USE_FPGA )
      // configure RF Core SMI Data Link
      IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
    
      // configure RF Core SMI Command Link
      IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
    
      // configure RF Core tracer IO
      IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
    #else // !USE_FPGA
      #if defined( DEBUG_SW_TRACE )
        // configure RF Core tracer IO
        IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
      #endif // DEBUG_SW_TRACE
    #endif // USE_FPGA
    
      // Create an RTOS queue for message from profile to be sent to app.
      appMsgQueue = Util_constructQueue(&appMsg);
    
      // Create one-shot clocks for internal periodic events.
      Util_constructClock(&periodicClock, SimpleBLEPeripheral_clockHandler,
                          SBP_PERIODIC_EVT_PERIOD, 0, false, SBP_PERIODIC_EVT);
    
      dispHandle = Display_open(SBP_DISPLAY_TYPE, NULL);
    
      WatchdogApp_Init();
    
      // Set GAP Parameters: After a connection was established, delay in seconds
      // before sending when GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE,...)
      // uses GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS or
      // GAPROLE_LINK_PARAM_UPDATE_INITIATE_APP_PARAMS
      // For current defaults, this has no effect.
      GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
    
      // Setup the Peripheral GAPRole Profile. For more information see the User's
      // Guide:
      // software-dl.ti.com/.../
      {
        // Device starts advertising upon initialization of GAP
        //uint8_t initialAdvertEnable = TRUE;
        uint8_t initialAdvertEnable = FALSE;
    
        // By setting this to zero, the device will go into the waiting state after
        // being discoverable for 30.72 second, and will not being advertising again
        // until re-enabled by the application
        uint16_t advertOffTime = 0;
    
        uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
        uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
        uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
        uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
        uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
    
        // Set the Peripheral GAPRole Parameters
        GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                             &initialAdvertEnable);
        GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                             &advertOffTime);
    
        GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
                             scanRspData);
        GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
    
        GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),
                             &enableUpdateRequest);
        GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMinInterval);
        GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
                             &desiredMaxInterval);
        GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
                             &desiredSlaveLatency);
        GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
                             &desiredConnTimeout);
      }
    
      // Set the Device Name characteristic in the GAP GATT Service
      // For more information, see the section in the User's Guide:
      // software-dl.ti.com/.../html
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      // Set GAP Parameters to set the advertising interval
      // For more information, see the GAP section of the User's Guide:
      // software-dl.ti.com/.../html
      {
        // Use the same interval for general and limited advertising.
        // Note that only general advertising will occur based on the above configuration
        uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
    
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
        GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
      }
    
      // Setup the GAP Bond Manager. For more information see the section in the
      // User's Guide:
      // software-dl.ti.com/.../
      {
        // Don't send a pairing request after connecting; the peer device must
        // initiate pairing
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        // Use authenticated pairing: require passcode.
        uint8_t mitm = TRUE;
        // This device only has display capabilities. Therefore, it will display the
        // passcode during pairing. However, since the default passcode is being
        // used, there is no need to display anything.
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        // Request bonding (storing long-term keys for re-encryption upon subsequent
        // connections without repairing)
        uint8_t bonding = TRUE;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
      }
    
      // Initialize GATT attributes
      GGS_AddService(GATT_ALL_SERVICES);           // GAP GATT Service
      GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT Service
      DevInfo_AddService();                        // Device Information Service
      SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
    
      // Setup the SimpleProfile Characteristic Values
      // For more information, see the sections in the User's Guide:
      // software-dl.ti.com/.../
      {
        uint8_t charValue1 = 1;
        uint8_t charValue2 = 2;
        uint8_t charValue3 = 3;
        uint8_t charValue4 = 4;
        uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };
    
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                                   &charValue1);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                                   &charValue2);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                                   &charValue3);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &charValue4);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
                                   charValue5);
      }
    
      // Register callback with SimpleGATTprofile
      SimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);
    
      // Start the Device
      VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);
    
      // Start Bond Manager and register callback
      VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);
    
      // Register with GAP for HCI/Host messages. This is needed to receive HCI
      // events. For more information, see the section in the User's Guide:
      // software-dl.ti.com/.../html
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      //Set default values for Data Length Extension
      {
        //Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
        #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
        #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
    
        //This API is documented in hci.h
        //See the LE Data Length Extension section in the BLE-Stack User's Guide for information on using this command:
        //software-dl.ti.com/.../index.html
        //HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
      }
    
    #if !defined (USE_LL_CONN_PARAM_UPDATE)
      // Get the currently set local supported LE features
      // The HCI will generate an HCI event that will get received in the main
      // loop
      HCI_LE_ReadLocalSupportedFeaturesCmd();
    #endif // !defined (USE_LL_CONN_PARAM_UPDATE)
    
      Display_print0(dispHandle, 0, 0, "BLE Peripheral");
    }
    static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
      SimpleBLEPeripheral_init();
    
      // Application main loop
      for (;;)
      {
        uint32_t events;
    
        // Waits for an event to be posted associated with the calling thread.
        // Note that an event associated with a thread is posted when a
        // message is queued to the message receive queue of the thread
        events = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS,
                            ICALL_TIMEOUT_FOREVER);
    
        WatchdogApp_Clear();
    
        if (events)
        {
          ICall_EntityID dest;
          ICall_ServiceEnum src;
          ICall_HciExtEvt *pMsg = NULL;

    -kel

  • I would not expect the device to wake up every second just because you are using the "Seconds" module, this would be horrible for power consumption. The module itself is wrapping the RTC, translating it into seconds; It do not require a periodic tick. I would assume that the spikes are the recharge pulses, they should not result in the watchdog ticking.

    You should not need to initiate the Icall and watchdog in any particular order what I'm aware of, I recommend having a look at the example posted by Markel and compare it to yours.