Add support for statically allocated watchdog timer structures

This commit is contained in:
Gregory Nutt 2014-08-22 08:46:34 -06:00
parent 09396b39eb
commit fd484c4de9
9 changed files with 119 additions and 101 deletions

View File

@ -2705,33 +2705,35 @@ int up_timer_start(FAR const struct timespec *ts);
or <code>kill()</code> to communicate with NuttX tasks. or <code>kill()</code> to communicate with NuttX tasks.
</p> </p>
<ul> <ul>
<li><a href="#wdcreate">4.3.5.1 wd_create</a></li> <li><a href="#wdcreate">4.3.5.1 wd_create/wd_static</a></li>
<li><a href="#wddelete">4.3.5.2 wd_delete</a></li> <li><a href="#wddelete">4.3.5.2 wd_delete</a></li>
<li><a href="#wdstart">4.3.5.3 wd_start</a></li> <li><a href="#wdstart">4.3.5.3 wd_start</a></li>
<li><a href="#wdcancel">4.3.5.4 wd_cancel</a></li> <li><a href="#wdcancel">4.3.5.4 wd_cancel</a></li>
<li><a href="#wdgettime">4.3.5.5 wd_gettime</a></li> <li><a href="#wdgettime">4.3.5.5 wd_gettime</a></li>
</ul> </ul>
<h4><a name="wdcreate">4.3.5.1 wd_create</a></h4> <h4><a name="wdcreate">4.3.5.1 wd_create/wd_static</a></h4>
<p> <p>
<b>Function Prototype:</b> <b>Function Prototype:</b>
<pre> <pre>
#include &lt;nuttx/wdog.h&gt; #include &lt;nuttx/wdog.h&gt;
WDOG_ID wd_create(void); WDOG_ID wd_create(void);
void wd_static(FAR struct wdog_s *wdog);
</pre> </pre>
<p> <p>
<b>Description:</b> The wd_create function will create a watchdog <b>Description:</b> The <code>wd_create()</code> function will create a timer by allocating the appropriate resources for the watchdog. The <code>wd_create()</code> function returns a pointer to a fully initialized, dynamically allocated <code>struct wdog_s</code> instance (which is <code>typedef</code>'ed as <code>WDOG_ID</code>);
by allocating the appropriate resources for the watchdog. </p>
<p>
<code>wd_static()</code> performs the equivalent initialization of a statically allocated <code>struct wdog_s</code> instance. No allocation is performed in this case. The initializer definition, <code>WDOG_INITIALIZER</code> is also available for initialization of static instances of <code>struct wdog_s</code>. NOTE: <code>wd_static()</code> is also implemented as a macro definition.
</p>
<p> <p>
<b>Input Parameters:</b> None. <b>Input Parameters:</b> None.
<p> <p>
<b>Returned Value:</b> <b>Returned Value:</b>
<ul> <ul>
<li>Pointer to watchdog that may be used as a handle in subsequent <li>Pointer to watchdog that may be used as a handle in subsequent NuttX calls (i.e., the watchdog ID), or NULL if insufficient resources are available to create the watchdogs.
NuttX calls (i.e., the watchdog ID), or NULL if insufficient resources
are available to create the watchdogs.
</ul> </ul>
<p> <p>
@ -2760,10 +2762,11 @@ initialization time).
</pre> </pre>
<p> <p>
<b>Description:</b> The wd_delete function will deallocate a <b>Description:</b> The wd_delete function will deallocate a watchdog timer previously allocated via <code>wd_create()</code>. The watchdog timer will be removed from the timer queue if has been started.
watchdog. The watchdog will be removed from the timer queue if
has been started.
<p> <p>
<p>
This function need not be called for statically allocated timers (but it is not harmful to do so).
</p>
<b>Input Parameters:</b> <b>Input Parameters:</b>
<ul> <ul>
<li><code>wdog</code>. The watchdog ID to delete. This is actually a <li><code>wdog</code>. The watchdog ID to delete. This is actually a

View File

