#include "vxWorks.h"
#include "wdLib.h"
#include "stdio.h"
#include "semLib.h"
#include "taskLib.h"
#include "usrLib.h"
#include "sysLib.h"
/* defines */
#define TASK_WORK_TIME 2 /* 2 ticks */
#define NUM_OF_GIVES 3
/* globals */
LOCAL SEM_ID semId = NULL; /* counting or binary semaphore ID */
LOCAL WDOG_ID wdId = NULL; /* watchdog ID */
LOCAL int syncTaskTid = 0; /* tid of syncTask */
LOCAL int numToGive = NUM_OF_GIVES; /* Number of times semGive is called */
/* forward declaratiuon */
void syncISR(int); /* ISR to unblock syncTask */
void cleanUp (); /* cleanup routine */
void syncTask (); /* task that needs to be synchronized
* with external events */
/*****************************************************************************
* countingSemDemo - demonstrates task synchronization using counting
* semaphores. User can also select to use binary semaphore instead of
* counting semaphore in this demonstration, for comparision between the two
* semaphores.
*
* RETURNS: OK or ERROR
*
*/
STATUS TestCSem (char semType
/* counting semaphore type 'c' or binary semaphore
* type 'b'
*/
)
{
switch (semType)
{
case 'c':
case 'C':
if ((semId = semCCreate (SEM_Q_PRIORITY, 0)) == NULL)
{
perror ("semCCreate");
return (ERROR);
}
break;
case 'b':
case 'B':
if ((semId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)) == NULL)
{
perror ("semBCreate");
return (ERROR);
}
break;
default:
printf ("Unknown semType -- must be 'c' or 'b'\n");
return (ERROR);
}
if ((wdId = wdCreate()) == NULL)
{
perror ("wdCreate");
cleanUp ();
return (ERROR);
}
if ((syncTaskTid = taskSpawn ("tsyncTask", 101, 0,5000,(FUNCPTR) syncTask, 0,0,0,0,0,0,0,0,0,0)) == ERROR)
{
perror ("taskSpawn");
cleanUp();
return (ERROR);
}
/* watchdog simulates hardware interrupts */
if (wdStart (wdId, 1, (FUNCPTR) syncISR, numToGive)
== ERROR)
{
perror ("wdStart");
cleanUp ();
return (ERROR);
}
/* arbitrary delay to allow program to complete before clean up */
taskDelay (sysClkRateGet() + ((TASK_WORK_TIME + 2) * numToGive));
cleanUp();
return (OK);
}
/*****************************************************************************
* syncTask - synchronizes with interrupts using counting or binary
* semaphores.
*/
void syncTask (void)
{
int eventCount = 0;
FOREVER
{
if (semTake (semId, WAIT_FOREVER) == ERROR)
{
perror ("syncTask semTake");
return;
}
/* Do "work" */
taskDelay (TASK_WORK_TIME);
semShow (semId, 1);
eventCount++;
printf ("semaphore taken %d times\n", eventCount);
}
}
/*****************************************************************************
* syncISR - simulates a hardware device which generates interrupts very
* quickly and synchronizes with syncTask using semaphores.
*/
void syncISR(int times)
{
semGive (semId);
times--;
//看门狗定时器需要递归调用
if (times > 0)
{
wdStart (wdId, 1, (FUNCPTR) syncISR, times);
}
}
/*****************************************************************************
* cleanUP - deletes the syncTask, deletes the semaphore and the watchdog timer
* previously created by countingSemDemo.
*/
void cleanUp ()
{
if (syncTaskTid)
taskDelete (syncTaskTid);
if (semId)
semDelete (semId);
if (wdId)
wdDelete (wdId);
}