Watchdog Timer Example Code

On the CC23xx, the Watchdog continues to tick using the 32kHz clock in Standby. As a workaround, a “soft stop” is implemented by setting the Watchdog reload value to 0xFFFFFFFF (~34 hours). Once the CC23xx wakes from Standby, you can change the Watchdog reload value to the intended value. This workaround potentially reduces the power consumption of the CC23xx. Without the workaround, the CC23xx must wake up before the timeout expires, or a reset will occur.

The code below implements this workaround.

Listing 16. watchdog_addons.h
 1#ifndef WATCHDOG_ADDONS_WATCHDOG_ADDONS_H_
 2#define WATCHDOG_ADDONS_WATCHDOG_ADDONS_H_
 3
 4#include <stdint.h>
 5
 6#define WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY 1
 7
 8#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
 9#include <ti/drivers/Watchdog.h>
10typedef struct
11{
12    Watchdog_Handle handle;
13#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
14    uint32_t applicationReloadTicks;
15    uint32_t standbyReloadTicks;
16#endif
17} Watchdog_addons_Params;
18#endif
19
20/**
21 * assumes Watchdog is already initialized.
22 * ok to call if Watchdog is already running.
23 * returns 0 if ok
24 */
25extern int8_t Watchdog_addons_init(Watchdog_addons_Params *pParams);
26
27
28#endif /* WATCHDOG_ADDONS_WATCHDOG_ADDONS_H_ */
Listing 17. watchdog_addons.c
 1#include "watchdog_addons.h"
 2
 3#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
 4#include <ti/drivers/Power.h>
 5#include <ti/drivers/power/PowerCC23X0.h>
 6#endif
 7
 8static uint8_t gInitDone = 0;
 9static Watchdog_addons_Params gCurParams;
