Tics Realtime -----


 
Home Services Products Tutorials Contact Us
- - - - -

Tics Realtime Sample Code


Tics Realtime Simple Tasks



/*******************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     taskA continuously prints string to screen,      
 *     and yields to other tasks. (Note that since     
 *     no other tasks are running there are no other     
 *     tasks to yield to, so taskA runs continuously).     
 *                                   
 ********************************************************/


void taskA(void)
{
     while (TRUE) {
          printf("Hello from taskA... ");
          yield();
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     taskA prints string to screen every 200 ms.     
 *                                   
 ********************************************************/


void taskA(void)
{
     while (TRUE) {
          printf("Hello from taskA... ");
          pause(200L);
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     taskA and taskB continuously print to the      
 *     screen and yield to each other.               
 *                                   
 ********************************************************/


void taskA(void)
{
     while (TRUE) {
          printf("Hello from taskA... ");
          yield();
     }
}
 
void taskB(void)
{
     while (TRUE) {
          printf("Hello from taskB... ");
          yield();
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     taskA prints string to screen every 200 ms,     
 *     while taskB continuously prints and yields.     
 *                                   
 ********************************************************/


void taskA(void)
{
     while (TRUE) {
          printf("Hello from taskA... ");
          pause(100L);
     }
}
 
void taskB(void)
{
     while (TRUE) {
          printf("Hello from taskB... ");
          yield();
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


Tics Realtime Task Instance Examples

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Illustrates how multiple instances of the same     
 *     task can be used to manage multiple           
 *     analog channels using the task number method.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

typeFreeMsg MsgSpace[NUM_MSGS];

typedef struct structAnalog {
     int channelNum, gain;
     long sampleInterval;
} typeAnalog;

typeAnalog Analog[] = {
     0, 50, 100L,     /* Channel 0 */
     1, 60, 400L,     /* Channel 1 */
     2, 70, 1000L     /* Channel 2 */
};


/********************************************************
 *                                   
 *     The task below is a single generic task that     
 *     accesses its data based on its task number,     
 *     which is the second argument to makeTask (see     
 *     makeTask in main below). The task number for     
 *     the active task is contained in the global      
 *     ActiveTcb->taskNum. Thus, a task determines      
 *     which instance (in this example 0, 1, or 2) by     
 *     its task number. Note that although the code     
 *     below is the same for each task instance,     
 *     the data is different, and so the gain,      
 *     channel, and sample interval are different for     
 *     each task instance.                    
 *                                   
 *     The 3 instances of this task are started in     
 *     main below.                         
 *                                   
 ********************************************************/

void readAnalogChannel(void)
{
     int reading;
     typeAnalog * a;

     a = &Analog[ActiveTcb->taskNum];

     setGain(a->gain);

     while (TRUE) {
          reading = getAnalogReading(a->channelNum);
          processAnalogReading(reading);
          pause(a->sampleInterval);
     }
}

void main()
{
     int i;

     startTics(makeTics(MsgSpace, NUM_MSGS));

     for (i = 0; i < 3; i++) {
          startTask(makeTask(readAnalogChannel, i));
     }

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Illustrates how multiple instances of the same     
 *     task can be used to manage multiple           
 *     analog channels using the tcb->ptr method.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

typeFreeMsg MsgSpace[NUM_MSGS];

typedef struct structAnalog {
     int channelNum, gain;
     long sampleInterval;
} typeAnalog;

typeAnalog Analog[] = {
     0, 50, 100L,     /* Channel 0 */
     1, 60, 400L,     /* Channel 1 */
     2, 70, 1000L     /* Channel 2 */
};


/********************************************************
 *                                   
 *     The task below is a single generic task that     
 *     accesses its data based on its the generic     
 *     pointer ActiveTcb->ptr, which is assigned     
 *     to each individual task instance in main.     
 *                                   
 *     Note that although the code               
 *     below is the same for each task instance,     
 *     the data is different, and so the gain,      
 *     channel, and sample interval are different for     
 *     each task instance.                    
 *                                   
 *     The 3 instances of this task are started in     
 *     main below.                         
 *                                   
 ********************************************************/

void readAnalogChannel(void)
{
     int reading;
     typeAnalog * a;

     a = (typeAnalog *) ActiveTcb->ptr;

     setGain(a->gain);

     while (TRUE) {
          reading = getAnalogReading(a->channelNum);
          processAnalogReading(reading);
          pause(a->sampleInterval);
     }
}

void main()
{
     int i;
     typeTcb * tcb;
     typeAnalog * a;
     static int gain[] = {50, 60, 90};
     static long sampleInterval[] = {100L, 200L, 3000L};

     startTics(makeTics(MsgSpace, NUM_MSGS));

     for (i = 0; i <3; i++) { tcb="startTask(makeTask(readAnalogChannel," i)); tcb->ptr = malloc(sizeof(typeAnalog));
          a = (typeAnalog *) tcb->ptr;
          a->channelNum = i;
          a->gain = gain[i];
          a->sampleInterval = sampleInterval[i];
     }

     suspend();
}

Tics Realtime Sample Isr Code



/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     The code below illustrates how a transmit and     
 *     receive isr for a network might be coded.     
 *                                   
 *     The hardware generates an interrupt to the     
 *     receive isr whenever data can be sent out, at     
 *     which time the receive isr checks the transmit     
 *     queue for requests and processes the request     
 *     at the front of the queue.               
 *                                   
 *     A receive interrupt is generated when a      
 *     complete packet of data has been received.     
 *     The receive isr allocates a data packet, puts     
 *     the received data into the packet, points a msg     
 *     to the packet, and sends the msg to a packet     
 *     processing task.                    
 *                                   
 *     Note that Tics has no requirements involving     
 *     the installation of a driver or isr. You simply     
 *     write the isr code using the "interrupt"     
 *     keyword, and set up the isr vector.          
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define DATA_OUT 1005
#define DATA_IN 1006
#define RCV_INTR_NUM     (0x3e0 / 4)
#define XMIT_INTR_NUM     (0x3f0 / 4)

#define NET_POOL_BLKSIZE 64

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbNetQ, * TcbE;
typeMem * NetPool;

unsigned char NetPoolData[NET_POOL_BLKSIZE * 10];


/********************************************************
 *                                   
 *     T r a n s m i t   I s r                    
 *                                   
 *      The isr below gets an interrupt whenever it     
 *     is ok to transmit more data out over a high     
 *     speed communications channel. The isr checks     
 *     a request queue that tasks (see taskD below)     
 *     send msgs to when data is to be sent out.      
 *     The isr illustrates how a null tcb queue is     
 *     used inside an isr. The null tcb queue is      
 *     created in main below. taskD below sends a     
 *     request to the queue.                    
 *                                   
 ********************************************************/

void interrupt far netXmitIsr(void)
{
     int msgList[] = {DATA_OUT, NULL_MSG};
     typeMsg * msg;

     /* Check the request queue to see if there is any data to
      * send out and if so, get the data packet from the msg and
      * send it out onto the network.
      */
     msg = _rcvMsg(TcbNetQ, 0, msgList, FALSE, TRUE);

     if (msg != NULL) {
          /* Put code here to send msg out onto network. */

          /* Free the data pointed to by the msg. */
          _putMem(&NetPool, msg->pData, FALSE);

          /* Free the msg itself. */
          _freeMsg(msg, FALSE);
     }
     /* Note that _isrRet() is not necessary here because no
      * other tasks were scheduled from within this isr. Contrast
      * this with netIsrRcv below.
      */
}

/********************************************************
 *                                   
 *     R e c e i v e   I s r                    
 *                                   
 *     A receive interrupt is generated when a      
 *     complete packet of data has been received.     
 *     The receive isr allocates a data packet, puts     
 *     the received data into the packet, points a msg     
 *     to the packet, and sends the msg to a packet     
 *     processing task.                    
 *                                   
 ********************************************************/

void interrupt far netRcvIsr(void)
{
     typeMsg * msg;
     unsigned char * packet;

     packet = _getMem(&NetPool, FALSE);
     msg = _makeMsg(TcbE, DATA_IN, FALSE);
     msg->pData = packet;
     _sendMsg(msg, FALSE, FALSE);

     /* Return to the interrupted task, or preempt it if TcbE is
      * of a higher priority. The invocation of _isrRet() below
      * is necessary because taskE was implicitly scheduled
      * by sendMsg and may be of a higher priority than
      * the task that was preempted to enter this isr. If _isrRet()
      * is not invoked, then this isr will return to the preempted
      * task.
      */
     _isrRet();
}

/********************************************************
 *                                   
 *     T r a n s m i t   R e q u e s t   T a s k     
 *                                   
 *     This task generates transmit requests by     
 *     sending msgs to the transmit request queue.     
 *                                   
 ********************************************************/

void taskD(void)
{
     typeMsg * msg;

     while (TRUE) {
          pause(1000L);
          msg = makeMsg(TcbNetQ, DATA_OUT);
          msg->pData = getMem(&NetPool);

          /* Fill packet pointed to by msg->pData here... */

          sendMsg(msg);
        }
}

/********************************************************
 *                                   
 *     P a c k e t   P r o c e s s i n g   T a s k     
 *                                   
 *     This task receives packet msgs from the      
 *     receive isr and processes them.               
 *                                   
 ********************************************************/

void taskE(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(DATA_IN);

          /* Process msg here... */

          /* Free the data packet. */
          putMem(&NetPool, msg->pData);

          /* Free the msg itself. */
          freeMsg(msg);
        }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskD, 0));
     startTask(makeTask(taskE, 0));

     /* Create a queue (a NULL task). */
     TcbNetQ = startTask(makeTask(NULL, 0));

     /* Set interrupt vectors for transmit and receive. */
     setvect(RCV_INTR_NUM, netRcvIsr);
     setvect(XMIT_INTR_NUM, netXmitIsr);

     /* Create a memory pool for network packets. When taskD
      * sends a msg to the TcbNetQ, it points the msg to a
      * packet that will be sent out on the network. */
     NetPool = makeMem(NetPoolData, sizeof(NetPoolData), NET_POOL_BLKSIZE);

     suspend();
}

Tics Realtime Sample Mail Passing



/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Shows simple mail passing between two tasks.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 0

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{

     while (TRUE) {
          freeMail(waitMail(HELLO));
          printf("Received Mail. ");
     }
}

void taskB(void)
{
     while (TRUE) {
          sendMail(makeMail(TcbA, HELLO));
          pause(200L);
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Shows simple mail passing between 3 tasks.     
 *     taskB sends mail with data to taskA with mail     
 *     over-write allowed (default). taskC also sends     
 *     mail to taskA, with over-writes disallowed.     
 *                                   
 *     Note that it is sometimes desirable to           
 *     over-write data. Consider a task that updates      
 *     the screen with     the latest data value,           
 *     which is received from another task via mail.      
 *     If a newer value arrives before the previous      
 *     value is written to the     screen, then it is      
 *     desirable to over-write     the old in the          
 *     mailbox with the new value before it is      
 *     displayed. If msgs were used instead of mail,      
 *     both the old and the new value would be queued      
 *     resulting in the undesirable situation of      
 *     the old value being displayed even though      
 *     the newer value is available.               
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 0

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     int data;
     typeMail * mail;

     while (TRUE) {
          mail = waitMail(HELLO);
          printf("Received mail with data = %d ", mail->iData);
          freeMail(mail);
     }
}

void taskB(void)
{
     typeMail * mail;

     while (TRUE) {
          mail = makeMail(TcbA, HELLO);
          mail->iData = 5;
          sendMail(mail);
          pause(200L);
     }
}
 
void taskC(void)
{
     typeMail * mail;

     while (TRUE) {
          mail = makeMail(TcbA, HELLO);
          mail->iData = 5;

          /* Disallow over-writing of mail that has not yet been
           * read.
           */
           mail->flags |= OVER_WRITE_DISABLE;

          sendMail(mail);

          pause(300L);
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));
     startTask(makeTask(taskC, 0));

     suspend();
}

Miscellaneous Tics Settings


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     int pri = DEF_PRI;

     while (TRUE) {

          /* Dynamically change the priority of this task. */
          ActiveTcb->pri = pri++;
          if (pri > 50) pri = DEF_PRI;
     }
}

void main()
{
     typeTics * tics;

     /* Make the Tics data structure. */
     tics = makeTics(MsgSpace, NUM_MSGS);


     /* Tics defaults timer chip interrupt rate to 5 ms. The code
     * below resets it to 10 ms. For details on computing "timerChipCount"
     * for see the "Tics Realtime Kernel Programmer's Guide".
      */
      tics->timerChipCount = 11932; /* Raw count to be loaded into timer register. */
     tics->uSPerTimerChipCount = 10000; /* Number of uS per interrupt. */
     startTics(tics);

     /* Make task control block for taskA. */
     TcbA = makeTask(taskA, 0);


     /* Raise taskA's priority. (Lower numbers are higher priority). */
     TcbA->pri--;


     /* Enable time-slicing. Note that time-slicing is undesirable.
      * See the chapter on time-slicing in "The Art of Real-time
      * Programming" for further details.
      */
      TcbA->flags |= TIMESLICE;



     /* Set the time-slice interval to 100 ms. (Default is 50 ms). */
     TcbA->timeSlice = 100;



     /* Disable stack checking between context switches. */
     TcbA->flags |= NO_STACK_CHECK;

     /* Now start taskA with the attributes assigned above. Note that
      * any of the above defined attributes can be changed
      * dynamically during program execution.
      */
     startTask(TcbA);

     suspend();
}

Tics Realtime Sample Message Passing

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Shows simple message passing between two tasks.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{

     while (TRUE) {
          freeMsg(waitMsg(HELLO));
          printf("Received msg. ");
     }
}

void taskB(void)
{
     while (TRUE) {
          sendMsg(makeMsg(TcbA, HELLO));
          pause(200L);
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *     Show simple message passing bewtween tasks.     
 *     Keyboard monitoring task has been adding so     
 *     that pressing any key forces a clean exit.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskC(void)
{
     while (TRUE) {
          if (kbhit()) {
               exitTics();
               exit(0);
          }
          pause(200L);
        }
}

void taskA(void)
{

     while (TRUE) {
          freeMsg(waitMsg(HELLO));
          printf("Received msg. ");
     }
}

void taskB(void)
{
     while (TRUE) {
          sendMsg(makeMsg(TcbA, HELLO));
          pause(200L);
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));
     startTask(makeTask(taskC, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing with integer data      
 *     bewtween tasks.                     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;


void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(HELLO);
          printf("Received msg with data = %d ", msg->iData);
          freeMsg(msg);
     }
}

void taskB(void)
{
     int i;
     typeMsg * msg;

     i = 0;

     while (TRUE) {
          msg = makeMsg(TcbA, HELLO);
          msg->iData = i++;
          sendMsg(msg);
          pause(200L);
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing with pointer data      
 *     bewtween tasks.                     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

typedef struct structData {
     int item00, item01, item02;
} typeData;

void taskA(void)
{
     typeMsg * msg;
     typeData * d;

     while (TRUE) {
          msg = waitMsg(HELLO);
          d = (typeData *) msg->pData;
          printf("Received msg with data = %d,%d,%d ",
          d->item00, d->item01, d->item02);
          freeMsg(msg);
     }
}

void taskB(void)
{
     int i;
     typeMsg * msg;
     typeData data;

     data.item00 = 5;
     data.item01 = 6;
     data.item02 = 7;

     while (TRUE) {
          msg = makeMsg(TcbA, HELLO);
          msg->pData = &data;
          sendMsg(msg);
          pause(200L);
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task can receive more     
 *     than one message number.               
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define START 1000
#define STOP  1001

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void startMotor(int motorNum)
{
     /* Start motor according to its motor number. */
     printf("Motor number %d started.  ", motorNum);
}

void stopMotor(void)
{
     /* Motor number not require to stop motor. */
     printf("Motor stopped.  ");
}

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(ANY_MSG);

          switch (msg->msgNum) {

          case START:
               startMotor(msg->iData); /* Pass motor number. */
               break;

          case STOP:
               stopMotor();
               break;
          }

          freeMsg(msg);
     }
}

void taskB(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = makeMsg(TcbA, START);
          msg->iData = 5;
          sendMsg(msg);
          pause(10000L); /* Wait 10 seconds before stopping. */
          sendMsg(makeMsg(TcbA, STOP));
          pause(5000L); /* Wait 5 seconds before starting. */
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task must reply to     
 *     the sender task.                    
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000
#define HELLO_BACK 1001

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(HELLO);
          sendMsg(makeMsg(msg->senderTcb, HELLO_BACK));
          freeMsg(msg);
     }
}

void taskB(void)
{
     while (TRUE) {
          sendMsg(makeMsg(TcbA, HELLO));
          freeMsg(waitMsg(HELLO_BACK));
     }
}
 
void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the sender task fakes out the           
 *     receiving task who responds to taskC           
 *     instead of taskB. See code below for details.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000
#define HELLO_BACK 1001
#define CONTINUE 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA, * TcbC;

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(HELLO);
          sendMsg(makeMsg(msg->senderTcb, HELLO_BACK));
          freeMsg(msg);
     }
}

void taskB(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = makeMsg(TcbA, HELLO);
          msg->senderTcb = TcbC;
          sendMsg(msg);
          freeMsg(waitMsg(CONTINUE));
     }
}
 
void taskC(void)
{
     while (TRUE) {
          freeMsg(waitMsg(HELLO_BACK));
          sendMsg(makeMsg(TcbA, CONTINUE));
     }
}

void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));
     TcbC = startTask(makeTask(taskC, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task (taskA) will only      
 *     wait 1 second for a message, after which it      
 *     prints a timeout error string to the screen.     
 *                                   
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000
#define HELLO_BACK 1001
#define CONTINUE 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitTimedMsg(HELLO, 1000L);
          if (msg->msgNum == TIMEOUT) {
               freeMsg(msg);
               printf("TIMEOUT error. Exiting.\n");
               exitTics();
               exit(0);
          }
          freeMsg(msg);
     }
}

void taskB(void)
{
     long pauseValue = 1000L;

     while (TRUE) {
          sendMsg(makeMsg(TcbA, HELLO));
          pause(pauseValue);
          pauseValue += 100L;
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task will only wait     
 *     1 second for a message, after which it prints     
 *     a timeout error string to the screen. The      
 *     distinction between this example and the     
 *     one above is that here taskA will accept     
 *     any of 3 messages before it times out, and     
 *     therefore, uses _waitTimedMsg which accepts     
 *     a list of messages.                    
 *                                   
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define START 1000
#define STOP 1001
#define CONTINUE 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     typeMsg * msg;
     int msgList[] = {START, STOP, CONTINUE, NULL_MSG};

     while (TRUE) {
          msg = _waitTimedMsg(MSGQ, msgList, 1000L, TRUE, TRUE);
          if (msg->msgNum == TIMEOUT) {
               freeMsg(msg);
               printf("TIMEOUT error. Exiting.\n");
               exitTics();
               exit(0);
          }

          switch (msg->msgNum) {
          case START:      /* Handle START msg. */ break;
          case STOP: /* Handle STOP msg. */ break;
          case CONTINUE: /* Handle CONTINUE msg. */ break;
          }

          freeMsg(msg);
     }
}

void taskB(void)
{
     long pauseValue = 1000L;

     while (TRUE) {
          sendMsg(makeMsg(TcbA, START));
          pause(pauseValue);
          pauseValue += 100L;
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task wants to peek     
 *     into its message queue. This cannot be done     
 *     with waitMsg because if the message is not      
 *     in the queue, the task will suspend until the     
 *     desired message is received. The code below      
 *     uses rcvMsg, which always returns - a NULL is     
 *     returned if the message is not in the queue,      
 *     otherwise, a pointer to the message is           
 *     returned.                         
 *                                   
 *     N o t e s                         
 *                                   
 *     rcvMsg is seldom used. Use waitMsg instead.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define START 1000
#define STOP 1001
#define CONTINUE 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = rcvMsg(START);
          if (msg == NULL) {
               printf("Have not yet received msg.  ");
               pause(200L);
          }
          else {
               freeMsg(msg);
               printf("Got msg.\n");
               exitTics();
               exit(0);
          }
     }
}

void taskB(void)
{
     while (TRUE) {
          pause(200L);
          sendMsg(makeMsg(TcbA, START));
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Shows simple message passing bewtween tasks      
 *     where the destination task wants to peek     
 *     into its message queue AND not remove the      
 *     message. This cannot be done with waitMsg      
 *     because if the message is not in the queue,      
 *     the task will suspend until the     desired message 
 *     is received. Nor can it be done with rcvMsg     
 *     since rcvMsg removes the message from the     
 *     queue if it is there. The code below uses      
 *     _rcvMsg, which optionally leaves the message     
 *     in the queue.                         
 *                                   
 *                                   
 *     N o t e s                         
 *                                   
 *     rcvMsg is seldom used. Use waitMsg instead.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define START 1000
#define STOP 1001
#define CONTINUE 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskA(void)
{
     int msgList[] = {START, NULL_MSG};
     typeMsg * msg;

     while (TRUE) {
          msg = _rcvMsg(ActiveTcb, MSGQ, msgList, TRUE, FALSE);
          if (msg == NULL) {
               printf("Have not yet received msg.  ");
               pause(200L);
          }
          else {
               /* We got the START msg. At this point the
                * msg is still in the queue. We can leave it
                * there or remove it as shown below. */
               removeMsg(msg);

               printf("Got msg. \n");

               /* Note that removing the msg from the queue
                * does not free it. You must free the msg after
                * you are done with it. */
               freeMsg(msg);

               exitTics();
               exit(0);
          }
     }
}

void taskB(void)
{
     while (TRUE) {
          pause(200L);
          sendMsg(makeMsg(TcbA, START));
     }
}
 
void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Shows how to apply and use msg priorities.     
 *     This example also shows how a task's priority     
 *     can be changed dynamically.               
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define START_MOTOR 1000
#define STOP_MOTOR 1001
#define EMERGENCY_STOP 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void interrupt far errorDectect(void)
{
     typeMsg * msg;

     /* This isr is entered when hardware detects a critical error.
      * Motor must be stopped immediately and brake applied.
      */

      msg = _makeMsg(TcbA, EMERGENCY_STOP, FALSE);

      /* Setting the msg flag BUMP_PRI (see code line following
       * this comment) tells sendMsg that the destination
       * task's priority is to be temporarily forced high so that
       * the destination task (taskA in this case) runs next. After
       * taskA is scheduled, its priority is set to its previous value.
       * Note also that setting the BUMP_PRI flag is an option. If
       * BUMP_PRI is not set, but the msg priority is set high, as
       * is done below in the statement "msg->pri = HI_USER_PRI", then
       * the msg is still forced to the front of taskA's msg queue,
       * however, taskA may not be the next task to run.
       */
      msg->flags |= BUMP_PRI;

      /* Raise msg priority so that msg goes to the front of
       * taskA's msg queue.
       */
       msg->pri = HI_USER_PRI;
       _sendMsg(msg, FALSE, FALSE);
}

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(ANY_MSG);

          switch (msg->msgNum) {

          case START_MOTOR:
               /* Perform motor startup functions. */
               break;

          case STOP_MOTOR:
               /* Perform motor shutdown functions. */
               break;

          case EMERGENCY_STOP:
               /* Shut off motor and
                * apply brake to immediately stop motor. */
               break;
          }

          freeMsg(msg);
     }
}


void main() 
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Illusrates the use of dormant msgs.          
 *     A dormant msg is one which remains invisible     
 *     until activated. This is useful where very      
 *     high speed notifications are required, since     
 *     all the overhead of putting the msg into     
 *     the destination task's queue and scheduling the     
 *     task has been done beforehand.               
 *                                   
 *     Note that normal msgs are typically fast      
 *     enough. Only use this technique when normal     
 *     msgs wont do.                         
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define SHUT_DOWN 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbShutDown;
typeMsg * ShutDownMsg;

void interrupt far errorDetect(void)
{
     /* Do not send msg, as it has already been sent. Simply activate it. */
     activateMsg(ShutDownMsg);
}

void shutDown(void)
{
     freeMsg(waitMsg(SHUT_DOWN));

     /* Do system shutdown here... */

     printf("System shutdown.\n");
     exitTics();
     exit(0);
}

void simulateInterrupt(void)
{
     while (TRUE) {
          pause(2000L);
          errorDetect();
        }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbShutDown = startTask(makeTask(shutDown, 0));
     startTask(makeTask(simulateInterrupt, 0));

     ShutDownMsg = makeMsg(TcbShutDown, SHUT_DOWN);
     deActivateMsg(ShutDownMsg);
     sendMsg(ShutDownMsg);

     suspend();
}


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *                                   
 *     P u r p o s e                         
 *                                   
 *      Illustrates msg forwarding and how          
 *     the destination task can wait for any           
 *     msg from a given set.                    
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

#define PRINT_DONE 1000
#define PRINT_ERROR 1001
#define PRINT 1002

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * PrintServerTcb, * PrintDriverTcb;

void printDriver(void)
{
     typeMsg * msg;

     while (TRUE) {
          msg = waitMsg(PRINT);
          /* Talk to print driver here... */

          /* Use a short-cut to respond. We do not reccomend
           * this method - shown here for illustration. */
          msg->msgNum = PRINT_DONE;
          forwardMsg(msg->senderTcb, msg);
     }
}

void printServer(void)
{
     int msgList[] = {PRINT_DONE, PRINT_ERROR, NULL_MSG};
     typeMsg * msg;
     typeTcb * senderTcb;

     while (TRUE) {
          msg = waitMsg(PRINT);
          senderTcb = msg->senderTcb;
          forwardMsg(PrintDriverTcb, msg);

          msg = _waitMsg(MSGQ, msgList, TRUE, TRUE);

          switch (msg->msgNum) {

          case PRINT_DONE:
               forwardMsg(senderTcb, msg);
               break;

          case PRINT_ERROR:
               setError("Printer error.\n");
               break;

          default:
               setError("PrintServer - unknown msg.\n");
               break;
          }
     }
}

void taskA(void)
{
     char filename[] = "myfile.doc";
     typeMsg * msg;

     while (TRUE) {
          msg = makeMsg(PrintServerTcb, PRINT);
          msg->pData = filename;
          sendMsg(msg);
          freeMsg(waitMsg(PRINT_DONE));
        }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     PrintServerTcb = startTask(makeTask(printServer, 0));
     PrintDriverTcb = startTask(makeTask(printDriver, 0));
     startTask(makeTask(taskA, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     The code below illustrates how msgs can be     
 *     sent to a task without the task being           
 *     scheduled. This capability is seldom useful.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define MSG00 1001
#define MSG01 1002
#define MSG02 1003
#define BEGIN 1004

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbA;

void taskB(void)
{
     typeMsg * msg;

     while (TRUE) {
          /* The following 3 code blocks queue up the msgs
           * MSG00, MSG01, MSG02 to taskA without scheduling the
           * task. This is accomplished by setting the
           * NO_MSG_NOTIFY flag as shown below.
           * This means that the msgs MSG00, MSG01, MSG02
           * are put into taskA's msg queue, but taskA remains
           * suspended. Finally, the msg BEGIN is sent without the
           * NO_MSG_NOTIFY flag set, which will schedule taskA
           * to run. Note that when taskA runs it will have 4 msgs
           * in its queue and that it will not suspend on each
           * waitMsg call; it will return immediately with the msg
           * since the desired msg is already in the queue.
           */
          msg = makeMsg(TcbA, MSG00);
          msg->flags |= NO_MSG_NOTIFY;
          sendMsg(msg);

          msg = makeMsg(TcbA, MSG01);
          msg->flags |= NO_MSG_NOTIFY;
          sendMsg(msg);

          msg = makeMsg(TcbA, MSG02);
          msg->flags |= NO_MSG_NOTIFY;
          sendMsg(msg);

          sendMsg(makeMsg(TcbA, BEGIN));

          /* Let other tasks of the same priority run. */
                yield();
     }
}
 
void taskA(void)
{
     while (TRUE) {
          /* Note that the msgs below are retrieved in reverse order;
           * that is, the msgs were put into the queue by taskB in
           * the order MSG00, MSG01, MSG02, BEGIN, but are retrieved
           * in the reverse order. This is done to illustrate how msgs
           * can be retrieved by name. Of course, the msgs could
           * have been retrieved in the correct order also.
           * To retrieve msgs in fifo order when the names are
           * not known, wait for ANY_MSG, i.e.,  waitMsg(ANY_MSG),
           * then use msg->msgNum to determine the msg number.
           */
          freeMsg(waitMsg(BEGIN));
          freeMsg(waitMsg(MSG02));
          freeMsg(waitMsg(MSG01));
          freeMsg(waitMsg(MSG00));
     }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbA = startTask(makeTask(taskA, 0));
     startTask(makeTask(taskB, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     The code below illustrates how a receiving     
 *     task can throttle msgs using semaphores. This     
 *     method is inferior to standard throttling,     
 *     which is illustrated in the second example.     
 *                                   
 *     In this example, a semaphore called "Port"     
 *     is created with a count of 8. Sending tasks     
 *     must acquire Port before sending and the     
 *     receiving task must release Port after          
 *     receiving the msg. The effect is that no more     
 *     than 8 msgs are allowed in the receiving tasks     
 *     queue.                              
 *                                   
 *     The semaphore is started in main by creating     
 *     an instance of the semaphore manager task     
 *     "semMgr". The count and maxCount are set as     
 *     shown. maxCount is used for error detection     
 *     and must always be set to the same value     
 *     as count.                         
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define HELLO 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * Port, * TcbA, * TcbB, * TcbC;

void taskA(void)
{
     typeMsg * msg;

     while (TRUE) {
          pause(1000L);
          while ((msg = rcvMsg(HELLO)) != NULL) {
               printf("Got msg... ");
               freeMsg(msg);
               releaseSem(Port);
          }
     }
}

void taskB(void)
{
     while (TRUE) {
          acquireSem(Port);
          sendMsg(makeMsg(TcbA, HELLO));
          yield();
     }
}

void taskC(void)
{
     while (TRUE) {
          acquireSem(Port);
          sendMsg(makeMsg(TcbA, HELLO));
          yield();
     }
}

void main(void)
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     Port = makeTask(semMgr, 0);
     Port->semCount = Port->semCountMax = 8;
     startTask(Port);

     TcbA = startTask(makeTask(taskA, 0));
     TcbB = startTask(makeTask(taskB, 0));
     TcbC = startTask(makeTask(taskC, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     The code below illustrates how a receiving     
 *     task can throttle msgs using standard          
 *     throttling. This method is superior to the     
 *     semaphore method because it is faster, simpler,     
 *      and can be used from within an isr.          
 *                                   
 *     Throttling is accomplished by setting the      
 *     msgCount field of the head msg. (The head msg     
 *     is the head of the doubly linked list msg      
 *     queue). If the msgCount     field is 0, sendMsg      
 *     will not send the msg and will return a NULL.      
 *                                   
 *     Note that it is up the the sender (in this     
 *     case the isr) to check the destination task's     
 *     msg count and refrain from sending if a low     
 *     water mark has been reached.               
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define DATA 1000

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbDataHandler;

void sendDataMsg(int data)
{
     typeMsg * msg;

     msg = makeMsg(TcbDataHandler, DATA);
     msg->iData = data;
     sendMsg(msg);
}

void interrupt far rcvIsr(void)
{
     char data;
     static int state = 0;

     typeMsg * headPtr;

     data = getData();

     headPtr = TcbDataHandler->msgTable[0];

     switch (state) {

     case 0:          /* Throttling not in effect.     */
          sendDataMsg(data);
          if (headPtr->msgCount <3) { sendXoffToDataSource(); state="1;" } break; case 1: /* Throttling is in effect. */ if (headPtr->msgCount >= 3) {
               sendDataMsg(data);
               sendXonToDataSource();
               state = 0;
          }
     }
}

void dataHandler(void)
{
     typeMsg  * msg;

     while (TRUE) {
          msg = waitMsg(DATA);
          processData(msg);
          freeMsg(msg);
     }
}

void main(void)
{
     typeMsg * msgHead;

     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbDataHandler = startTask(makeTask(dataHandler, 0));
     msgHead = TcbDataHandler->msgTable[0];

     /* Do not allow more than 8 msgs in the msg queue.     */
     msgHead->msgCount = 8;

     suspend();
}

Tics Realtime Sample Timer Code


/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e                     
 *                                   
 *      Copyright © 2000 Tics Realtime.                
 *     All rights reserved.                                
 *                                   
 *     Shows simple use of pause.                          
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

typeFreeMsg MsgSpace[NUM_MSGS];

void taskA(void)
{
     int data = 0;

     while (TRUE) {
          pause(100L);
          printf("Data value is %d   ", data++);
          if (data > 100) { exitTics(); exit(0);}
     }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e                  
 *                                   
 *     Copyright © 2000 Tics Realtime.             
 *     All rights reserved.                             
 *                                   
 *     Shows simple use of one-shot timer.              
 *                                   
 *     One-shot timers are typically used internally    
 *     by Tics to implement time-outs. For example,     
 *     Tics uses a one-shot timer to implement          
 *     the function "waitTimedMsg". The code below      
 *     implements a watchdog timer. The interrupt       
 *     service routine "watchDogIsr" is entered         
 *     once each second due to an external interrupt.   
 *     Concurrently, a task runs that waits             
 *     either for a STROBE message from the interrupt   
 *     service routine, or a TIMEOUT message. The       *  
 *     TIMEOUT msg is sent to the task after 2 seconds.
 *     If the STROBE msg is received first, then     
 *     all is ok, and the TIMEOUT msg is cancelled,     
 *     otherwise the watchdog did not strobe, and an     
 *     error condition exists.                    
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100
#define STROBE 1001

typeFreeMsg MsgSpace[NUM_MSGS];
typeTcb * TcbWatchDog;

void interrupt far watchDogIsr(void)
{
     typeMsg * msg;

     msg = _makeMsg(TcbWatchDog, STROBE, FALSE);
     _sendMsg(msg, FALSE, FALSE);
}

void taskWatchDog(void)
{
     typeMsg * msg, * timer;
     long seqNum;

     while (TRUE) {
          timer = makeTimer(2000L);
          seqNum = timer->seqNum;
          startTimer(timer);

          msg = waitMsg(ANY_MSG);

          switch (msg->msgNum) {

          case STROBE:
               cancelTimer(timer, seqNum);
               break;

          case TIMEOUT:
               setError("Watchdog timeout error.");
               break;
          }

          freeMsg(msg);
        }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     TcbWatchDog = startTask(makeTask(taskWatchDog, 0));

     suspend();
}

/********************************************************
 *                                   
 *     C o p y r i g h t   N o t i c e               
 *                                   
 *      Copyright © 2000 Tics Realtime.           
 *     All rights reserved.                    
 *                                   
 *     Shows simple use of periodic timer.           
 *                                   
 *     Periodic timers allow for precise timing     
 *     because the timer is restarted inside the timer     
 *     isr itself, as opposed to the programmer      
 *     restarting the timer by using "pause" in a     
 *     loop. Note that the periodic timer is only      
 *     issued once after which a TIMEOUT msg is      
 *     received by the task at the specified interval     
 *     until the timer is cancelled with           
 *     "cancelTimer".                         
 *                                   
 *     See "The Art of Real-time Programming",          
 *     or "The Tics Programmer's Guide" for details.     
 *                                   
 ********************************************************/

#include "tics.h"
#include "ticsmain.h"
#include "ticsext.h"

#define NUM_MSGS 100

typeFreeMsg MsgSpace[NUM_MSGS];

void taskA(void)
{
     typeMsg * timer, * msg;

     timer = makeTimer(2000L);
     timer->flags |= PERIODIC;
     startTimer(timer);

     while (TRUE) {
          msg = waitMsg(TIMEOUT);
          /* Do something... */
          freeMsg(msg);
     }
}

void main()
{
     startTics(makeTics(MsgSpace, NUM_MSGS));

     startTask(makeTask(taskA, 0));

     suspend();
}

Copyright © 2000, Tics Realtime