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)

Part Number: CC2640R2F

Tool/software: TI-RTOS

Hi all,

I'm trying to add a watchdog to my application, but I'm running into issues when the device goes to sleep. I'm using Event_pend as a semaphore, and basically the watchdog works well as long as events occur within the watchdog reload period. If There is no event to wake up the device, then the watchdog will trigger.

The documentation (DriverLib) clearly specifies that the watchdog should stop counting when the device goes into sleep/ standby mode

Power Management
Once started, the Watchdog will keep running in Active or Idle mode. When the device enters Standby mode, the Watchdog timer will stop counting down but the counter value will be preserved. When the device wakes up from Standby, the Watchdog timer will continue to count down from the previous counter value.

This means that if a system goes into Standby 50% of the time and the Watchdog reload value is set to 1 second, the Watchdog timer will actually time out in 2 seconds. A system which is only in Active/Idle mode for 1% of the time, the Watchdog timer will time out in 100 seconds. However, if a bug locks up the application in Active mode, the Watchdog timer will time out in the configured time.

Here is my main loop:

    for (;;)
    {
        /******** SEMAPHORE WAIT **************************************************************************************************/
        // 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
        uint32_t events = Event_pend(m_syncEvent, Event_Id_NONE, PAMSYS_ALL_EVENTS, ICALL_TIMEOUT_FOREVER);


        /******** WATCHDOG*********************************************************************************************************/
        CMSIS_RTOS_clearWatchdog();

        if (events > 0)
        {
             .....
        }
   }

Thanks for your help,

Best 