10
11#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
12Power_NotifyObj gPowerNotifyObj;
13int PowerNotify_handler(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg);
14#endif
15
16/**
17 * assumes Watchdog is already initialized.
18 * ok to call if Watchdog is already running.
19 * returns 0 if ok
20 */
21int8_t Watchdog_addons_init(Watchdog_addons_Params *pParams)
22{
23    if (gInitDone)
24        return -1; // error: already initialized
25
26    if (!pParams || !pParams->handle)
27        return -1; // error: invalid parameters
28
29    gCurParams.handle                   =   pParams->handle;
30
31#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
32    gCurParams.applicationReloadTicks   =   pParams->applicationReloadTicks;
33    gCurParams.standbyReloadTicks       =   pParams->standbyReloadTicks;
34
35    // register for power notifications.
36    // if entering standby, set the Watchdog reload value to X (typically will be max, e.g. 0xFFFFFFFF)
37    // if exiting standby, set the Watchdog reload value to normal
38    int status = Power_registerNotify(&gPowerNotifyObj, PowerLPF3_ENTERING_STANDBY | PowerLPF3_AWAKE_STANDBY, &PowerNotify_handler, 0);
39    if (status != Power_SOK) while (1); // error
40#endif
41
42    gInitDone = 1;
43    return 0;
44}
45
46#if WATCHDOG_ADDON_FEATURE__SOFT_DISABLE_DURING_STANDBY
47int PowerNotify_handler(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg)
48{
49    if (eventType == PowerLPF3_ENTERING_STANDBY)
50    {
51        Watchdog_setReload(gCurParams.handle, gCurParams.standbyReloadTicks);
52    }
53    else if (eventType == PowerLPF3_AWAKE_STANDBY)
54    {
55        Watchdog_setReload(gCurParams.handle, gCurParams.applicationReloadTicks);
56    }
57
58    return Power_NOTIFYDONE;
59}
60#endif
Listing 18. watchdog.c
  1#include <stdint.h>
  2#include <stddef.h>
  3#include <unistd.h>
  4
  5/* Driver Header files */
  6#include <ti/drivers/GPIO.h>
  7#include <ti/drivers/Power.h>
  8#include <ti/drivers/Watchdog.h>
  9
 10/* Driver configuration */
 11#include "ti_drivers_config.h"
 12
 13#include "watchdog_addons.h"
 14
 15#define TIMEOUT_MS 1000
 16#define SLEEP_US   500000
 17
 18Watchdog_Handle watchdogHandle;
 19uint32_t reloadValue;
 20
 21static void testWatchdogAddon(uint8_t useWatchdogAddon);
 22
 23/*
 24*  ======== gpioButtonIsr ========
 25*/
 26void gpioButtonIsr(uint_least8_t index)
 27{
 28   GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
 29
 30   /*
 31   * Simulate the application being stuck in an ISR. This ISR can be
 32   * preempted by the watchdog Non-Maskable Interrupt (NMI).
 33   */
 34   while (1) {}
 35}
 36
 37/*
 38*  ======== mainThread ========
 39*/
 40void *mainThread(void *arg0)
 41{
 42   Watchdog_Params params;
 43
 44   /* Call driver init functions */
 45   GPIO_init();
 46   Watchdog_init();
 47
 48   /* Configure the LED and button pins */
 49   GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
 50   GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
 51
 52   /* Open a Watchdog driver instance */
 53   Watchdog_Params_init(&params);
 54   params.debugStallMode = Watchdog_DEBUG_STALL_ON;
 55   params.resetMode      = Watchdog_RESET_ON;
 56
 57   watchdogHandle = Watchdog_open(CONFIG_WATCHDOG_0, &params);
 58   if (watchdogHandle == NULL)
 59   {
 60      /* Error opening Watchdog */
 61      while (1) {}
 62   }
 63
 64   /*
 65   * The watchdog reload value is initialized during the
 66   * Watchdog_open() call. The reload value can also be
 67   * set dynamically during runtime.
 68   *
 69   * Converts TIMEOUT_MS to watchdog clock ticks.
 70   * This API is not applicable for all devices.
 71   * See the device specific watchdog driver documentation
 72   * for your device.
 73   */
 74   reloadValue = Watchdog_convertMsToTicks(watchdogHandle, TIMEOUT_MS);
 75
 76   /*
 77   * A value of zero (0) indicates the converted value exceeds 32 bits
 78   * OR that the API is not applicable for this specific device.
 79   */
 80   if (reloadValue != 0)
 81   {
 82      Watchdog_setReload(watchdogHandle, reloadValue);
 83   }
 84
 85   const uint8_t useAddon = 1;
 86   testWatchdogAddon(useAddon);
 87
 88   while (1)
 89   {
 90
 91      /*
 92      * Disabling power policy will prevent the device from entering
 93      * low power state. The device will stay awake when the CPU is
 94      * idle.
 95      */
 96      Power_disablePolicy();
 97
 98      /* Sleep for SLEEP_US before clearing the watchdog */
 99      usleep(SLEEP_US);
100      Watchdog_clear(watchdogHandle);
101      GPIO_toggle(CONFIG_GPIO_LED_0);
102
103      /*
104      * Enabling power policy will allow the device to enter a low
105      * power state when the CPU is idle. How the watchdog peripheral
106      * behaves in a low power state is device specific.
107      */
108      Power_enablePolicy();
109
110      /* Sleep for SLEEP_US before clearing the watchdog */
111      usleep(SLEEP_US);
112      Watchdog_clear(watchdogHandle);
113      GPIO_toggle(CONFIG_GPIO_LED_0);
114   }
115}
116
117/*
118* This function tests when Standby is entered.
119* Then Watchdog will have a "soft" stop during Standby.
120* So, Watchdog will never trigger reset, as long as time(standby) < time(standby Watchdog reload).
121* While device is active:
122*  - Watchdog will trigger if time(application interval Watchdog_clear) > time(application Watchdog ticks)
123*  - Watchdog will not trigger if time(application interval Watchdog_clear) < time(application Watchdog ticks)
124*/
125#include DeviceFamily_constructPath(inc/hw_types.h)
126#include DeviceFamily_constructPath(inc/hw_memmap.h)
127#include DeviceFamily_constructPath(inc/hw_ckmd.h)
128#include DeviceFamily_constructPath(driverlib/hapi.h)
129static void testWatchdogAddon(uint8_t useWatchdogAddon)
130{
131   if (useWatchdogAddon)
132   {
133      Watchdog_addons_Params params;
134      params.handle = watchdogHandle;
135      params.applicationReloadTicks = reloadValue;
136      params.standbyReloadTicks = 0xFFFFFFFF;
137      int8_t status = Watchdog_addons_init(&params);
138      if (status) while (1); // error
139   }
140
141   // Stay in Standby for longer than time(Watchdog application reload value).
142   // If Watchdog addon for "soft stop in standby" is used, then Watchdog should not trigger a reset.
143   // Else if not used, then Watchdog should trigger a reset.
144   //
145   // test result:
146   // - OK: if useWatchdogAddon==0, then a reset is generated
147   // - OK: if useWatchdogAddon==1, then reset is not generated
148
149   // Stay in Active for longer than time(Watchdog application reload value).
150   // Independent of whether "soft stop in standby" is used, Watchdog should trigger a reset.
151   // Test results:
152   // - OK: if useWatchdogAddon==0, then a reset is generated
153   // - OK: if useWatchdogAddon==1, then reset is not generated
154
155   // Two Test Cases:
156   // - clearWatchdog == 1 --> proves that the workaround works in the normal
157   //    case (application wakes up periodically from Standby to clear the
158   //    Watchdog).
159   // - clearWatchdog == 0 --> proves that the Watchdog will reset the device
160   //    if the device a) is in Active Mode and b) does not clear the
161   //    Watchdog.
162   // Assume addon always enabled (useWatchdogAddon == 1).
163   const uint32_t sleep_sec = (TIMEOUT_MS * 2) / 1000;
164   const uint8_t clearWatchdog = 1;
165   while (1)
166   {
167      sleep(sleep_sec);
168
169      if (clearWatchdog)
170      {
171         Watchdog_clear(watchdogHandle);
172      }
173      else
174      {
175         while (1);
176      }
177   }
178}