@ -48,11 +48,59 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ********************************************************/
#ifndef CONFIG_PREALLOC_WDOGS
# define CONFIG_PREALLOC_WDOGS 32
#endif
#ifndef CONFIG_WDOG_INTRESERVE
# if CONFIG_PREALLOC_WDOGS > 16
# define CONFIG_WDOG_INTRESERVE 4
# elif CONFIG_PREALLOC_WDOGS > 8
# define CONFIG_WDOG_INTRESERVE 2
# else
# define CONFIG_WDOG_INTRESERVE 1
# endif
#endif
#if CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
# error CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
#endif
/* Watchdog Definitions *************************************************/
/* Flag bits for the flags field of struct wdog_s */
#define WDOGF_ACTIVE (1 << 0) /* Bit 0: 1=Watchdog is actively timing */
#define WDOGF_ALLOCED (1 << 1) /* Bit 1: 0=Pre-allocated, 1=Allocated */
#define WDOGF_STATIC (1 << 2) /* Bit 2: 0=[Pre-]allocated, 1=Static */
#define WDOG_SETACTIVE(w) do { (w)->flags |= WDOGF_ACTIVE; } while (0)
#define WDOG_SETALLOCED(w) do { (w)->flags |= WDOGF_ALLOCED; } while (0)
#define WDOG_SETSTATIC(w) do { (w)->flags |= WDOGF_STATIC; } while (0)
#define WDOG_CLRACTIVE(w) do { (w)->flags &= ~WDOGF_ACTIVE; } while (0)
#define WDOG_CLRALLOCED(w) do { (w)->flags &= ~WDOGF_ALLOCED; } while (0)
#define WDOG_CLRSTATIC(w) do { (w)->flags &= ~WDOGF_STATIC; } while (0)
#define WDOG_ISACTIVE(w) (((w)->flags & WDOGF_ACTIVE) != 0)
#define WDOG_ISALLOCED(w) (((w)->flags & WDOGF_ALLOCED) != 0)
#define WDOG_ISSTATIC(w) (((w)->flags & WDOGF_STATIC) != 0)
/* Initialization of statically allocated timers ****************************/
#define wd_static(w) \
do { (w)->next = NULL; (w)->flags = WDOGF_STATIC; } while (0)
#ifdef CONFIG_PIC
# define WDOG_INITIAILIZER { NULL, NULL, NULL, 0, WDOGF_STATIC, 0 }
#else
# define WDOG_INITIAILIZER { NULL, NULL, 0, WDOGF_STATIC, 0 }
#endif
/**************************************************************************** /****************************************************************************
* Public Type Declarations * Public Type Declarations
****************************************************************************/ ****************************************************************************/
/* The arguments are passed as uint32_t values. For systems where the /* The arguments are passed as uint32_t values. For systems where the
* sizeof(pointer) < sizeof(uint32_t), the following union defines the * sizeof(pointer) < sizeof(uint32_t), the following union defines the
* alignment of the pointer within the uint32_t. For example, the SDCC * alignment of the pointer within the uint32_t. For example, the SDCC
@ -76,6 +124,23 @@ typedef union wdparm_u wdparm_t;
typedef CODE void (*wdentry_t)(int argc, uint32_t arg1, ...); typedef CODE void (*wdentry_t)(int argc, uint32_t arg1, ...);
/* This is the internal representation of the watchdog timer structure. The
* WDOG_ID is a pointer to a watchdog structure.
*/
struct wdog_s
{
FAR struct wdog_s *next; /* Support for singly linked lists. */
wdentry_t func; /* Function to execute when delay expires */
#ifdef CONFIG_PIC
FAR void *picbase; /* PIC base address */
#endif
int lag; /* Timer associated with the delay */
uint8_t flags; /* See WDOGF_* definitions above */
uint8_t argc; /* The number of parameters to pass */
uint32_t parm[CONFIG_MAX_WDOGPARMS];
};
/* Watchdog 'handle' */ /* Watchdog 'handle' */
typedef FAR struct wdog_s *WDOG_ID; typedef FAR struct wdog_s *WDOG_ID;

View File