Val

  • Hello,

    Are you trying to make watchdog timer work while the device is in standby mode?

    If so, this will be impossible I suggest that you disable standby mode this way when the device goes to "sleep" the watchdog can keep counting. Keep in mind that this will increase your current consumption.
    Regards,
    AB
  • Hi AB,
    I have the opposite issue. The watchdog timer is running while I'm on standby mode, and thus triggers unexpectedly. I'm looking for a way to make sure that the watchdog stops when the device enters standby mode.
    Thanks,
    Val
  • Hello Valerian,

    Understood, how many tasks are you running? Can you post the power setting here? They are located in the xxxxLAUNCHXL.c file.

    Regards,
    AB
  • Hi AB

    Hereafter is my board.c.
    Thanks,
    Val


    /**********************************************************************************************//** * @file Board.c * @date 2017/06/22 * @brief This file contains the CC2640 Configuration * @copyright 2018 BioSensics LLC. All rights reserved. **************************************************************************************************/ /* * ====================== CC2640R2_LAUNCHXL.c ================================= * This board file is made for the 7x7 mm QFN package, to convert this board * file to use for other smaller device packages please refer to the table * below which lists the max IOID values supported by each package. All other * unused pins should be set to IOID_UNUSED. * * Furthermore the board file is also used * to define a symbol that configures the RF front end and bias. * See the comments below for more information. * For an in depth tutorial on how to create a custom board file, please refer * to the section "Running the SDK on Custom Boards" with in the Software * Developer's Guide. * * Refer to the datasheet for all the package options and IO descriptions: * www.ti.com/.../cc2640r2f.pdf * * +-----------------------+------------------+-----------------------+ * | Package Option | Total GPIO Pins | MAX IOID | * +=======================+==================+=======================+ * | 7x7 mm QFN | 31 | IOID_30 | * +-----------------------+------------------+-----------------------+ * | 5x5 mm QFN | 15 | IOID_14 | * +-----------------------+------------------+-----------------------+ * | 4x4 mm QFN | 10 | IOID_9 | * +-----------------------+------------------+-----------------------+ * | 2.7 x 2.7 mm WCSP | 14 | IOID_13 | * +-----------------------+------------------+-----------------------+ * */ /* * ====================== Includes ============================================ */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/family/arm/m3/Hwi.h> #include <ti/devices/cc26x0r2/driverlib/ioc.h> #include <ti/devices/cc26x0r2/driverlib/udma.h> #include <ti/devices/cc26x0r2/inc/hw_ints.h> #include <ti/devices/cc26x0r2/inc/hw_memmap.h> #include "Board.h" /* * =============================== PIN =============================== */ #include <ti/drivers/PIN.h> #include <ti/drivers/pin/PINCC26XX.h> /* Place into subsections to allow the TI linker to remove items properly */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(BoardGpioInitTable, ".const:BoardGpioInitTable") #pragma DATA_SECTION(PINCC26XX_hwAttrs, ".const:PINCC26XX_hwAttrs") #endif const PIN_Config BoardGpioInitTable[] = { // Turn off radio amp by default Board_Radio_Amp_PAEN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL, Board_Radio_Amp_EN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL, Board_Radio_RF_High | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL, PIN_TERMINATE /* Terminate list */ }; const PINCC26XX_HWAttrs PINCC26XX_hwAttrs = { .intPriority = ~0, .swiPriority = 0 }; /*============================================================================*/ /* * ============================= Power begin =================================== */ #include <ti/drivers/Power.h> #include <ti/drivers/power/PowerCC26XX.h> const PowerCC26XX_Config PowerCC26XX_config = { .policyInitFxn = NULL, .policyFxn = &PowerCC26XX_standbyPolicy, .calibrateFxn = &PowerCC26XX_calibrate, .enablePolicy = TRUE, #ifdef USE_RCOSC .calibrateRCOSC_LF = TRUE, #else .calibrateRCOSC_LF = FALSE, #endif .calibrateRCOSC_HF = TRUE, }; /* * ============================= Power end =================================== */ /* * =============================== GPTimer =============================== * Remove unused entries to reduce flash usage both in Board.c and Board.h */ #include <ti/drivers/timer/GPTimerCC26XX.h> GPTimerCC26XX_Object gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMERCOUNT]; const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMERPARTSCOUNT] = { { .baseAddr = GPT0_BASE, .intNum = INT_GPT0A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0A, }, { .baseAddr = GPT0_BASE, .intNum = INT_GPT0B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0B, }, { .baseAddr = GPT1_BASE, .intNum = INT_GPT1A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1A, }, { .baseAddr = GPT1_BASE, .intNum = INT_GPT1B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1B, }, { .baseAddr = GPT2_BASE, .intNum = INT_GPT2A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2A, }, { .baseAddr = GPT2_BASE, .intNum = INT_GPT2B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2B, }, { .baseAddr = GPT3_BASE, .intNum = INT_GPT3A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3A, }, { .baseAddr = GPT3_BASE, .intNum = INT_GPT3B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3B, }, }; const GPTimerCC26XX_Config GPTimerCC26XX_config[CC2640R2_LAUNCHXL_GPTIMERPARTSCOUNT] = { { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER0], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER0A], GPT_A }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER0], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER0B], GPT_B }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER1], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER1A], GPT_A }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER1], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER1B], GPT_B }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER2], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER2A], GPT_A }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER2], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER2B], GPT_B }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER3], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER3A], GPT_A }, { &gptimerCC26XXObjects[CC2640R2_LAUNCHXL_GPTIMER3], &gptimerCC26xxHWAttrs[CC2640R2_LAUNCHXL_GPTIMER3B], GPT_B }, }; /* * ============================= UDMA begin =================================== */ /* Place into subsections to allow the TI linker to remove items properly */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(UDMACC26XX_config, ".const:UDMACC26XX_config") #pragma DATA_SECTION(udmaHWAttrs, ".const:udmaHWAttrs") #endif /* Include drivers */ #include <ti/drivers/dma/UDMACC26XX.h> /* UDMA objects */ UDMACC26XX_Object udmaObjects[CC2640R2_LAUNCHXL_UDMACOUNT]; /* UDMA configuration structure */ const UDMACC26XX_HWAttrs udmaHWAttrs[CC2640R2_LAUNCHXL_UDMACOUNT] = { { .baseAddr = UDMA0_BASE, .powerMngrId = PowerCC26XX_PERIPH_UDMA, .intNum = INT_DMA_ERR, .intPriority = ~0 } }; /* UDMA configuration structure */ const UDMACC26XX_Config UDMACC26XX_config[CC2640R2_LAUNCHXL_UDMACOUNT] = { { .object = &udmaObjects[CC2640R2_LAUNCHXL_UDMA0], .hwAttrs = &udmaHWAttrs[CC2640R2_LAUNCHXL_UDMA0] }, }; /* * ============================= UDMA end ===================================== */ /* * =============================== Watchdog =============================== */ #include <ti/drivers/Watchdog.h> #include <ti/drivers/watchdog/WatchdogCC26XX.h> WatchdogCC26XX_Object watchdogCC26XXObjects[CC2640R2_LAUNCHXL_WATCHDOGCOUNT]; const WatchdogCC26XX_HWAttrs watchdogCC26XXHWAttrs[CC2640R2_LAUNCHXL_WATCHDOGCOUNT] = { { .baseAddr = WDT_BASE, .reloadValue = 2000 /* Reload value in milliseconds */ }, }; const Watchdog_Config Watchdog_config[CC2640R2_LAUNCHXL_WATCHDOGCOUNT] = { { .fxnTablePtr = &WatchdogCC26XX_fxnTable, .object = &watchdogCC26XXObjects[CC2640R2_LAUNCHXL_WATCHDOG0], .hwAttrs = &watchdogCC26XXHWAttrs[CC2640R2_LAUNCHXL_WATCHDOG0] }, }; const uint_least8_t Watchdog_count = CC2640R2_LAUNCHXL_WATCHDOGCOUNT; /* * =============================== RF Driver =============================== * Note: The BLE-Stack requires RF SWI priorities to be set to 5. */ #include <ti/drivers/rf/RF.h> /* RF hwi and swi priority */ const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = { .hwiCpe0Priority = ~0, .hwiHwPriority = ~0, .swiCpe0Priority = 5, .swiHwPriority = 5, }; /* * ========================== RF driver end ========================================= */ /* * ============================= UART begin =================================== */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(UART_config, ".const:UART_config") #pragma DATA_SECTION(uartCC26XXHWAttrs, ".const:uartCC26XXHWAttrs") #endif /* Include drivers */ #include <ti/drivers/UART.h> #include <ti/drivers/uart/UARTCC26XX.h> /* UART objects */ UARTCC26XX_Object uartCC26XXObjects[CC2640R2_LAUNCHXL_UARTCOUNT]; /* UART hardware parameter structure, also used to assign UART pins */ const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CC2640R2_LAUNCHXL_UARTCOUNT] = { { .baseAddr = UART0_BASE, .powerMngrId = PowerCC26XX_PERIPH_UART0, .intNum = INT_UART0_COMB, .intPriority = ~0, .swiPriority = 0, .txPin = Board_McuLink_TX, .rxPin = Board_McuLink_RX, .ctsPin = PIN_UNASSIGNED, .rtsPin = PIN_UNASSIGNED } }; /* UART configuration structure */ const UART_Config UART_config[CC2640R2_LAUNCHXL_UARTCOUNT] = { { .fxnTablePtr = &UARTCC26XX_fxnTable, .object = &uartCC26XXObjects[CC2640R2_LAUNCHXL_UART0], .hwAttrs = &uartCC26XXHWAttrs[CC2640R2_LAUNCHXL_UART0] }, }; const uint_least8_t UART_count = CC2640R2_LAUNCHXL_UARTCOUNT; /* * ============================= UART end ===================================== */ /* * ========================== SPI DMA begin =================================== */ /* Place into subsections to allow the TI linker to remove items properly */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(SPI_config, ".const:SPI_config") #pragma DATA_SECTION(spiCC26XXDMAHWAttrs, ".const:spiCC26XXDMAHWAttrs") #endif /* Include drivers */ #include <ti/drivers/spi/SPICC26XXDMA.h> /* SPI objects */ SPICC26XXDMA_Object spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPICOUNT]; /* SPI configuration structure, describing which pins are to be used */ const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPICOUNT] = { { .baseAddr = SSI0_BASE, .intNum = INT_SSI0_COMB, .intPriority = ~0, .swiPriority = 0, .powerMngrId = PowerCC26XX_PERIPH_SSI0, .defaultTxBufValue = 0, .rxChannelBitMask = 1<<UDMA_CHAN_SSI0_RX, .txChannelBitMask = 1<<UDMA_CHAN_SSI0_TX, // .mosiPin = Board_SPI0_MOSI, // .misoPin = Board_SPI0_MISO, // .clkPin = Board_SPI0_CLK, .mosiPin = PIN_UNASSIGNED, .misoPin = PIN_UNASSIGNED, .clkPin = PIN_UNASSIGNED, .csnPin = PIN_UNASSIGNED }, { .baseAddr = SSI1_BASE, .intNum = INT_SSI1_COMB, .intPriority = ~0, .swiPriority = 0, .powerMngrId = PowerCC26XX_PERIPH_SSI1, .defaultTxBufValue = 0, .rxChannelBitMask = 1<<UDMA_CHAN_SSI1_RX, .txChannelBitMask = 1<<UDMA_CHAN_SSI1_TX, .mosiPin = Board_SPI1_MOSI, .misoPin = Board_SPI1_MISO, .clkPin = Board_SPI1_CLK, .csnPin = PIN_UNASSIGNED } }; /* SPI configuration structure */ const SPI_Config SPI_config[] = { { .fxnTablePtr = &SPICC26XXDMA_fxnTable, .object = &spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPI0], .hwAttrs = &spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPI0] }, { .fxnTablePtr = &SPICC26XXDMA_fxnTable, .object = &spiCC26XXDMAObjects[CC2640R2_LAUNCHXL_SPI1], .hwAttrs = &spiCC26XXDMAHWAttrs[CC2640R2_LAUNCHXL_SPI1] }, }; const uint_least8_t SPI_count = CC2640R2_LAUNCHXL_SPICOUNT; /* * ========================== SPI DMA end ===================================== */ /* * ============================= I2C Begin===================================== */ /* Place into subsections to allow the TI linker to remove items properly */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_SECTION(I2C_config, ".const:I2C_config") #pragma DATA_SECTION(i2cCC26xxHWAttrs, ".const:i2cCC26xxHWAttrs") #endif /* Include drivers */ #include <ti/drivers/i2c/I2CCC26XX.h> /* I2C objects */ I2CCC26XX_Object i2cCC26xxObjects[CC2650_I2CCOUNT]; /* I2C configuration structure, describing which pins are to be used */ const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CC2650_I2CCOUNT] = { { .baseAddr = I2C0_BASE, .powerMngrId = PowerCC26XX_PERIPH_I2C0, .intNum = INT_I2C_IRQ, .intPriority = ~0, .swiPriority = 0, .sdaPin = Board_Batt_SDA, .sclPin = Board_Batt_SCL, } }; const I2C_Config I2C_config[] = { {&I2CCC26XX_fxnTable, &i2cCC26xxObjects[0], &i2cCC26xxHWAttrs[0]}, {NULL, NULL, NULL} }; const uint_least8_t I2C_count = CC2640R2_LAUNCHXL_I2CCOUNT; /* * ========================== I2C end ========================================= */ /* * =============================== Crypto =============================== */ #include <ti/drivers/crypto/CryptoCC26XX.h> CryptoCC26XX_Object cryptoCC26XXObjects[CC2640R2_LAUNCHXL_CRYPTOCOUNT]; const CryptoCC26XX_HWAttrs cryptoCC26XXHWAttrs[CC2640R2_LAUNCHXL_CRYPTOCOUNT] = { { .baseAddr = CRYPTO_BASE, .powerMngrId = PowerCC26XX_PERIPH_CRYPTO, .intNum = INT_CRYPTO_RESULT_AVAIL_IRQ, .intPriority = ~0, } }; const CryptoCC26XX_Config CryptoCC26XX_config[CC2640R2_LAUNCHXL_CRYPTOCOUNT] = { { .object = &cryptoCC26XXObjects[CC2640R2_LAUNCHXL_CRYPTO0], .hwAttrs = &cryptoCC26XXHWAttrs[CC2640R2_LAUNCHXL_CRYPTO0] }, }; /* * ========================= TRNG begin ==================================== */ #include <TRNGCC26XX.h> /* TRNG objects */ TRNGCC26XX_Object trngCC26XXObjects[CC2640R2_LAUNCHXL_TRNGCOUNT]; /* TRNG configuration structure, describing which pins are to be used */ const TRNGCC26XX_HWAttrs TRNGCC26XXHWAttrs[CC2640R2_LAUNCHXL_TRNGCOUNT] = { { .powerMngrId = PowerCC26XX_PERIPH_TRNG, } }; /* TRNG configuration structure */ const TRNGCC26XX_Config TRNGCC26XX_config[] = { { .object = &trngCC26XXObjects[0], .hwAttrs = &TRNGCC26XXHWAttrs[0] }, {NULL, NULL} }; /* * ========================= TRNG end ==================================== */ /* * ======== CC2640R2_LAUNCHXL_initGeneral ======== */ void CC2640R2_LAUNCHXL_initGeneral(void) { Power_init(); if (PIN_init(BoardGpioInitTable) != PIN_SUCCESS) { System_abort("Error with PIN_init\n"); } }

  • Hi AB,

    What should I look for in the board file? I also checked with a Power Profiler, and it seems that the device is going to standby as expected.

    Thanks,
    Val
  • Hi Valerian,

    Are you using CCS or IAR Embedded Workbench? Post your Watchdog code here.

    -kel
  • Hi Kel,

    I'm using CCS.

    Thanks for taking over.

    Best,

    Val



    /** * @brief Initialize WATCHDOG module * @param moduleClbs */ void WATCHDOG_init(WATCHDOG_appCBs_t moduleClbs) { m_moduleClbs = moduleClbs; #if APP_WATCHDOG_ENABLED==TRUE Watchdog_init(); #endif } /**********************************************************************************************//** * @brief Start WATCHDOG Module and Watchdog */ void WATCHDOG_start (void) { #if APP_WATCHDOG_ENABLED==TRUE Watchdog_Params params; /* Create and enable a Watchdog with resets disabled */ Watchdog_Params_init(&params); params.callbackFxn = watchdogHandler; params.resetMode = Watchdog_RESET_ON; m_watchdogHandle = Watchdog_open(Board_WATCHDOG0, &params); if (m_watchdogHandle == NULL) { /* Error opening Watchdog */ RTOS_errorHandler(eError, eUnidentified); } else { Watchdog_setReload(m_watchdogHandle, Watchdog_convertMsToTicks(m_watchdogHandle, APP_WATCHDOG_RELOAD)); } #endif } /**********************************************************************************************//** * @brief Clear Watchdog */ void WATCHDOG_clearWatchdog (void) { if (m_watchdogHandle != NULL) { Watchdog_clear(m_watchdogHandle); } }
  • Hi Valerian,

         There is a problem debugging the Watchdog using CCS. As you observed the watchdog countdown even at Standby Mode. It will also countdown even if you call Watchdog_clear(). But, debugging using IAR Embedded Workbench it works as expected.

         I have tested the Watchdog by putting a while(1) loop at GAPROLE_CONNECTED so when I connect using Smart Phone the Watchdog will countdown at my set reload value example 5 seconds. I have set the leds to visually indicate that the device resets.

         The Watchdog does a WARM Reset. In the Technical docs it is mentioned that WARM Reset is not recommended and you need to convert it to SYSTEM Reset using code. So that I do not need to implement this code I just call HAL_SYSTEM_RESET() at the Watchdog Callback.

    -kel

  • Hi Kel,

    So basically you're saying the watchdog is not working well with the debugger attached (CCS), but should work well without the debugger? That's good news, I'll test that asap.

    Concerning your last comment, I perform HAL_SYSTEM_RESET in my watchdog interrupt handler. However, I also perform a couple of recovery operations before, and I want to be sure the device will reset.

    Thanks for your help,

    Best,

    Val

  • Valerian G said:
    watchdog is not working well with the debugger attached (CCS), but should work well without the debugger?

    The watchdog work well without CCS debugger. I have tested it many times.

    -kel

  • Hi Kel,

    As you mentioned, the watchdog is not working properly when the device is attached to the debugger, but else works fine.
    I checked with my application and confirmed your conclusion.

    However, I have a similar issue when my device (custom IoT weareable board) is powered by the USB port (instead of the battery). It seems that changing the power source impacts the watchdog behavior.

    Can you provide details about the watchdog+debugger issue, so I can check with my hardware engineer if we are in a similar situation when powered by USB.

    Thanks,
    Val
  • Hi Valerian,

    It more seems the CCS is the cause of the problem and not the XDS110 JTAG debugger.

    Before I implemented Watchdog at custom CC2640R2F board using IAR Embedded Workbench, I tested it powered by coin cell battery and USB powered and it worked for days. To power it and debug through USB we used the CC-DEVPACK-DEBUG.

    Actually, when I recently tested the Watchdog using the CC2640R2F Launchpad it did not reset properly at first. But after re-attaching the USB cable it worked without problems.

    -kel