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.
</p>
<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="#wdstart">4.3.5.3 wd_start</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>
</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>
<b>Function Prototype:</b>
<pre>
#include &lt;nuttx/wdog.h&gt;
WDOG_ID wd_create(void);
void wd_static(FAR struct wdog_s *wdog);
</pre>
<p>
<b>Description:</b> The wd_create function will create a watchdog
by allocating the appropriate resources for the 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>);
</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>
<b>Input Parameters:</b> None.
<p>
<b>Returned Value:</b>
<ul>
<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.
<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.
</ul>
<p>
@ -2760,10 +2762,11 @@ initialization time).
</pre>
<p>
<b>Description:</b> The wd_delete function will deallocate a
watchdog. The watchdog will be removed from the timer queue if
has been started.
<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.
<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>
<ul>
<li><code>wdog</code>. The watchdog ID to delete. This is actually a

View File

@ -48,11 +48,59 @@
/****************************************************************************
* 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
****************************************************************************/
/* The arguments are passed as uint32_t values. For systems where the
* sizeof(pointer) < sizeof(uint32_t), the following union defines the
* 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, ...);
/* 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' */
typedef FAR struct wdog_s *WDOG_ID;

View File

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

View File

@ -92,7 +92,7 @@
WDOG_ID wd_create (void)
{
FAR wdog_t *wdog;
FAR struct wdog_s *wdog;
irqstate_t state;
/* 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.
*/
wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist);
wdog = (FAR struct wdog_s *)sq_remfirst(&g_wdfreelist);
DEBUGASSERT(g_wdnfree > 0);
g_wdnfree--;
irqrestore(state);
@ -139,7 +139,7 @@ WDOG_ID wd_create (void)
/* We do not require that interrupts be disabled to do this. */
irqrestore(state);
wdog = (FAR wdog_t *)kmalloc(sizeof(wdog_t));
wdog = (FAR struct wdog_s *)kmalloc(sizeof(struct wdog_s));
/* Did we get one? */

View File

@ -132,9 +132,11 @@ int wd_delete(WDOG_ID 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
* timers, all with interrupts disabled.

View File

@ -98,10 +98,10 @@ int wd_gettime(WDOG_ID wdog)
* that we are looking for
*/
wdog_t *curr;
FAR struct wdog_s *curr;
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;
if (curr == wdog)

View File

@ -83,7 +83,7 @@ uint16_t g_wdnfree;
* 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
@ -114,7 +114,7 @@ static FAR wdog_t g_wdpool[CONFIG_PREALLOC_WDOGS];
void wd_initialize(void)
{
FAR wdog_t *wdog = g_wdpool;
FAR struct wdog_s *wdog = g_wdpool;
int i;
/* 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)
{
FAR wdog_t *wdog;
FAR struct wdog_s *wdog;
/* 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
* other watchdogs that became ready to run at this time
*/
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 */
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
* its lag (this shouldn't be necessary).
@ -138,7 +138,7 @@ static inline void wd_expiration(void)
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. */
@ -228,11 +228,11 @@ static inline void wd_expiration(void)
int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
{
va_list ap;
FAR wdog_t *curr;
FAR wdog_t *prev;
FAR wdog_t *next;
FAR struct wdog_s *curr;
FAR struct wdog_s *prev;
FAR struct wdog_s *next;
int32_t now;
irqstate_t saved_state;
irqstate_t state;
int i;
/* 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.
*/
saved_state = irqsave();
state = irqsave();
if (WDOG_ISACTIVE(wdog))
{
wd_cancel(wdog);
@ -309,7 +309,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
else
{
now = 0;
prev = curr = (FAR wdog_t*)g_wdactivelist.head;
prev = curr = (FAR struct wdog_s *)g_wdactivelist.head;
/* Advance to positive time */
@ -342,7 +342,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
/* 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 */
@ -394,7 +394,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
sched_timer_resume();
#endif
irqrestore(saved_state);
irqrestore(state);
return OK;
}
@ -426,7 +426,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
#ifdef CONFIG_SCHED_TICKLESS
unsigned int wd_timer(int ticks)
{
FAR wdog_t *wdog;
FAR struct wdog_s *wdog;
int decr;
/* 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 */
wdog = (FAR wdog_t*)g_wdactivelist.head;
wdog = (FAR struct wdog_s *)g_wdactivelist.head;
#ifndef CONFIG_SCHED_TICKLESS_ALARM
/* 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 g_wdactivelist.head ?
((FAR wdog_t*)g_wdactivelist.head)->lag : 0;
((FAR struct wdog_s *)g_wdactivelist.head)->lag : 0;
}
#else
@ -474,7 +474,7 @@ void wd_timer(void)
{
/* 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 */

View File

@ -51,63 +51,11 @@
/************************************************************************
* 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
************************************************************************/
/* 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
************************************************************************/