@ -91,16 +91,16 @@
int wd_cancel(WDOG_ID wdog) int wd_cancel(WDOG_ID wdog)
{ {
wdog_t *curr; FAR struct wdog_s *curr;
wdog_t *prev; FAR struct wdog_s *prev;
irqstate_t saved_state; irqstate_t state;
int ret = ERROR; int ret = ERROR;
/* Prohibit timer interactions with the timer queue until the /* Prohibit timer interactions with the timer queue until the
* cancellation is complete * cancellation is complete
*/ */
saved_state = irqsave(); state = irqsave();
/* Make sure that the watchdog is initialized (non-NULL) and is still /* Make sure that the watchdog is initialized (non-NULL) and is still
* active. * active.
@ -114,7 +114,7 @@ int wd_cancel(WDOG_ID wdog)
*/ */
prev = NULL; prev = NULL;
curr = (wdog_t*)g_wdactivelist.head; curr = (FAR struct wdog_s *)g_wdactivelist.head;
while ((curr) && (curr != wdog)) while ((curr) && (curr != wdog))
{ {
@ -168,6 +168,6 @@ int wd_cancel(WDOG_ID wdog)
ret = OK; ret = OK;
} }
irqrestore(saved_state); irqrestore(state);
return ret; return ret;
} }

View File

