Chapter 6 intertask communication sysnchronization
This presentation is the property of its rightful owner.
Sponsored Links
1 / 41

Chapter 6 Intertask Communication & Sysnchronization PowerPoint PPT Presentation


  • 86 Views
  • Uploaded on
  • Presentation posted in: General

Chapter 6 Intertask Communication & Sysnchronization. Semaphores, message mailboxes, and message queue. Figure 6.1 use of event control blocks (ECB). Event Control Blocks. Each semaphore, mailbox, and queue is assigned an ECB. typedef struct {

Download Presentation

Chapter 6 Intertask Communication & Sysnchronization

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Chapter 6 intertask communication sysnchronization

Chapter 6Intertask Communication & Sysnchronization

Semaphores, message mailboxes, and message queue


Figure 6 1 use of event control blocks ecb

Figure 6.1 use of event control blocks (ECB)


Event control blocks

Event Control Blocks

  • Each semaphore, mailbox, and queue is assigned an ECB

typedef struct {

void *OSEventPtr; /* Ptr to message or queue structure */

INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* Wait list for event to occur */

INT16U OSEventCnt; /* Count (when event is a semaphore) */

INT8U OSEventType; /* Event type */

INT8U OSEventGrp; /* Group for wait list */

} OS_EVENT;

  • OSEventPtr: only used when the ECB is assigned to a mailbox or a queue

  • OSEventTbl[] and OSEventGrp are similar to OSRdyTbl[ and OSRdyGrp, respectively

  • OSEventCnt: used to hold the semaphore count

  • OSEventType: contains the type associated with the ECB

    • OS_EVENT_SEM, OS_EVENT_TYPE_MBOX, OS_EVENT_TYPE_Q


Figure 6 2 wait list for task waiting for an event to occur

Figure 6.2 Wait list for task waiting for an event to occur


Chapter 6 intertask communication sysnchronization

pevent->OSEventGrp |= OSMapTbl[prio >> 3];

pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

Making a task wait for an event

Removing a task from a wait list

if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) {

pevent->OSEventGrp &= ~OSMapTbl[prio >> 3];

}

Finding the highest priority task waiting for the event

y = OSUnMapTbl[pevent->OSEventGrp];

x = OSUnMapTbl[pevent->OSEventTbl[y]];

prio = (y << 3) + x;


Figure 6 3 list of free ecbs

Figure 6.3 List of free ECBs

  • The number of ECBs to allocate depends on the number of semaphores, mailboxes, and queues needed for your application

  • When OSInit() is called, all ECBs are linked in a singly linked list

    • The list of free ECBs


Chapter 6 intertask communication sysnchronization

  • Four common operations can be performed on ECBs

    • Initialize an ECB

    • Make a task ready

    • Make a task wait for an event

    • Make a task ready because a timeout occurred while waiting for an event

  • Four functions have been created to performs these operations

    • OSEventWaitListInit()

    • OSEventTaskRdy()

    • OSEventWait()

    • OSEventTO()


Initializing an ecb oseventwaitlistinit

Initializing an ECBOSEventWaitListInit()

  • Is called by OSSemCreate(), OSMboxCreate (), OSQCreate ()

    • No task is waiting on the ECB

void OSEventWaitListInit (OS_EVENT *pevent)

{

INT8U i;

pevent->OSEventGrp = 0x00;

for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

pevent->OSEventTbl[i] = 0x00;

}

}


Making a task ready oseventtaskrdy

Making a task readyOSEventTaskRdy()

  • This function is called by

    • OSSemPost(), OSMbosPost(), OSQPost(), and OSQPostFront()

  • Removes the highest priority task (HPT) from the wait list of the ECB and makes this task ready to run

void OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)

