...
To enable µC/OS-II message mailbox services, you must set configuration constants in
. Specifically, table 10.1 shows which services are compiled based on the value of configuration constants found in OS_CFG.H
. You should note that NONE of the mailbox services are enabled when OS_CFG.H
OS_MBOX_EN
is set to 0. To enable specific features (i.e. service) listed in Table 10.1, simply set the configuration constant to 1. You will notice that OSMboxCreate()
and OSMboxPend()
cannot be individually disabled like the other services. That’s because they are always needed when you enable µC/OS-II message mailbox management. You must enable at least one of the post services: OSMboxPost()
and OSMboxPostOpt()
.
Anchor | ||||
---|---|---|---|---|
|
Panel | |||||
---|---|---|---|---|---|
| |||||
|
...
|
...
|
Figure 10.1 shows a flow diagram to illustrate the relationship between tasks, ISRs, and a message mailbox. Note that the symbology used to represent a mailbox is an I-beam. The hourglass represents a timeout that can be specified with the OSMboxPend()
call. The content of the mailbox is a pointer to a message. What the pointer points to is application specific. A mailbox can only contain one pointer (mailbox is full) or a pointer to NULL (mailbox is empty).
As you can see from Figure 10.1, a task or an ISR can call OSMboxPost()
or OSMboxPostOpt()
. However, only tasks are allowed to call OSMboxDel()
, OSMboxPend()
and OSMboxQuery()
. Your application can have just about any number of mailboxes. The limit is set by OS_MAX_EVENTS
in
.OS_CFG.H
Anchor | ||||
---|---|---|---|---|
|
Creating a Mailbox, OSMboxCreate()
A mailbox needs to be
|
Panel | ||||
---|---|---|---|---|
| ||||
Creating a Mailbox, OSMboxCreate()
A mailbox needs to be created before it can be used. Creating a mailbox is accomplished by calling OSMboxCreate()
and specifying the initial value of the pointer. Typically, the initial value is a NULL pointer, but a mailbox can initially contain a message. If you use the mailbox to signal the occurrence of an event (i.e., send a message), you typically initialize it to a NULL pointer because the event (most likely) has not occurred. If you use the mailbox to access a shared resource, you initialize the mailbox with a non-NULL pointer. In this case, you basically use the mailbox as a binary semaphore.
The code to create a mailbox is shown in Listing 10.1.
The timeout feature of a mailbox can be used to simulate a call to OSTimeDly()
. As shown in Listing 10.9, Task1() resumes execution after the time period expires if no message is received within the specified TIMEOUT. This is basically identical to OSTimeDly(TIMEOUT)
. However, the task can be resumed by Task2() when Task(2) post a “dummy” message to the mailbox before the timeout expires. This is the same as calling OSTimeDlyResume()
had Task1() called OSTimeDly()
. Note that the returned message is ignored because you are not actually looking to get a message from another task or an ISR.
Anchor |
---|
Figure 10.2 ECB just before OSMboxCreate()
returns.
Deleting a Mailbox, OSMboxDel()
The code to delete a mailbox is shown in listing 10.2 and this code will only be generated by the compiler if OS_MBOX_DEL_EN
is set to 1 in
. This is a function you must use with caution because multiple tasks could attempt to access a deleted mailbox. You should always use this function with great care. Generally speaking, before you would delete a mailbox, you would first delete all the tasks that can access the mailbox.OS_CFG.H
Waiting for a Message at a Mailbox, OSMboxPend()
The code to wait for a message to arrive at a mailbox is shown in Listing 10.3.
Sending a message to a mailbox, OSMboxPost()
The code to deposit a message in a mailbox is shown in Listing 10.4.
Note that a context switch does not occur if OSMboxPost()
is called by an ISR because context switching from an ISR only occurs when OSIntExit()
is called at the completion of the ISR and from the last nested ISR (see section 3.09, Interrupts under µC/OS-II).
Sending a message to a mailbox, OSMboxPostOpt()
You can also post a message to a mailbox using an alternate and more powerful function called OSMboxPostOpt()
. The reason there are two post calls is for backwards compatibility with previous versions of µC/OS-II. OSMboxPostOpt()
is the newer function and can replace OSMboxPost()
. In addition, OSMboxPostOpt()
allows posting a message to all tasks (i.e. broadcast) waiting on the mailbox. The code to deposit a message in a mailbox is shown in Listing 10.5.
Note that a context switch does not occur if OSMboxPostOpt()
is called by an ISR because context switching from an ISR only occurs when OSIntExit()
is called at the completion of the ISR and from the last nested ISR (see section 3.10, Interrupts under µC/OS-II).
Getting a message without waiting (non-blocking), OSMboxAccept()
You can obtain a message from a mailbox without putting a task to sleep if the mailbox is empty. This is accomplished by calling OSMboxAccept()
, shown in Listing 10.6.
The code that called OSMboxAccept()
must examine the returned value. If OSMboxAccept()
returns a NULL pointer, then a message was not available. A non-NULL pointer indicates that a message was deposited in the mailbox. An ISR should use OSMboxAccept()
instead of OSMboxPend()
.
You can use OSMboxAccept()
to flush (i.e., empty) the contents of a mailbox.
Obtaining the status of a mailbox, OSMboxQuery()
OSMboxQuery()
allows your application to take a snapshot of an ECB used for a message mailbox. The code for this function is shown in Listing 10.7. OSMboxQuery()
is passed two arguments: pevent contains a pointer to the message mailbox, which is returned by OSMboxCreate()
when the mailbox is created, and pdata is a pointer to a data structure (OS_MBOX_DATA
, see uCOS_II.H
) that holds information about the message mailbox. Your application needs to allocate a variable of type OS_MBOX_DATA
that will be used to receive the information about the desired mailbox. I decided to use a new data structure because the caller should only be concerned with mailbox-specific data, as opposed to the more generic OS_EVENT
data structure, which contains two additional fields (.OSEventCnt
and .OSEventType
). OS_MBOX_DATA
contains the current contents of the message (.OSMsg
) and the list of tasks waiting for a message to arrive (.OSEventTbl[]
and .OSEventGrp
).
Using a Mailbox as a Binary Semaphore
A message mailbox can be used as a binary semaphore by initializing the mailbox with a non-NULL pointer [(void *)1 works well]. A task requesting the “semaphore” calls OSMboxPend()
and releases the “semaphore” by calling OSMboxPost()
. Listing 10.8 shows how this works. You can use this technique to conserve code space if your application only needs binary semaphores and mailboxes. In this case, set OS_MBOX_EN
to 1 and OS_SEM_EN
to 0 so that you use only mailboxes instead of both mailboxes and semaphores.
Using a Mailbox instead of OSTimeDly()
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
OS_EVENT *OSMboxCreate (void *msg)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr; (1)
#endif
OS_EVENT *pevent;
if (OSIntNesting > 0) { (2)
return ((OS_EVENT *)0);
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; (3)
if (OSEventFreeList != (OS_EVENT *)0) { (4)
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; (5)
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { (6)
pevent->OSEventType = OS_EVENT_TYPE_MBOX; (7)
pevent->OSEventCnt = 0; (8)
pevent->OSEventPtr = msg; (9)
OS_EventWaitListInit(pevent); (10)
}
return (pevent); (11)
} |
Panel | ||
---|---|---|
| ||
(1) A local variable called cpu_sr to support (2) (3) (4) (5) The linked list of free ECBs is adjusted to point to the next free ECB. (6) (7) If there is an ECB available, the ECB type is set to (8) The (9) The initial value of the message is stored in the ECB. (10) The wait list is then initialized by calling (11) Finally, |
Anchor | ||||
---|---|---|---|---|
|
Panel | ||||
---|---|---|---|---|
| ||||
Deleting a Mailbox, OSMboxDel()
The code to delete a mailbox is shown in listing 10.2 and this code will only be generated by the compiler if OS_MBOX_DEL_EN
is set to 1 in
. This is a function you must use with caution because multiple tasks could attempt to access a deleted mailbox. You should always use this function with great care. Generally speaking, before you would delete a mailbox, you would first delete all the tasks that can access the mailbox.OS_CFG.H
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
OS_EVENT *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
BOOLEAN tasks_waiting;
if (OSIntNesting > 0) { (1)
*err = OS_ERR_DEL_ISR;
return (pevent);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (2)
*err = OS_ERR_PEVENT_NULL;
return (pevent);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (3)
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { (4)
tasks_waiting = TRUE;
} else {
tasks_waiting = FALSE;
}
switch (opt) {
case OS_DEL_NO_PEND:
if (tasks_waiting == FALSE) {
pevent->OSEventType = OS_EVENT_TYPE_UNUSED; (5)
pevent->OSEventPtr = OSEventFreeList; (6)
OSEventFreeList = pevent; (7)
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return ((OS_EVENT *)0); (8)
} else {
OS_EXIT_CRITICAL();
*err = OS_ERR_TASK_WAITING;
return (pevent);
}
case OS_DEL_ALWAYS:
while (pevent->OSEventGrp != 0x00) { (9)
OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX); (10)
}
pevent->OSEventType = OS_EVENT_TYPE_UNUSED; (11)
pevent->OSEventPtr = OSEventFreeList; (12)
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
if (tasks_waiting == TRUE) {
OS_Sched(); (13)
}
*err = OS_NO_ERR;
return ((OS_EVENT *)0); (14)
default:
OS_EXIT_CRITICAL();
*err = OS_ERR_INVALID_OPT;
return (pevent);
}
} |
Panel | ||
---|---|---|
| ||
(1) (2) (3) We then validate pevent to ensure that it’s not a NULL pointer and that it points to an ECB that was created as a mailbox. (4) Based on the option (i.e., opt) specified in the call, (5) (6) (7) When opt is set to (8) You will note that
This allows the pointer to the mailbox to be altered by the call. (9) (10) When opt is set to (11) (12) Once all pending tasks are readied, (13) The scheduler is called only if there were tasks waiting on the mailbox. (14) Again, you will note that |
Waiting for a Message at a Mailbox, OSMboxPend()
The code to wait for a message to arrive at a mailbox is shown in Listing 10.3.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
void *msg;
if (OSIntNesting > 0) { (1)
*err = OS_ERR_PEND_ISR;
return ((void *)0);
}
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (2)
*err = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (3)
*err = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr; (4)
if (msg != (void *)0) {
pevent->OSEventPtr = (void *)0; (5)
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg); (6)
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; (7)
OSTCBCur->OSTCBDly = timeout; (8)
OS_EventTaskWait(pevent); (9)
OS_EXIT_CRITICAL();
OS_Sched(); (10)
OS_ENTER_CRITICAL();
msg = OSTCBCur->OSTCBMsg;
if (msg != (void *)0) { (11)
OSTCBCur->OSTCBMsg = (void *)0;
OSTCBCur->OSTCBStat = OS_STAT_RDY;
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (msg); (12)
}
OS_EventTO(pevent); (13)
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT;
return ((void *)0); (14)
} |
Panel | ||
---|---|---|
| ||
(1) (2) (3) If (4) (5) (6) If a message has been deposited in the mailbox (non NULL pointer), the message is extracted from the mailbox and replaced with a NULL pointer and the function returns to its caller with the message that was in the mailbox. An error code is also set indicating success. If your code calls If the mailbox was empty, the calling task needs to be put to sleep until another task (or an ISR) sends a message through the mailbox (see section 10.04). (7) To put the calling task to sleep, (8) The timeout is also stored in the TCB so that it can be decremented by (9) The actual work of putting the task to sleep is done by (10) Because the calling task is no longer ready to run, the scheduler is called to run the next highest priority task that is ready to run. As far as your task is concerned, it made a call to (11) When (12) If so, the call is successful and the message is returned to the caller. (13) If a message is not received then (14) Note that the returned pointer is set to NULL because there is no message to return. The calling task should either examine the contents of the return pointer or the return code to determine whether a valid message was received. |
Sending a message to a mailbox, OSMboxPost()
The code to deposit a message in a mailbox is shown in Listing 10.4.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (1)
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) {
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { (2)
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX); (3)
OS_EXIT_CRITICAL();
OS_Sched(); (4)
return (OS_NO_ERR);
}
if (pevent->OSEventPtr != (void *)0) { (5)
OS_EXIT_CRITICAL();
return (OS_MBOX_FULL);
}
pevent->OSEventPtr = msg; (6)
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
} |
Panel | ||
---|---|---|
| ||
(1) If (2) (3) The highest priority task waiting for the message is removed from the wait list by (4) (5) At this point, there are no tasks waiting for a message at the specified mailbox. (6) If there are no tasks waiting for a message to arrive at the mailbox, then the pointer to the message is saved in the mailbox. Storing the pointer in the mailbox allows the next task to call |
Note that a context switch does not occur if OSMboxPost()
is called by an ISR because context switching from an ISR only occurs when OSIntExit()
is called at the completion of the ISR and from the last nested ISR (see section 3.09, Interrupts under µC/OS-II).
Sending a message to a mailbox, OSMboxPostOpt()
You can also post a message to a mailbox using an alternate and more powerful function called OSMboxPostOpt()
. The reason there are two post calls is for backwards compatibility with previous versions of µC/OS-II. OSMboxPostOpt()
is the newer function and can replace OSMboxPost()
. In addition, OSMboxPostOpt()
allows posting a message to all tasks (i.e. broadcast) waiting on the mailbox. The code to deposit a message in a mailbox is shown in Listing 10.5.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
INT8U OSMboxPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (1)
return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) {
return (OS_ERR_POST_NULL_PTR);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { (2)
if ((opt & OS_POST_OPT_BROADCAST) != 0x00) { (3)
while (pevent->OSEventGrp != 0x00) { (4)
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX); (5)
}
} else {
OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX); (6)
}
OS_EXIT_CRITICAL();
OS_Sched(); (7)
return (OS_NO_ERR);
}
if (pevent->OSEventPtr != (void *)0) { (8)
OS_EXIT_CRITICAL();
return (OS_MBOX_FULL);
}
pevent->OSEventPtr = msg; (9)
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
} |
Panel | ||
---|---|---|
| ||
(1) If (2) (3) (4) (5) If you set the (6) If a broadcast was not requested then, only the highest priority task waiting for a message will be made ready to run. The highest priority task waiting for the message is removed from the wait list by (7) (8) If nobody is waiting for a message, the message to post needs to be placed in the mailbox. In this case, (9) |
Note that a context switch does not occur if OSMboxPostOpt()
is called by an ISR because context switching from an ISR only occurs when OSIntExit()
is called at the completion of the ISR and from the last nested ISR (see section 3.10, Interrupts under µC/OS-II).
Getting a message without waiting (non-blocking), OSMboxAccept()
You can obtain a message from a mailbox without putting a task to sleep if the mailbox is empty. This is accomplished by calling OSMboxAccept()
, shown in Listing 10.6.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
void *OSMboxAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
void *msg;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (1)
return ((void *)0);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (2)
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
msg = pevent->OSEventPtr; (3)
pevent->OSEventPtr = (void *)0; (4)
OS_EXIT_CRITICAL();
return (msg); (5)
} |
Panel | ||
---|---|---|
| ||
(1) (2) If (3) (4) If a message is available, the mailbox is emptied. You should note that this operation is done even if the message already contains a NULL pointer. This is done for performance considerations. (5) Finally, the original contents of the mailbox is returned to the caller. |
The code that called OSMboxAccept()
must examine the returned value. If OSMboxAccept()
returns a NULL pointer, then a message was not available. A non-NULL pointer indicates that a message was deposited in the mailbox. An ISR should use OSMboxAccept()
instead of OSMboxPend()
.
You can use OSMboxAccept()
to flush (i.e., empty) the contents of a mailbox.
Obtaining the status of a mailbox, OSMboxQuery()
OSMboxQuery()
allows your application to take a snapshot of an ECB used for a message mailbox. The code for this function is shown in Listing 10.7. OSMboxQuery()
is passed two arguments: pevent contains a pointer to the message mailbox, which is returned by OSMboxCreate()
when the mailbox is created, and pdata is a pointer to a data structure (OS_MBOX_DATA
, see uCOS_II.H
) that holds information about the message mailbox. Your application needs to allocate a variable of type OS_MBOX_DATA
that will be used to receive the information about the desired mailbox. I decided to use a new data structure because the caller should only be concerned with mailbox-specific data, as opposed to the more generic OS_EVENT
data structure, which contains two additional fields (.OSEventCnt
and .OSEventType
). OS_MBOX_DATA
contains the current contents of the message (.OSMsg
) and the list of tasks waiting for a message to arrive (.OSEventTbl[]
and .OSEventGrp
).
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT8U *psrc;
INT8U *pdest;
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { (1)
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { (2)
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSEventGrp = pevent->OSEventGrp; (3)
psrc = &pevent->OSEventTbl[0];
pdest = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 1
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 2
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 3
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 4
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 5
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 6
*pdest++ = *psrc++;
#endif
#if OS_EVENT_TBL_SIZE > 7
*pdest = *psrc;
#endif
pdata->OSMsg = pevent->OSEventPtr; (4)
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
} |
Panel | ||
---|---|---|
| ||
(1) (2) As always, if (3) (4) Finally, the current message, from the |
Using a Mailbox as a Binary Semaphore
A message mailbox can be used as a binary semaphore by initializing the mailbox with a non-NULL pointer [(void *)1 works well]. A task requesting the “semaphore” calls OSMboxPend()
and releases the “semaphore” by calling OSMboxPost()
. Listing 10.8 shows how this works. You can use this technique to conserve code space if your application only needs binary semaphores and mailboxes. In this case, set OS_MBOX_EN
to 1 and OS_SEM_EN
to 0 so that you use only mailboxes instead of both mailboxes and semaphores.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
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()
The timeout feature of a mailbox can be used to simulate a call to OSTimeDly()
. As shown in Listing 10.9, Task1() resumes execution after the time period expires if no message is received within the specified TIMEOUT. This is basically identical to OSTimeDly(TIMEOUT)
. However, the task can be resumed by Task2() when Task(2) post a “dummy” message to the mailbox before the timeout expires. This is the same as calling OSTimeDlyResume()
had Task1() called OSTimeDly()
. Note that the returned message is ignored because you are not actually looking to get a message from another task or an ISR.
Anchor | ||||
---|---|---|---|---|
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
OS_EVENT *MboxTimeDly;
void Task1 (void *pdata)
{
INT8U err;
for (;;) {
OSMboxPend(MboxTimeDly, TIMEOUT, &err); /* Delay task */
.
. /* Code executed after time delay or dummy message is received */
.
}
}
void Task2 (void *pdata)
{
INT8U err;
for (;;) {
OSMboxPost(MboxTimeDly, (void *)1); /* Cancel delay for Task1 */
.
.
}
} |