@ -92,7 +92,7 @@
WDOG_ID wd_create (void) WDOG_ID wd_create (void)
{ {
FAR wdog_t *wdog; FAR struct wdog_s *wdog;
irqstate_t state; irqstate_t state;
/* These actions must be atomic with respect to other tasks and also with /* These actions must be atomic with respect to other tasks and also with
@ -113,7 +113,7 @@ WDOG_ID wd_create (void)
* count of free timers all with interrupts disabled. * count of free timers all with interrupts disabled.
*/ */
wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist); wdog = (FAR struct wdog_s *)sq_remfirst(&g_wdfreelist);
DEBUGASSERT(g_wdnfree > 0); DEBUGASSERT(g_wdnfree > 0);
g_wdnfree--; g_wdnfree--;
irqrestore(state); irqrestore(state);
@ -139,7 +139,7 @@ WDOG_ID wd_create (void)
/* We do not require that interrupts be disabled to do this. */ /* We do not require that interrupts be disabled to do this. */
irqrestore(state); irqrestore(state);
wdog = (FAR wdog_t *)kmalloc(sizeof(wdog_t)); wdog = (FAR struct wdog_s *)kmalloc(sizeof(struct wdog_s));
/* Did we get one? */ /* Did we get one? */

View File

@ -132,9 +132,11 @@ int wd_delete(WDOG_ID wdog)
sched_kfree(wdog); sched_kfree(wdog);
} }
/* This was a pre-allocated timer. */ /* This was a pre-allocated timer. This function should not be called for
* statically allocated timers.
*/
else else if (!WDOG_ISSTATIC(wdog))
{ {
/* Put the timer back on the free list and increment the count of free /* Put the timer back on the free list and increment the count of free
* timers, all with interrupts disabled. * timers, all with interrupts disabled.

View File

@ -98,10 +98,10 @@ int wd_gettime(WDOG_ID wdog)
* that we are looking for * that we are looking for
*/ */
wdog_t *curr; FAR struct wdog_s *curr;
int delay = 0; int delay = 0;
for (curr = (wdog_t*)g_wdactivelist.head; curr; curr = curr->next) for (curr = (FAR struct wdog_s *)g_wdactivelist.head; curr; curr = curr->next)
{ {
delay += curr->lag; delay += curr->lag;
if (curr == wdog) if (curr == wdog)

View File

@ -83,7 +83,7 @@ uint16_t g_wdnfree;
* in the pool is a configuration item. * in the pool is a configuration item.
*/ */
static FAR wdog_t g_wdpool[CONFIG_PREALLOC_WDOGS]; static struct wdog_s g_wdpool[CONFIG_PREALLOC_WDOGS];
/************************************************************************ /************************************************************************
* Private Functions * Private Functions
@ -114,7 +114,7 @@ static FAR wdog_t g_wdpool[CONFIG_PREALLOC_WDOGS];
void wd_initialize(void) void wd_initialize(void)
{ {
FAR wdog_t *wdog = g_wdpool; FAR struct wdog_s *wdog = g_wdpool;
int i; int i;
/* Initialize watchdog lists */ /* Initialize watchdog lists */

View File

@ -115,22 +115,22 @@ typedef void (*wdentry4_t)(int argc, uint32_t arg1, uint32_t arg2,
static inline void wd_expiration(void) static inline void wd_expiration(void)
{ {
FAR wdog_t *wdog; FAR struct wdog_s *wdog;
/* Check if the watchdog at the head of the list is ready to run */ /* Check if the watchdog at the head of the list is ready to run */
if (((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) if (((FAR struct wdog_s *)g_wdactivelist.head)->lag <= 0)
{ {
/* Process the watchdog at the head of the list as well as any /* Process the watchdog at the head of the list as well as any
* other watchdogs that became ready to run at this time * other watchdogs that became ready to run at this time
*/ */
while (g_wdactivelist.head && while (g_wdactivelist.head &&
((FAR wdog_t*)g_wdactivelist.head)->lag <= 0) ((FAR struct wdog_s *)g_wdactivelist.head)->lag <= 0)
{ {
/* Remove the watchdog from the head of the list */ /* Remove the watchdog from the head of the list */
wdog = (FAR wdog_t*)sq_remfirst(&g_wdactivelist); wdog = (FAR struct wdog_s *)sq_remfirst(&g_wdactivelist);
/* If there is another watchdog behind this one, update its /* If there is another watchdog behind this one, update its
* its lag (this shouldn't be necessary). * its lag (this shouldn't be necessary).
@ -138,7 +138,7 @@ static inline void wd_expiration(void)
if (g_wdactivelist.head) if (g_wdactivelist.head)
{ {
((FAR wdog_t*)g_wdactivelist.head)->lag += wdog->lag; ((FAR struct wdog_s *)g_wdactivelist.head)->lag += wdog->lag;
} }
/* Indicate that the watchdog is no longer active. */ /* Indicate that the watchdog is no longer active. */
@ -227,13 +227,13 @@ static inline void wd_expiration(void)
int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...) int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
{ {
va_list ap; va_list ap;
FAR wdog_t *curr; FAR struct wdog_s *curr;
FAR wdog_t *prev; FAR struct wdog_s *prev;
FAR wdog_t *next; FAR struct wdog_s *next;
int32_t now; int32_t now;
irqstate_t saved_state; irqstate_t state;
int i; int i;
/* Verify the wdog */ /* Verify the wdog */
@ -249,7 +249,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
* the critical section is established. * the critical section is established.
*/ */
saved_state = irqsave(); state = irqsave();
if (WDOG_ISACTIVE(wdog)) if (WDOG_ISACTIVE(wdog))
{ {
wd_cancel(wdog); wd_cancel(wdog);
@ -309,7 +309,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
else else
{ {
now = 0; now = 0;
prev = curr = (FAR wdog_t*)g_wdactivelist.head; prev = curr = (FAR struct wdog_s *)g_wdactivelist.head;
/* Advance to positive time */ /* Advance to positive time */
@ -342,17 +342,17 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
/* Insert the new watchdog in the list */ /* Insert the new watchdog in the list */
if (curr == (FAR wdog_t*)g_wdactivelist.head) if (curr == (FAR struct wdog_s *)g_wdactivelist.head)
{ {
/* Insert the watchdog at the head of the list */ /* Insert the watchdog at the head of the list */
sq_addfirst((FAR sq_entry_t*)wdog, &g_wdactivelist); sq_addfirst((FAR sq_entry_t *)wdog, &g_wdactivelist);
} }
else else
{ {
/* Insert the watchdog in mid- or end-of-queue */ /* Insert the watchdog in mid- or end-of-queue */
sq_addafter((FAR sq_entry_t*)prev, (FAR sq_entry_t*)wdog, sq_addafter((FAR sq_entry_t *)prev, (FAR sq_entry_t *)wdog,
&g_wdactivelist); &g_wdactivelist);
} }
@ -394,7 +394,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
sched_timer_resume(); sched_timer_resume();
#endif #endif
irqrestore(saved_state); irqrestore(state);
return OK; return OK;
} }
@ -426,7 +426,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
#ifdef CONFIG_SCHED_TICKLESS #ifdef CONFIG_SCHED_TICKLESS
unsigned int wd_timer(int ticks) unsigned int wd_timer(int ticks)
{ {
FAR wdog_t *wdog; FAR struct wdog_s *wdog;
int decr; int decr;
/* Check if there are any active watchdogs to process */ /* Check if there are any active watchdogs to process */
@ -435,7 +435,7 @@ unsigned int wd_timer(int ticks)
{ {
/* Get the watchdog at the head of the list */ /* Get the watchdog at the head of the list */
wdog = (FAR wdog_t*)g_wdactivelist.head; wdog = (FAR struct wdog_s *)g_wdactivelist.head;
#ifndef CONFIG_SCHED_TICKLESS_ALARM #ifndef CONFIG_SCHED_TICKLESS_ALARM
/* There is logic to handle the case where ticks is greater than /* There is logic to handle the case where ticks is greater than
@ -462,7 +462,7 @@ unsigned int wd_timer(int ticks)
/* Return the delay for the next watchdog to expire */ /* Return the delay for the next watchdog to expire */
return g_wdactivelist.head ? return g_wdactivelist.head ?
((FAR wdog_t*)g_wdactivelist.head)->lag : 0; ((FAR struct wdog_s *)g_wdactivelist.head)->lag : 0;
} }
#else #else
@ -474,7 +474,7 @@ void wd_timer(void)
{ {
/* There are. Decrement the lag counter */ /* There are. Decrement the lag counter */
--(((FAR wdog_t*)g_wdactivelist.head)->lag); --(((FAR struct wdog_s *)g_wdactivelist.head)->lag);
/* Check if the watchdog at the head of the list is ready to run */ /* Check if the watchdog at the head of the list is ready to run */

View File

@ -51,63 +51,11 @@
/************************************************************************ /************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
************************************************************************/ ************************************************************************/
/* Configuration ********************************************************/
#ifndef CONFIG_PREALLOC_WDOGS
# define CONFIG_PREALLOC_WDOGS 32
#endif
#ifndef CONFIG_WDOG_INTRESERVE
# if CONFIG_PREALLOC_WDOGS > 16
# define CONFIG_WDOG_INTRESERVE 4
# elif CONFIG_PREALLOC_WDOGS > 8
# define CONFIG_WDOG_INTRESERVE 2
# else
# define CONFIG_WDOG_INTRESERVE 1
# endif
#endif
#if CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
# error CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
#endif
/* Watchdog Definitions *************************************************/
/* Flag bits for the flags field of struct wdog_s */
#define WDOGF_ACTIVE (1 << 0) /* Watchdog is actively timing */
#define WDOGF_ALLOCED (1 << 1) /* 0:Pre-allocated, 1:Allocated */
#define WDOG_SETACTIVE(w) do { (w)->flags |= WDOGF_ACTIVE; } while (0)
#define WDOG_SETALLOCED(w) do { (w)->flags |= WDOGF_ALLOCED; } while (0)
#define WDOG_CLRACTIVE(w) do { (w)->flags &= ~WDOGF_ACTIVE; } while (0)
#define WDOG_CLRALLOCED(w) do { (w)->flags &= ~WDOGF_ALLOCED; } while (0)
#define WDOG_ISACTIVE(w) (((w)->flags & WDOGF_ACTIVE) != 0)
#define WDOG_ISALLOCED(w) (((w)->flags & WDOGF_ALLOCED) != 0)
/************************************************************************ /************************************************************************
* Public Type Declarations * Public Type Declarations
************************************************************************/ ************************************************************************/
/* This is the watchdog structure. The WDOG_ID is a pointer to a
* watchdog structure.
*/
struct wdog_s
{
FAR struct wdog_s *next; /* Support for singly linked lists. */
wdentry_t func; /* Function to execute when delay expires */
#ifdef CONFIG_PIC
FAR void *picbase; /* PIC base address */
#endif
int lag; /* Timer associated with the delay */
uint8_t flags; /* See WDOGF_* definitions above */
uint8_t argc; /* The number of parameters to pass */
uint32_t parm[CONFIG_MAX_WDOGPARMS];
};
typedef struct wdog_s wdog_t;
/************************************************************************ /************************************************************************
* Public Variables * Public Variables
************************************************************************/ ************************************************************************/