{

OS_TCB *ptcb;

INT8U x;

INT8U y;

INT8U bitx;

INT8U bity;

INT8U prio;


Oseventtaskrdy cont d

y = OSUnMapTbl[pevent->OSEventGrp]; (1)

bity = OSMapTbl[y]; (2)

x = OSUnMapTbl[pevent->OSEventTbl[y]]; (3)

bitx = OSMapTbl[x]; (4)

prio = (INT8U)((y << 3) + x); (5)

if ((pevent->OSEventTbl[y] &= ~bitx) == 0) { (6)

pevent->OSEventGrp &= ~bity;

}

ptcb = OSTCBPrioTbl[prio]; (7)

ptcb->OSTCBDly = 0; (8)

ptcb->OSTCBEventPtr = (OS_EVENT *)0; (9)

#if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN

ptcb->OSTCBMsg = msg; (10)

#else

msg = msg;

#endif

ptcb->OSTCBStat &= ~msk; (Semaphore,mail box, mail queue) (11)

if (ptcb->OSTCBStat == OS_STAT_RDY) { (12)

OSRdyGrp |= bity; (13)

OSRdyTbl[y] |= bitx;

}

}

OSEventTaskRdy (cont’d)


Figure 6 4 making a task ready to run

Figure 6.4 Making a task ready to run


Making a task wait for an event oseventtaskwait

Making a task wait for an eventOSEventTaskWait()

  • Called by OSSemPend(), OSMboxPend, and OSQPend() when a task must wait on an ECB

  • OSEventTaskWait() removes the current task from the ready list and places it in the wait list of the ECB

void OSEventTaskWait (OS_EVENT *pevent)

{

OSTCBCur->OSTCBEventPtr = pevent; (1)

if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (2)

OSRdyGrp &= ~OSTCBCur->OSTCBBitY;

}

pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; (3)

pevent->OSEventGrp |= OSTCBCur->OSTCBBitY;

}


Making a task ready becase of a timeout oseventto

Making a task ready becase of a timeoutOSEventTO()

  • Called by OSSemPend(), OSMboxPend(), OSQPend() when a task has been made ready to run by OSTimeTick()

  • OSEventTO() must remove the task from the wait list of the ECB and mark the task as being ready

void OSEventTO (OS_EVENT *pevent)

{

if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) { (1)

pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;

}

OSTCBCur->OSTCBStat = OS_STAT_RDY; (2)

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (3)

}


Semaphores

Semaphores

  • Create a semaphore by calling OSSemCreate()

  • The initial count of the semaphore can be 0 to 65535

    • Use to signal the occurrence of one ore more event, the init value is 0 (flag)

    • Use to access a shared resource, the init value is set to 1 (binary) (key)

  • Five services will access semaphore:

    • OSSemCreate(), OSSemPend(), OSSemPost(), OSSemAccept(), OSSemQuery()

Figure 6.5 Relationships between tasks, ISRs, and a semaphore


Creating a semaphore ossemcreate

Creating a SemaphoreOSSemCreate()

OS_EVENT *OSSemCreate (INT16U cnt)

{

OS_EVENT *pevent;

OS_ENTER_CRITICAL();

pevent = OSEventFreeList; (1)

if (OSEventFreeList != (OS_EVENT *)0) { (2)

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;

}

OS_EXIT_CRITICAL();

if (pevent != (OS_EVENT *)0) { (3)

pevent->OSEventType = OS_EVENT_TYPE_SEM; (4)

pevent->OSEventCnt = cnt; (5)

OSEventWaitListInit(pevent); (6)

}

return (pevent); (7)

}


Waiting on a semaphore ossempend

Waiting on a SemaphoreOSSemPend()

void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)

{

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

*err = OS_ERR_EVENT_TYPE;

}

if (pevent->OSEventCnt > 0) { (2)

pevent->OSEventCnt--; (3)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} else if (OSIntNesting > 0) { (4)

OS_EXIT_CRITICAL();

*err = OS_ERR_PEND_ISR;

} else {

OSTCBCur->OSTCBStat |= OS_STAT_SEM; (5)

OSTCBCur->OSTCBDly = timeout; (6)

OSEventTaskWait(pevent); (7)

OS_EXIT_CRITICAL();

OSSched(); (8)

OS_ENTER_CRITICAL();

if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { (9)

OSEventTO(pevent); (10)

OS_EXIT_CRITICAL();

*err = OS_TIMEOUT;

} else {

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

}

}

}


Signaling a semaphore ossempost

Signaling a SemaphoreOSSemPost()

INT8U OSSemPost (OS_EVENT *pevent)

{

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

if (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, (void *)0, OS_STAT_SEM); (3)

OS_EXIT_CRITICAL();

OSSched(); (4)

return (OS_NO_ERR);

} else {

if (pevent->OSEventCnt < 65535) {

pevent->OSEventCnt++; (5)

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

} else {

OS_EXIT_CRITICAL();

return (OS_SEM_OVF);

}

}

}


Getting a semaphore without waiting ossemaccept

Getting a Semaphore without WaitingOSSemAccept()

  • To obtain a semaphore without putting a task to sleep if the semaphore is not available

INT16U OSSemAccept (OS_EVENT *pevent)

{

INT16U cnt;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

return (0);

}

cnt = pevent->OSEventCnt; (2)

if (cnt > 0) { (3)

pevent->OSEventCnt--; (4)

}

OS_EXIT_CRITICAL();

return (cnt); (5)

}


Obaining the status of a semaphore ossemquery

Obaining the status of a semaphoreOSSemQuery()

  • Allow APs to take a snapshot of an ECB

  • Two arguments are required

    • Pevent: pointer to the semaphore

    • Pdata pointer to a data structure which will receive the information about the desired semaphore

INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)

{

INT8U i;

INT8U *psrc;

INT8U *pdest;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp = pevent->OSEventGrp; (2)

psrc = &pevent->OSEventTbl[0];

pdest = &pdata->OSEventTbl[0];

for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

*pdest++ = *psrc++;

}

pdata->OSCnt = pevent->OSEventCnt; (3)

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

}


Message mailboxes

Message Mailboxes

  • Allow a task or an ISR to send a pointer-sized variable to another task

  • Five services to access mailboxes

    • OSMboxCreate(), OSMboxPend(), OSMboxPost(), OSMboxAccept(), OSMboxQuery

Figure 6.6 Relationships between tasks, ISRs, and a message mailbox


Creating a mailbox osmboxcreate

Creating a Mailbox -- OSMboxCreate()

  • Similar to OSSemCreate()

    • Use OSEventPtr to instead of the OSEventCnt

  • Return a pointer to the ECB, such as mailbox handle

OS_EVENT *OSMboxCreate (void *msg)

{

OS_EVENT *pevent;

OS_ENTER_CRITICAL();

pevent = OSEventFreeList;

if (OSEventFreeList != (OS_EVENT *)0) {

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;

}

OS_EXIT_CRITICAL();

if (pevent != (OS_EVENT *)0) {

pevent->OSEventType = OS_EVENT_TYPE_MBOX; (1)

pevent->OSEventPtr = msg; (2)

OSEventWaitListInit(pevent);

}

return (pevent); (3)

}


Waiting for a message at a mailbox osmboxpend

Waiting for a Message at a MailboxOSMboxPend()

  • Similar to OSSemPend()

void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)

{

void *msg;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

*err = OS_ERR_EVENT_TYPE;

return ((void *)0);

}

msg = pevent->OSEventPtr;

if (msg != (void *)0) { (2)

pevent->OSEventPtr = (void *)0; (3)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} else if (OSIntNesting > 0) { (4)

OS_EXIT_CRITICAL();

*err = OS_ERR_PEND_ISR;


Waiting for a message to arrive at a mailbox cont d

Waiting for a message to arrive at a mailbox (cont’d)

} else {

OSTCBCur->OSTCBStat |= OS_STAT_MBOX; (5)

OSTCBCur->OSTCBDly = timeout;

OSEventTaskWait(pevent);

OS_EXIT_CRITICAL();

OSSched();

OS_ENTER_CRITICAL();

if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { (6)

OSTCBCur->OSTCBMsg = (void *)0;

OSTCBCur->OSTCBStat = OS_STAT_RDY;

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) { (7)

OSEventTO(pevent); (8)

OS_EXIT_CRITICAL();

msg = (void *)0; (9)

*err = OS_TIMEOUT;

} else {

msg = pevent->OSEventPtr; (10)

pevent->OSEventPtr = (void *)0;

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

}

}

return (msg);

}


Sending a message to a mailbox osmboxpost

Sending a Message to a MailboxOSMboxPost()

INT8U OSMboxPost (OS_EVENT *pevent, void *msg)

{

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

if (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, msg, OS_STAT_MBOX); (3)

OS_EXIT_CRITICAL();

OSSched(); (4)

return (OS_NO_ERR);

} else {

if (pevent->OSEventPtr != (void *)0) { (5)

OS_EXIT_CRITICAL();

return (OS_MBOX_FULL);

} else {

pevent->OSEventPtr = msg; (6)

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

}

}

}


Getting a message without waiting osmboxaccept

Getting a Message without WaitingOSMboxAccept()

void *OSMboxAccept (OS_EVENT *pevent)

{

void *msg;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

return ((void *)0);

}

msg = pevent->OSEventPtr; (2)

if (msg != (void *)0) { (3)

pevent->OSEventPtr = (void *)0; (4)

}

OS_EXIT_CRITICAL();

return (msg); (5)

}


Obtaining the status of a mailbox osmboxquery

Obtaining the status of a MailboxOSMboxQuery()

INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)

{

INT8U i;

INT8U *psrc;

INT8U *pdest;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp = pevent->OSEventGrp; (2)

psrc = &pevent->OSEventTbl[0];

pdest = &pdata->OSEventTbl[0];

for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

*pdest++ = *psrc++;

}

pdata->OSMsg = pevent->OSEventPtr; (3)

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

}


Using a mailbox as a binary semaphore

Using a Mailbox as a Binary Semaphore

  • Initializing the mailbox with a non-NULL pointer (ex void *1) as a binary semaphore

OS_EVENT *MboxSem;

void Task1 (void *pdata)

{

INT8U err;

for (;;) {

OSMboxPend(MboxSem, 0, &err); /* Obtain access to resource(s) */

.

. /* Task has semaphore, access resource(s) */

.

OSMboxPost(MboxSem, (void )1); /* Release access to resource(s) */

}

}


Using a mailbox instead of ostimedly

Using a Mailbox instead of OSTimeDly()

OS_EVENT *MboxTimeDly;

void Task1 (void *pdata)

{

INT8U err;

for (;;) {

OSMboxPend(MboxTimeDly, TIMEOUT, &err); /* Delay task */

.

. /* Code executed after time delay */

.

}

}

void Task2 (void *pdata)

{

INT8U err;

for (;;) {

OSMboxPost(MboxTimeDly, (void *)1); /* Cancel delay for Task1 */

.

.

}

}

  • Task1() resumes execution after the time period expires if no message is received

  • Task2() post a “dummy” message to the mailbox before the timeout expires.

    • Same as calling OSTimeDlyResume()


Message queue

Message Queue

  • Seven services to access message queues

    • OSQCreate(), OSQPend(), OSQPost(), OSQPostFront(), OSQAccept(), OSQFlush(), and OSQQuery

Figure 6.7 Relationships between tasks, ISRs, and a message queue


Figure 6 8 data structures used in a message queue

Figure 6.8 Data structures used in a message queue


Figure 6 9 list of free queue control blocks

Figure 6.9 List of free queue control blocks

Figure 6.10 A message queue is a circular buffer of pointers


Creating a queue osqcreate

OS_EVENT *OSQCreate (void **start, INT16U size)

{

OS_EVENT *pevent;

OS_Q *pq;

OS_ENTER_CRITICAL();

pevent = OSEventFreeList; (1)

if (OSEventFreeList != (OS_EVENT *)0) {

OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; (2)

}

OS_EXIT_CRITICAL();

if (pevent != (OS_EVENT *)0) {

OS_ENTER_CRITICAL();

pq = OSQFreeList; (3)

if (OSQFreeList != (OS_Q *)0) {

OSQFreeList = OSQFreeList->OSQPtr;

}

OS_EXIT_CRITICAL();

if (pq != (OS_Q *)0) {

pq->OSQStart = start; (4)

pq->OSQEnd = &start[size];

pq->OSQIn = start;

pq->OSQOut = start;

pq->OSQSize = size;

pq->OSQEntries = 0;

pevent->OSEventType = OS_EVENT_TYPE_Q; (5)

pevent->OSEventPtr = pq; (6)

OSEventWaitListInit(pevent); (7)

} else {

OS_ENTER_CRITICAL();

pevent->OSEventPtr = (void *)OSEventFreeList; (8)

OSEventFreeList = pevent;

OS_EXIT_CRITICAL();

pevent = (OS_EVENT *)0;

}

}

return (pevent); (9)

}

Creating a queue, OSQCreate()


Waiting for a message at a queue osqpend

Waiting for a Message at a Queue, OSQPend()

void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)

{

void *msg;

OS_Q *pq;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1)

OS_EXIT_CRITICAL();

*err = OS_ERR_EVENT_TYPE;

return ((void *)0);

}

pq = pevent->OSEventPtr;

if (pq->OSQEntries != 0) { (2)

msg = *pq->OSQOut++; (3)

pq->OSQEntries--; (4)

if (pq->OSQOut == pq->OSQEnd) { (5)

pq->OSQOut = pq->OSQStart; (6)

}

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} else if (OSIntNesting > 0) { (7)

OS_EXIT_CRITICAL();

*err = OS_ERR_PEND_ISR;


Chapter 6 intertask communication sysnchronization

} else {

OSTCBCur->OSTCBStat |= OS_STAT_Q; (8)

OSTCBCur->OSTCBDly = timeout;

OSEventTaskWait(pevent);

OS_EXIT_CRITICAL();

OSSched(); (9)

OS_ENTER_CRITICAL();

if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) { (10)

OSTCBCur->OSTCBMsg = (void *)0;

OSTCBCur->OSTCBStat = OS_STAT_RDY;

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (11)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

} else if (OSTCBCur->OSTCBStat & OS_STAT_Q) { (12)

OSEventTO(pevent); (13)

OS_EXIT_CRITICAL();

msg = (void *)0; (14)

*err = OS_TIMEOUT;

} else {

msg = *pq->OSQOut++; (15)

pq->OSQEntries--;

if (pq->OSQOut == pq->OSQEnd) {

pq->OSQOut = pq->OSQStart;

}

OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; (16)

OS_EXIT_CRITICAL();

*err = OS_NO_ERR;

}

}

return (msg); (17)

}


6 23 depositing a message in a queue fifo

6.23 Depositing a message in a queue (FIFO)

INT8U OSQPost (OS_EVENT *pevent, void *msg)

{

OS_Q *pq;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

if (pevent->OSEventGrp) { (2)

OSEventTaskRdy(pevent, msg, OS_STAT_Q); (3)

OS_EXIT_CRITICAL();

OSSched();

return (OS_NO_ERR);

} else {

pq = pevent->OSEventPtr;

if (pq->OSQEntries >= pq->OSQSize) { (4)

OS_EXIT_CRITICAL();

return (OS_Q_FULL);

} else {

*pq->OSQIn++ = msg; (5)

pq->OSQEntries++;

if (pq->OSQIn == pq->OSQEnd) {

pq->OSQIn = pq->OSQStart;

}

OS_EXIT_CRITICAL();

}

return (OS_NO_ERR);

}

}


Sending a message to a queue lifo osqpostfront

Sending a message to a queue (LIFO), OSQPostFront()

INT8U OSQPostFront (OS_EVENT *pevent, void *msg)

{

OS_Q *pq;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) {

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

if (pevent->OSEventGrp) {

OSEventTaskRdy(pevent, msg, OS_STAT_Q);

OS_EXIT_CRITICAL();

OSSched();

return (OS_NO_ERR);

} else {

pq = pevent->OSEventPtr;

if (pq->OSQEntries >= pq->OSQSize) {

OS_EXIT_CRITICAL();

return (OS_Q_FULL);

} else {

if (pq->OSQOut == pq->OSQStart) { (1)

pq->OSQOut = pq->OSQEnd; (2)

}

pq->OSQOut--; (3)

*pq->OSQOut = msg;

pq->OSQEntries++;

OS_EXIT_CRITICAL();

}

return (OS_NO_ERR);

}

}


Getting a message without waiting osqaccept

Getting a message without waiting, OSQAccept()

void *OSQAccept (OS_EVENT *pevent)

{

void *msg;

OS_Q *pq;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1)

OS_EXIT_CRITICAL();

return ((void *)0);

}

pq = pevent->OSEventPtr;

if (pq->OSQEntries != 0) { (2)

msg = *pq->OSQOut++; (3)

pq->OSQEntries--;

if (pq->OSQOut == pq->OSQEnd) {

pq->OSQOut = pq->OSQStart;

}

} else {

msg = (void *)0; (4)

}

OS_EXIT_CRITICAL();

return (msg);

}


Flushing a queue osqflush

Flushing a queue, OSQFlush()

INT8U OSQFlush (OS_EVENT *pevent)

{

OS_Q *pq;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

pq = pevent->OSEventPtr;

pq->OSQIn = pq->OSQStart; (2)

pq->OSQOut = pq->OSQStart;

pq->OSQEntries = 0;

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

}


Using a message queue when reading analog inputs

Using a message queue when reading analog inputs


Using a queue as a counting semaphore

Using a queue as a counting semaphore

OS_EVENT *QSem;

void *QMsgTbl[N_RESOURCES]

void main (void)

{

OSInit();

.

QSem = OSQCreate(&QMsgTbl[0], N_RESOURCES);

for (i = 0; i < N_RESOURCES; i++) {

OSQPost(Qsem, (void *)1);

}

.

OSTaskCreate(Task1, .., .., ..);

.

OSStart();

}

void Task1 (void *pdata)

{

INT8U err;

for (;;) {

OSQPend(&QSem, 0, &err); /* Obtain access to resource(s) */

.

. /* Task has semaphore, access resource(s) */

.

OSMQPost(QSem, (void )1); /* Release access to resource(s) */

}

}


Obtaining the status of a queue osqquery

Obtaining the status of a queue, OSQQuery()

INT8U OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)

{

OS_Q *pq;

INT8U i;

INT8U *psrc;

INT8U *pdest;

OS_ENTER_CRITICAL();

if (pevent->OSEventType != OS_EVENT_TYPE_Q) { (1)

OS_EXIT_CRITICAL();

return (OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp = pevent->OSEventGrp; (2)

psrc = &pevent->OSEventTbl[0];

pdest = &pdata->OSEventTbl[0];

for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {

*pdest++ = *psrc++;

}

pq = (OS_Q *)pevent->OSEventPtr;

if (pq->OSQEntries > 0) { (3)

pdata->OSMsg = pq->OSQOut; (4)

} else {

pdata->OSMsg = (void *)0; (5)

}

pdata->OSNMsgs = pq->OSQEntries; (6)

pdata->OSQSize = pq->OSQSize;

OS_EXIT_CRITICAL();

return (OS_NO_ERR);

}


  • Login