Chapter 16
µC/OS-II Reference Manual This chapter provides a reference to µC/OS-II services. Each of the user-accessible kernel services is presented in alphabetical order. The following information is provided for each of the services: • A brief description •
The function prototype
•
The filename of the source code
•
The #define constant needed to enable the code for the service
•
A description of the arguments passed to the function
•
A description of the returned value(s)
•
Specific notes and warnings on using the service
•
One or two examples of how to use the function
405
OS_ENTER_CRITICAL() OS_EXIT_CRITICAL() Chapter
File
3
OS_CPU.H
Called from
Code enabled by
Task or ISR
N/A
OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() are macros used to disable and enable, respectively, the
processor’s interrupts.
Arguments none
Returned Values none
Notes/Warnings 1.
These macros must be used in pairs.
2.
If OS_CRITICAL_METHOD is set to 3, your code is assumed to have allocated local storage for a variable of type OS_CPU_SR, which is called cpu_sr, as follows
#if OS_CRITICAL_METHOD == 3 register */ OS_CPU_SR
/* Allocate storage for CPU status
cpu_sr;
#endif
Example void TaskX(void *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR
cpu_sr;
#endif
for (;;) { . . OS_ENTER_CRITICAL();
/* Disable interrupts
*/
.
/* Access critical code
*/
OS_EXIT_CRITICAL();
/* Enable
*/
. . } }
406
interrupts
OSEventNameGet() INT8U OSEventNameGet(OS_EVENT *pevent, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_CORE.C
Called from
Code enabled by
Task or ISR
OS_EVENT_NAME_SIZE
OSEventNameGet() allows you to obtain the name that you assigned to a semaphore, a mutex, a mailbox or a
message queue.
The name is an ASCII string and the size of the name can contain up to This function is typically used by a debugger to allow associating a name to a resource. OS_EVENT_NAME_SIZE characters (including the NUL termination).
Arguments pevent
is a pointer to the event control block. pevent can point either to a semaphore, a mutex, a mailbox or a queue. Where this function is concerned, the actual type is irrelevant. This pointer is returned to your application when the semaphore, mutex, mailbox or queue is created (see OSSemCreate(), OSMutexCreate(), OSMboxCreate() and OSQCreate()).
pname
is a pointer to an ASCII string that will receive the name of the semaphore, mutex, mailbox or queue. The string must be able to hold at least OS_EVENT_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the semaphore, mutex, mailbox or queue was copied to the array pointed to by pname.
OS_ERR_EVENT_TYPE
You are not pointing to either a semaphore, mutex, mailbox or message queue.
OS_ERR_PEVENT_NULL
You passed a NULL pointer for pevent.
Returned Values The size of the ASCII string placed in the array pointed to by pname or 0 if an error is encountered.
407
Notes/Warnings 1.
The semaphore, mutex, mailbox or message queue must be created before you can use this function and obtain the name of the resource.
Example char
PrinterSemName[30];
OS_EVENT *PrinterSem;
void Task (void *pdata) { INT8U
err;
INT8U
size;
pdata = pdata; for (;;) { size = OSEventNameGet(PrinterSem, &PrinterSemName[0], &err); . . } }
408
OSEventNameSet() void OSEventNameSet(OS_EVENT *pevent, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_CORE.C
Called from
Code enabled by
Task or ISR
OS_EVENT_NAME_SIZE
OSEventNameSet() allows you to assign a name to a semaphore, a mutex, a mailbox or a message queue. The name is an ASCII string and the size of the name can contain up to OS_EVENT_NAME_SIZE characters (including the NUL termination). This function is typically used by a debugger to allow associating a name to a resource.
Arguments pevent
is a pointer to the event control block that you want to name. pevent can point either to a semaphore, a mutex, a mailbox or a queue. Where this function is concerned, the actual type is irrelevant. This pointer is returned to your application when the semaphore, mutex, mailbox or queue is created (see OSSemCreate(), OSMutexCreate(), OSMboxCreate() and OSQCreate()).
pname
is a pointer to an ASCII string that contains the name for the resource. The size of the string must be smaller than or equal to OS_EVENT_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the semaphore, mutex, mailbox or queue was copied to the array pointed to by pname.
OS_ERR_EVENT_TYPE
You are not pointing to either a semaphore, mutex, mailbox or message queue.
OS_ERR_PEVENT_NULL
You passed a NULL pointer for pevent.
Returned Values none
Notes/Warnings 1.
The semaphore, mutex, mailbox or message queue must be created before you can use this function and set the name of the resource.
409
Example OS_EVENT *PrinterSem;
void Task (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { OSEventNameSet(PrinterSem, “Printer #1”, &err); . . } }
410
OSFlagAccept() OS_FLAGS OSFlagAccept(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT8U *err); Chapter 9
File
Called from
OS_FLAG.C
Code enabled by
Task
OS_FLAG_EN && OS_FLAG_ACCEPT_EN
OSFlagAccept() allows you to check the status of a combination of bits to be either set or cleared in an event
flag group. Your application can check for any bit to be set/cleared or all bits to be set/cleared. This function behaves exactly as OSFlagPend() does, except that the caller does NOT block if the desired event flags are not present.
Arguments pgrp
is a pointer to the event flag group. This pointer is returned to your application when the event flag group is created [see OSFlagCreate()].
flags
is a bit pattern indicating which bit(s) (i.e., flags) you wish to check. The bits you want are specified by setting the corresponding bits in flags.
wait_type
specifies whether you want all bits to be set/cleared or any of the bits to be set/cleared. You can specify the following arguments: OS_FLAG_WAIT_CLR_ALL
You check all bits in flags to be clear (0)
OS_FLAG_WAIT_CLR_ANY
You check any bit in flags to be clear (0)
OS_FLAG_WAIT_SET_ALL
You check all bits in flags to be set (1)
OS_FLAG_WAIT_SET_ANY
You check any bit in flags to be set (1)
You can add OS_FLAG_CONSUME if you want the event flag(s) to be consumed by the call. For example, to wait for any flag in a group and then clear the flags that are present, set wait_type to OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME err
a pointer to an error code and can be any of the following: OS_NO_ERR
No error
OS_ERR_EVENT_TYPE
You are not pointing to an event flag group
OS_FLAG_ERR_WAIT_TYPE
You didn’t specify a proper wait_type argument.
OS_FLAG_INVALID_PGRP
You passed a NULL pointer instead of the event flag handle.
OS_FLAG_ERR_NOT_RDY
The desired flags for which you are waiting are not available.
Returned Values The flag(s) that cause the task to be ready or, 0 if either none of the flags are ready or an error occurred.
411
Notes/Warnings 1.
The event flag group must be created before it is used.
2.
This function does not block if the desired flags are not present. IMPORTANT
The return value of OSFlagAccept() is different as of V2.70. In previous versions, OSFlagAccept() returned the current state of the flags and now, it returns the flag(s) that are ready, if any.
Example #define
ENGINE_OIL_PRES_OK
0x01
#define
ENGINE_OIL_TEMP_OK
0x02
#define
ENGINE_START
0x04
OS_FLAG_GRP *EngineStatus;
void Task (void *pdata) { INT8U
err;
OS_FLAGS
value;
pdata = pdata; for (;;) { value = OSFlagAccept(EngineStatus, ENGINE_OIL_PRES_OK + ENGINE_OIL_TEMP_OK, OS_FLAG_WAIT_SET_ALL, &err); switch (err) { case OS_NO_ERR: /* Desired flags are available */ break;
case OS_FLAG_ERR_NOT_RDY: /* The desired flags are NOT available */ break; } . . } }
412
413
OSFlagCreate() OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags, INT8U *err);
Chapter
File
9
OS_FLAG.C
Called from
Code enabled by
Task or startup code
OS_FLAG_EN
OSFlagCreate() is used to create and initialize an event flag group.
Arguments flags
contains the initial value to store in the event flag group.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the event flag group has been created.
OS_ERR_CREATE_ISR
if you attempt to create an event flag group from an ISR.
OS_FLAG_GRP_DEPLETED
if no more event flag groups are available. You need to increase the value of OS_MAX_FLAGS in OS_CFG.H.
Returned Values A pointer to the event flag group if a free event flag group is available. If no event flag group is available, OSFlagCreate() returns a NULL pointer.
Notes/Warnings 1.
Event flag groups must be created by this function before they can be used by the other services.
Example OS_FLAG_GRP *EngineStatus;
void main (void) { INT8U
err;
. OSInit();
/* Initialize µC/OS-II */
. . /* Create a flag group containing the engine’s status */ EngineStatus = OSFlagCreate(0x00, &err); . . OSStart();
/* Start Multitasking
}
414
*/
OSFlagDel() OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP *pgrp, INT8U opt, INT8U *err);
Chapter 9
File
Called from
OS_FLAG. C
Code enabled by
Task
OS_FLAG_EN and OS_FLAG_DEL_EN
OSFlagDel() is used to delete an event flag group. This function is dangerous to use because multiple tasks
could be relying on the presence of the event flag group. You should always use this function with great care. Generally speaking, before you delete an event flag group, you must first delete all the tasks that access the event flag group.
Arguments pgrp
is a pointer to the event flag group. This pointer is returned to your application when the event flag group is created [see OSFlagCreate()].
opt
specifies whether you want to delete the event flag group only if there are no pending tasks (OS_DEL_NO_PEND) or whether you always want to delete the event flag group regardless of whether tasks are pending or not (OS_DEL_ALWAYS). In this case, all pending task are readied.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the event flag group has been deleted.
OS_ERR_DEL_ISR
if you attempt to delete an event flag group from an ISR.
OS_FLAG_INVALID_PGRP
if you pass a NULL pointer in pgrp.
OS_ERR_EVENT_TYPE
if pgrp is not pointing to an event flag group.
OS_ERR_INVALID_OPT
if you do not specify one of the two options mentioned in the opt argument.
OS_ERR_TASK_WAITING
if one or more task are waiting on the event flag group and you specify OS_DEL_NO_PEND.
Returned Values A NULL pointer if the event flag group is deleted or pgrp if the event flag group is not deleted. In the latter case, you need to examine the error code to determine the reason for the error.
415
Notes/Warnings 1.
You should use this call with care because other tasks might expect the presence of the event flag group.
2.
This call can potentially disable interrupts for a long time. The interrupt-disable time is directly proportional to the number of tasks waiting on the event flag group.
Example OS_FLAG_GRP *EngineStatusFlags;
void Task (void *pdata) { INT8U
err;
OS_FLAG_GRP *pgrp;
pdata = pdata; while (1) { . . pgrp = OSFlagDel(EngineStatusFlags, OS_DEL_ALWAYS, &err); if (pgrp == (OS_FLAG_GRP *)0) { /* The event flag group was deleted */ } . . }
}
416
OSFlagNameGet() INT8U OSFlagNameGet(OS_FLAG_GRP *pgrp, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_FLAG.C
Called from
Code enabled by
Task or ISR
OS_FLAG_NAME_SIZE
OSFlagNameGet() allows you to obtain the name that you assigned to an event flag group. The name is an ASCII string and the size of the name can contain up to OS_FLAG_NAME_SIZE characters (including the NUL
termination). This function is typically used by a debugger to allow associating a name to a resource.
Arguments pgrp
is a pointer to the event flag group.
pname
is a pointer to an ASCII string that will receive the name of the event flag group. The string must be able to hold at least OS_FLAG_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the semaphore, mutex, mailbox or queue was copied to the array pointed to by pname.
OS_ERR_EVENT_TYPE
You are not pointing to either a semaphore, mutex, mailbox or message queue.
OS_ERR_INVALID_PGRP
You passed a NULL pointer for pgrp.
Returned Values The size of the ASCII string placed in the array pointed to by pname or 0 if an error is encountered.
417
Notes/Warnings 1.
The event flag group must be created before you can use this function and obtain the name of the resource.
Example char
EngineStatusName[30];
OS_FLAG_GRP *EngineStatusFlags;
void Task (void *pdata) { INT8U
err;
INT8U
size;
pdata = pdata; for (;;) { size = OSFlagNameGet(EngineStatusFlags, &EngineStatusName[0], &err); . . } }
418
OSFlagNameSet() void OSFlagNameSet(OS_FLAG_GRP *pgrp, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_FLAG.C
Called from
Code enabled by
Task or ISR
OS_EVENT_NAME_SIZE
OSFlagNameSet() allows you to assign a name to an event flag group. The name is an ASCII string and the size of the name can contain up to OS_FLAG_NAME_SIZE characters (including the NUL termination). This
function is typically used by a debugger to allow associating a name to a resource.
Arguments pgrp
is a pointer to the event flag group that you want to name. This pointer is returned to your application when the event flag group is created (see OSFlagCreate()).
pname
is a pointer to an ASCII string that contains the name for the resource. The size of the string must be smaller than or equal to OS_EVENT_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the event flag group was copied to the array pointed to by pname.
OS_ERR_EVENT_TYPE
You are not pointing to an event flag group.
OS_ERR_INVALID_PGRP
You passed a NULL pointer for pgrp.
Returned Values none
Notes/Warnings 1.
The event flag group must be created before you can use this function to set the name of the resource.
419
Example OS_FLAG_GRP *EngineStatus;
void Task (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { OSFlagNameSet(EngineStatus, “Engine Status Flags”, &err); . . } }
420
OSFlagPend() OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err);
Chapter 9
File
Called from Task only
OS_FLAG.C
Code enabled by OS_FLAG_EN
OSFlagPend() is used to have a task wait for a combination of conditions (i.e., events or bits) to be set (or cleared) in an event flag group. You application can wait for any condition to be set or cleared or for all conditions to be set or cleared. If the events that the calling task desires are not available, then the calling task is blocked until the desired conditions are satisfied or the specified timeout expires.
Arguments pgrp
is a pointer to the event flag group. This pointer is returned to your application when the event flag group is created [see OSFlagCreate()].
flags
is a bit pattern indicating which bit(s) (i.e., flags) you wish to check. The bits you want are specified by setting the corresponding bits in flags.
wait_type
specifies whether you want all bits to be set/cleared or any of the bits to be set/cleared. You can specify the following arguments: OS_FLAG_WAIT_CLR_ALL
You check all bits in flags to be clear (0)
OS_FLAG_WAIT_CLR_ANY
You check any bit in flags to be clear (0)
OS_FLAG_WAIT_SET_ALL
You check all bits in flags to be set (1)
OS_FLAG_WAIT_SET_ANY
You check any bit in flags to be set (1)
You can also specify whether the flags are consumed by adding OS_FLAG_CONSUME to the wait_type. For example, to wait for any flag in a group and then clear the flags that satisfy the condition, set wait_type to OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME timeout
allows the task to resume execution if the desired flag(s) is(are) not received from the event flag group within the specified number of clock ticks. A timeout value of 0 indicates that the task wants to wait forever for the flag(s). The maximum timeout is 65,535 clock ticks. The timeout value is not synchronized with the clock tick. The timeout count begins decrementing on the next clock tick, which could potentially occur immediately.
err
is a pointer to an error code and can be: OS_NO_ERR
No error.
OS_ERR_PEND_ISR
You try to call OSFlagPend from an ISR, which is not allowed.
OS_FLAG_INVALID_PGRP
You pass a NULL pointer instead of the event flag handle.
OS_ERR_EVENT_TYPE
You are not pointing to an event flag group.
OS_TIMEOUT
The flags are not available within the specified amount of time.
OS_FLAG_ERR_WAIT_TYPE
You don’t specify a proper wait_type argument.
421
Returned Values The flag(s) that cause the task to be ready or, 0 if either none of the flags are ready or an error occurred.
Notes/Warnings 1.
The event flag group must be created before it’s used. IMPORTANT
The return value of OSFlagPend() is different as of V2.70. In previous versions, OSFlagPend() returned the current state of the flags and now, it returns the flag(s) that are ready, if any.
Example #define
ENGINE_OIL_PRES_OK
0x01
#define
ENGINE_OIL_TEMP_OK
0x02
#define
ENGINE_START
0x04
OS_FLAG_GRP *EngineStatus;
void Task (void *pdata) { INT8U
err;
OS_FLAGS
value;
pdata = pdata; for (;;) { value = OSFlagPend(EngineStatus, ENGINE_OIL_PRES_OK
+ ENGINE_OIL_TEMP_OK,
OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 10, &err); switch (err) { case OS_NO_ERR: /* Desired flags are available */ break;
case OS_TIMEOUT: /* The desired flags were NOT available before 10 ticks occurred */ break; }
422
. . } }
OSFlagPendGetFlagsRdy() OS_FLAGS OSFlagPendGetFlagsRdy(void)
Chapter Added in V2.60
File
Called from Task only
OS_FLAG.C
Code enabled by OS_FLAG_EN
OSFlagPendGetFlagsRdy() is used to obtain the flags that caused the current task to become ready to run.
In other words, this function allows you to know "Who done It!"
Arguments None
Returned Value The value of the flags that caused the current task to become ready to run.
Notes/Warnings 1.
The event flag group must be created before it’s used.
423
Example #define
ENGINE_OIL_PRES_OK
0x01
#define
ENGINE_OIL_TEMP_OK
0x02
#define
ENGINE_START
0x04
OS_FLAG_GRP *EngineStatus;
void Task (void *pdata) { INT8U
err;
OS_FLAGS
value;
pdata = pdata; for (;;) { value = OSFlagPend(EngineStatus, ENGINE_OIL_PRES_OK
+ ENGINE_OIL_TEMP_OK,
OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 10, &err); switch (err) { case OS_NO_ERR: flags = OSFlagPendGetFlagsRdy();
/* Find out who made
task ready */ break;
case OS_TIMEOUT: /* The desired flags were NOT available before 10 ticks occurred */ break; } . . } }
424
OSFlagPost() OS_FLAGS OSFlagPost(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *err);
Chapter 9
File
Called from Task or ISR
OS_FLAG.C
Code enabled by OS_FLAG_EN
You set or clear event flag bits by calling OSFlagPost(). The bits set or cleared are specified in a bit mask. OSFlagPost() readies each task that has its desired bits satisfied by this call. You can set or clear bits that are already set or cleared.
Arguments pgrp
is a pointer to the event flag group. This pointer is returned to your application when the event flag group is created [see OSFlagCreate()].
flags
specifies which bits you want set or cleared. If opt is OS_FLAG_SET, each bit that is set in flags sets the corresponding bit in the event flag group. For example to set bits 0, 4, and 5, you set flags to 0x31 (note, bit 0 is the least significant bit). If opt is OS_FLAG_CLR, each bit that is set in flags will clears the corresponding bit in the event flag group. For example to clear bits 0, 4, and 5, you specify flags as 0x31 (note, bit 0 is the least significant bit).
opt
indicates whether the flags are set (OS_FLAG_SET) or cleared (OS_FLAG_CLR).
err
is a pointer to an error code and can be: OS_NO_ERR
The call is successful.
OS_FLAG_INVALID_PGRP
You pass a NULL pointer.
OS_ERR_EVENT_TYPE
You are not pointing to an event flag group.
OS_FLAG_INVALID_OPT
You specify an invalid option.
Returned Value The new value of the event flags.
Notes/Warnings 1.
Event flag groups must be created before they are used.
2.
The execution time of this function depends on the number of tasks waiting on the event flag group. However, the execution time is deterministic.
3.
The amount of time interrupts are disabled also depends on the number of tasks waiting on the event flag group.
425
Example #define
ENGINE_OIL_PRES_OK
0x01
#define
ENGINE_OIL_TEMP_OK
0x02
#define
ENGINE_START
0x04
OS_FLAG_GRP
void
*EngineStatusFlags;
TaskX (void *pdata)
{ INT8U
err;
pdata = pdata; for (;;) { . . err = OSFlagPost(EngineStatusFlags, ENGINE_START, OS_FLAG_SET, &err); . . } }
426
OSFlagQuery() OS_FLAGS OSFlagQuery(OS_FLAG_GRP *pgrp, INT8U *err);
Chapter
File
9
OS_FLAG.C
Called from
Code enabled by
Task or ISR
OS_FLAG_EN && OS_FLAG_QUERY_EN
OSFlagQuery() is used to obtain the current value of the event flags in a group. At this time, this function does not return the list of tasks waiting for the event flag group.
Arguments pgrp
is a pointer to the event flag group. This pointer is returned to your application when the event flag group is created [see OSFlagCreate()].
err
is a pointer to an error code and can be: OS_NO_ERR
The call is successful.
OS_FLAG_INVALID_PGRP
You pass a NULL pointer.
OS_ERR_EVENT_TYPE
You are not pointing to an event flag groups.
Returned Value The state of the flags in the event flag group.
Notes/Warnings 1.
The event flag group to query must be created.
2.
You can call this function from an ISR.
Example OS_FLAG_GRP *EngineStatusFlags;
void Task (void *pdata) { OS_FLAGS flags; INT8U
err;
pdata = pdata; for (;;) { . . flags = OSFlagQuery(EngineStatusFlags, &err); . . } }
427
OSInit() void OSInit(void);
Chapter 3
File OS_CORE.C
Called from Startup code only
Code enabled by N/A
OSInit() initializes _C/OS-II and must be called prior to calling OSStart(), which actually starts
multitasking.
Arguments none
Returned Values none
Notes/Warnings 1.
OSInit() must be called before OSStart().
Example void main (void) { . . OSInit();
/* Initialize µC/OS-II */
. . OSStart();
/* Start Multitasking
}
428
*/
OSIntEnter() void OSIntEnter(void);
Chapter
File
3
Called from
Code enabled by
ISR only
OS_CORE.C
N/A
OSIntEnter() notifies _C/OS-II that an ISR is being processed, which allows µC/OS-II to keep track of interrupt nesting. OSIntEnter() is used in conjunction with OSIntExit().
Arguments none
Returned Values none
Notes/Warnings 1.
This function must not be called by task-level code.
2.
You can increment the interrupt-nesting counter (OSIntNesting) directly in your ISR to avoid the overhead of the function call/return. It’s safe to increment OSIntNesting in your ISR because interrupts are assumed to be disabled when OSIntNesting needs to be incremented.
3.
You are allowed to nest interrupts up to 255 levels deep.
Example 1 (Intel 80x86, real mode, large model) Use OSIntEnter() for backward compatibility with µC/OS. ISRx PROC
FAR
PUSHA
; Save interrupted task's context
PUSH
ES
PUSH
DS
CALL
FAR PTR _OSIntEnter
; Notify µC/OS-II of start of ISR
POP
DS
; Restore processor registers
POP
ES
;
. .
POPA IRET
; Return from interrupt
ISRx ENDP
429
Example 2 (Intel 80x86, real mode, large model)
ISRx
PROC
FAR
PUSHA
; Save interrupted task's
context PUSH
ES
PUSH
DS
MOV
AX, SEG(_OSIntNesting)
MOV
DS, AX
INC
BYTE PTR _OSIntNesting
; Notify µC/OS-II of start of
POP
DS
; Restore processor registers
POP
ES
; ; Reload DS
; ISR . . .
POPA IRET ISRx
; Return from interrupt
ENDP
430
OSIntExit() void OSIntExit(void);
Chapter
File
3
Called from ISR only
OS_CORE.C
Code enabled by N/A
OSIntExit() notifies µC/OS-II that an ISR is complete, which allows µC/OS-II to keep track of interrupt nesting. OSIntExit() is used in conjunction with OSIntEnter(). When the last nested interrupt completes, OSIntExit() determines if a higher priority task is ready to run, in which case, the interrupt returns to the
higher priority task instead of the interrupted task.
Arguments none
Returned Value none
Notes/Warnings 1.
This function must not be called by task-level code. Also, if you decided to increment OSIntNesting, you still need to call OSIntExit().
Example (Intel 80x86, real mode, large model)
ISRx
PROC
FAR
PUSHA
; Save processor registers
PUSH
ES
PUSH
DS
. . CALL
FAR PTR _OSIntExit ; Notify µC/OS-II of end of ISR
POP
DS
POP
ES
; Restore processor registers
POPA IRET ISRx
; Return to interrupted task
ENDP
431
OSMboxAccept() void *OSMboxAccept(OS_EVENT *pevent);
Chapter
File
10
OS_MBOX.C
Called from Task or ISR
Code enabled by OS_MBOX_EN && OS_MBOX_ACCEPT_EN
OSMboxAccept() allows you to see if a message is available from the desired mailbox. Unlike OSMboxPend(), OSMboxAccept() does not suspend the calling task if a message is not available. In other words, OSMboxAccept() is non-blocking. If a message is available, the message is returned to your
application, and the content of the mailbox is cleared. This call is typically used by ISRs because an ISR is not allowed to wait for a message at a mailbox.
Arguments is a pointer to the mailbox from which the message is received. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
pevent
Returned Value A pointer to the message if one is available; NULL if the mailbox does not contain a message.
Notes/Warnings 1.
Mailboxes must be created before they are used.
Example OS_EVENT *CommMbox;
void Task (void *pdata) { void *msg;
pdata = pdata; for (;;) { msg = OSMboxAccept(CommMbox); /* Check mailbox for a message */ if (msg != (void *)0) { .
/* Message received, process
*/
. } else { .
/* Message not received, do .. */
.
/* .. something else */
} . . } }
432
OSMboxCreate() OS_EVENT *OSMboxCreate(void *msg);
Chapter
File
10
OS_MBOX.C
Called from Task or startup code
Code enabled by OS_MBOX_EN
OSMboxCreate() creates and initializes a mailbox. A mailbox allows tasks or ISRs to send a pointer-sized
variable (message) to one or more tasks.
Arguments is used to initialize the contents of the mailbox. The mailbox is empty when msg is a NULL pointer. The mailbox initially contains a message when msg is non-NULL.
msg
Returned Value A pointer to the event control block allocated to the mailbox. If no event control block is available, OSMboxCreate() returns a NULL pointer.
Notes/Warnings 1.
Mailboxes must be created before they are used.
Example OS_EVENT *CommMbox;
void main (void) { . . /* Initialize µC/OS-II
*/
CommMbox = OSMboxCreate((void *)0);
/* Create COMM mailbox
*/
OSStart();
/* Start Multitasking
*/
OSInit(); . .
}
433
OSMboxDel() OS_EVENT *OSMboxDel(OS_EVENT *pevent, INT8U opt, INT8U *err);
Chapter
File
10
OS_MBOX.C
Called from Task
Code enabled by OS_MBOX_EN and OS_MBOX_DEL_EN
OSMboxDel() is used to delete a message mailbox. This function is dangerous to use because multiple tasks
could attempt to access a deleted mailbox. You should always use this function with great care. Generally speaking, before you delete a mailbox, you must first delete all the tasks that can access the mailbox.
Arguments pevent
is a pointer to the mailbox. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
opt
specifies whether you want to delete the mailbox only if there are no pending tasks (OS_DEL_NO_PEND) or whether you always want to delete the mailbox regardless of whether tasks are pending or not (OS_DEL_ALWAYS). In this case, all pending task are readied.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the mailbox has been deleted.
OS_ERR_DEL_ISR
if you attempt to delete the mailbox from an ISR.
OS_ERR_INVALID_OPT
if you don’t specify one of the two options mentioned in the opt argument.
OS_ERR_TASK_WAITING
One or more tasks is waiting on the mailbox.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mailbox.
OS_ERR_PEVENT_NULL
if no more OS_EVENT structures are available.
Returned Value A NULL pointer if the mailbox is deleted or pevent if the mailbox is not deleted. In the latter case, you need to examine the error code to determine the reason.
Notes/Warnings 1.
You should use this call with care because other tasks might expect the presence of the mailbox.
2.
Interrupts are disabled when pended tasks are readied, which means that interrupt latency depends on the number of tasks that are waiting on the mailbox.
3.
OSMboxAccept() callers do not know that the mailbox has been deleted.
434
Example OS_EVENT *DispMbox;
void Task (void *pdata) { INT8U
err;
pdata = pdata; while (1) { . . DispMbox = OSMboxDel(DispMbox, OS_DEL_ALWAYS, &err); if (DispMbox == (OS_EVENT *)0) { /* Mailbox has been deleted */ } . . } }
435
OSMboxPend() void *OSMboxPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
Chapter 10
File
Called from Task only
OS_MBOX.C
Code enabled by OS_MBOX_EN
OSMboxPend() is used when a task expects to receive a message. The message is sent to the task either by an
ISR or by another task. The message received is a pointer-sized variable, and its use is application specific. If a message is present in the mailbox when OSMboxPend() is called, the message is retrieved, the mailbox is emptied, and the retrieved message is returned to the caller. If no message is present in the mailbox, OSMboxPend() suspends the current task until either a message is received or a user-specified timeout expires. If a message is sent to the mailbox and multiple tasks are waiting for the message, µC/OS-II resumes the highest priority task waiting to run. A pended task that has been suspended with OSTaskSuspend() can receive a message. However, the task remains suspended until it is resumed by calling OSTaskResume().
Arguments pevent
is a pointer to the mailbox from which the message is received. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
timeout
allows the task to resume execution if a message is not received from the mailbox within the specified number of clock ticks. A timeout value of 0 indicates that the task wants to wait forever for the message. The maximum timeout is 65,535 clock ticks. The timeout value is not synchronized with the clock tick. The timeout count begins decrementing on the next clock tick, which could potentially occur immediately.
err
is a pointer to a variable that holds an error code. OSMboxPend() sets *err to one of the following: OS_NO_ERR
if a message is received.
OS_TIMEOUT
if a message is not received within the specified timeout period.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mailbox.
OS_ERR_PEND_ISR
if you call this function from an ISR and µC/OS-II suspends it. In general, you should not call OSMboxPend() from an ISR, but _C/OS-II checks for this situation anyway.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
Returned Value OSMboxPend() returns the message sent by either a task or an ISR, and *err is set to OS_NO_ERR. If a message is not received within the specified timeout period, the returned message is a NULL pointer, and *err is set to OS_TIMEOUT.
Notes/Warnings 1.
Mailboxes must be created before they are used.
2.
You should not call OSMboxPend() from an ISR.
436
Example OS_EVENT *CommMbox;
void CommTask(void *pdata) { INT8U
err;
void
*msg;
pdata = pdata; for (;;) { . . msg = OSMboxPend(CommMbox, 10, &err); if (err == OS_NO_ERR) { . .
/* Code for received message
*/
. } else { . .
/* Code for message not received within timeout */
. } . . } }
437
OSMboxPost() INT8U OSMboxPost(OS_EVENT *pevent, void *msg);
Chapter
File
10
OS_MBOX.C
Called from Task or ISR
Code enabled by OS_MBOX_EN && OS_MBOX_POST_EN
OSMboxPost() sends a message to a task through a mailbox. A message is a pointer-sized variable and, its use is application specific. If a message is already in the mailbox, an error code is returned indicating that the mailbox is full. OSMboxPost() then immediately returns to its caller, and the message is not placed in the mailbox. If any task is waiting for a message at the mailbox, the highest priority task waiting receives the message. If the task waiting for the message has a higher priority than the task sending the message, the higher priority task is resumed, and the task sending the message is suspended. In other words, a context switch occurs.
Arguments pevent
is a pointer to the mailbox into which the message is deposited. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
msg
is the actual message sent to the task. msg is a pointer-sized variable and is application specific. You must never post a NULL pointer because this pointer indicates that the mailbox is empty.
Returned Value OSMboxPost() returns one of these error codes: OS_NO_ERR
if the message is deposited in the mailbox.
OS_MBOX_FULL
if the mailbox already contains a message.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mailbox.
OS_ERR_PEVENT_NULL
if pevent is a pointer to NULL.
OS_ERR_POST_NULL_PTR
if you are attempting to post a NULL pointer. By convention a NULL pointer is not supposed to point to anything.
Notes/Warnings 1.
Mailboxes must be created before they are used.
2.
You must never post a NULL pointer because this pointer indicates that the mailbox is empty.
438
Example OS_EVENT *CommMbox; INT8U
CommRxBuf[100];
void CommTaskRx (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { . . err = OSMboxPost(CommMbox, (void *)&CommRxBuf[0]); . . } }
439
OSMboxPostOpt() INT8U OSMboxPostOpt(OS_EVENT *pevent, void *msg, INT8U opt);
Chapter 10
File OS_MBOX.C
Called from
Code enabled by
Task or ISR
OS_MBOX_EN and OS_MBOX_POST_OPT_EN
OSMboxPostOpt() works just like OSMboxPost() except that it allows you to post a message to multiple tasks. In other words, OSMboxPostOpt() allows the message posted to be broadcast to all tasks waiting on the mailbox. OSMboxPostOpt() can actually replace OSMboxPost() because it can emulate OSMboxPost(). OSMboxPostOpt() is used to send a message to a task through a mailbox. A message is a pointer-sized variable, and its use is application specific. If a message is already in the mailbox, an error code is returned indicating that the mailbox is full. OSMboxPostOpt() then immediately returns to its caller, and the message is not placed in the mailbox. If any task is waiting for a message at the mailbox, OSMboxPostOpt() allows you either to post the message to the highest priority task waiting at the mailbox (opt set to OS_POST_OPT_NONE) or to all tasks waiting at the mailbox (opt is set to OS_POST_OPT_BROADCAST). In either case, scheduling occurs and, if any of the tasks that receives the message have a higher priority than the task that is posting the message, then the higher priority task is resumed, and the sending task is suspended. In other words, a context switch occurs.
Arguments pevent
is a pointer to the mailbox. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
msg
is the actual message sent to the task(s). msg is a pointer-sized variable and is application specific. You must never post a NULL pointer because this pointer indicates that the mailbox is empty.
opt
specifies whether you want to send the message to the highest priority task waiting at the mailbox (when opt is set to OS_POST_OPT_NONE) or to all tasks waiting at the mailbox (when opt is set to OS_POST_OPT_BROADCAST).
Returned Value err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the message has been sent.
OS_MBOX_FULL
if the mailbox already contains a message. You can only send one message at a time to a mailbox, and thus the message must be consumed before you are allowed to send another one.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mailbox.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_POST_NULL_PTR
if you are attempting to post a NULL pointer. By convention, a NULL pointer is not supposed to point to anything.
440
Notes/Warnings 1.
Mailboxes must be created before they are used.
2.
You must never post a NULL pointer to a mailbox because this pointer indicates that the mailbox is empty.
3.
If you need to use this function and want to reduce code space, you can disable code generation of OSMboxPost() because OSMboxPostOpt() can emulate OSMboxPost().
4.
The execution time of OSMboxPostOpt() depends on the number of tasks waiting on the mailbox if you set opt to OS_POST_OPT_BROADCAST.
Example OS_EVENT *CommMbox; INT8U
CommRxBuf[100];
void CommRxTask (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { . . err = OSMboxPostOpt(CommMbox, (void *)&CommRxBuf[0], OS_POST_OPT_BROADCAST); . . } }
441
OSMboxQuery() INT8U OSMboxQuery(OS_EVENT *pevent, OS_MBOX_DATA *pdata);
Chapter 10
File OS_MBOX.C
Called from
Code enabled by
Task or ISR
OS_MBOX_EN && OS_MBOX_QUERY_EN
OSMboxQuery() obtains information about a message mailbox. Your application must allocate an OS_MBOX_DATA data structure, which is used to receive data from the event control block of the message mailbox. OSMboxQuery() allows you to determine whether any tasks are waiting for a message at the mailbox and how many tasks are waiting (by counting the number of 1s in the .OSEventTbl[] field). You can also examine the current contents of the mailbox. Note that the size of .OSEventTbl[] is established by the #define constant OS_EVENT_TBL_SIZE (see uCOS_II.H).
Arguments pevent
is a pointer to the mailbox. This pointer is returned to your application when the mailbox is created [see OSMboxCreate()].
pdata
is a pointer to a data structure of type OS_MBOX_DATA, which contains the following fields:
void *OSMsg; mailbox */
/* Copy of the message stored in the
INT8U */
OSEventTbl[OS_EVENT_TBL_SIZE];
INT8U
OSEventGrp;
/* Copy of the mailbox wait list
Returned Value OSMboxQuery() returns one of these error codes: OS_NO_ERR
if the call is successful.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_EVENT_TYPE
if you don’t pass a pointer to a message mailbox.
Notes/Warnings 1.
Message mailboxes must be created before they are used.
442
Example OS_EVENT *CommMbox;
void Task (void *pdata) { OS_MBOXDATA mbox_data; INT8U err;
pdata = pdata; for (;;) { . . err = OSMboxQuery(CommMbox, &mbox_data); if (err == OS_NO_ERR) { . /* Mailbox contains a message if mbox_data.OSMsg is not NULL*/ } . . } }
443
OSMemCreate() OS_MEM *OSMemCreate(void *addr, INT32U nblks, INT32U blksize, INT8U *err);
Chapter 12
File OS_MEM.C
Called from Task or startup code
Code enabled by OS_MEM_EN
OSMemCreate() creates and initializes a memory partition. A memory partition contains a user-specified number of fixed-size memory blocks. Your application can obtain one of these memory blocks and, when done, release the block back to the partition.
Arguments addr
is the address of the start of a memory area that is used to create fixed-size memory blocks. Memory partitions can be created either using static arrays or malloc() during startup.
nblks
contains the number of memory blocks available from the specified partition. You must specify at least two memory blocks per partition.
blksize
specifies the size (in bytes) of each memory block within a partition. A memory block must be large enough to hold at least a pointer.
err
is a pointer to a variable that holds an error code. OSMemCreate() sets *err to: OS_NO_ERR
if the memory partition is created successfully
OS_MEM_INVALID_ADDR
if you are specifying an invalid address (i.e., addr is a NULL pointer)
OS_MEM_INVALID_PART
if a free memory partition is not available
OS_MEM_INVALID_BLKS
if you don’t specify at least two memory blocks per partition
OS_MEM_INVALID_SIZE
if you don’t specify a block size that can contain at least a pointer variable
Returned Value OSMemCreate() returns a pointer to the created memory-partition control block if one is available. If no memory-partition control block is available, OSMemCreate() returns a NULL pointer.
Notes/Warnings 1.
Memory partitions must be created before they are used.
444
Example OS_MEM *CommMem; INT8U
CommBuf[16][128];
void main (void) { INT8U err;
OSInit();
/* Initialize µC/OS-II
*/
. . CommMem = OSMemCreate(&CommBuf[0][0], 16, 128, &err); . . OSStart();
/* Start Multitasking
}
445
*/
OSMemGet() void *OSMemGet(OS_MEM *pmem, INT8U *err);
Chapter 12
File OS_MEM.C
Called from Task or ISR
Code enabled by OS_MEM_EN
OSMemGet obtains a memory block from a memory partition. It is assumed that your application knows the size of each memory block obtained. Also, your application must return the memory block [using OSMemPut()] when it no longer needs it. You can call OSMemGet() more than once until all memory blocks are allocated.
Arguments pmem
is a pointer to the memory-partition control block that is returned to your application from the OSMemCreate() call.
err
is a pointer to a variable that holds an error code. OSMemGet() sets *err to one of the following: OS_NO_ERR
if a memory block is available and returned to your application.
OS_MEM_NO_FREE_BLKS
if the memory partition doesn’t contain any more memory blocks to allocate.
OS_MEM_INVALID_PMEM
if pmem is a NULL pointer.
Returned Value OSMemGet() returns a pointer to the allocated memory block if one is available. If no memory block is available from the memory partition, OSMemGet() returns a NULL pointer.
Notes/Warnings 1.
Memory partitions must be created before they are used.
446
Example OS_MEM *CommMem;
void Task (void *pdata) { INT8U *msg;
pdata = pdata; for (;;) { msg = OSMemGet(CommMem, &err); if (msg != (INT8U *)0) { .
/* Memory block allocated, use it. */
. } . . } }
447
OSMemNameGet() INT8U OSMemNameGet(OS_MEM *pmem, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_MEM.C
Called from
Code enabled by
Task or ISR
OS_MEM_NAME_SIZE
OSMemNameGet() allows you to obtain the name that you assigned to a memory partition. The name is an ASCII string and the size of the name can contain up to OS_MEM_NAME_SIZE characters (including the NUL
termination). This function is typically used by a debugger to allow associating a name to a resource.
Arguments pmem
is a pointer to the memory partition.
pname
is a pointer to an ASCII string that will receive the name of the memory partition. The string must be able to hold at least OS_MEM_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the semaphore, mutex, mailbox or queue was copied to the array pointed to by pname.
OS_ERR_INVALID_PMEM
You passed a NULL pointer for pmem.
Returned Values The size of the ASCII string placed in the array pointed to by pname or 0 if an error is encountered.
448
Notes/Warnings 1.
The memory partition must be created before you can use this function and obtain the name of the resource.
Example OS_MEM char
*CommMem; CommMemName[OS_MEM_NAME_SIZE];
void Task (void *pdata) { INT8U
err;
INT8U
size;
pdata = pdata; for (;;) { size = OSMemNameGet(CommMem, & CommMemName [0], &err); . . } }
449
OSMemNameSet() void OSMemNameSet(OS_MEM *pmem, char *pname, INT8U *err); Chapter
File
New in V2.60
OS_MEM.C
Called from
Code enabled by
Task or ISR
OS_MEM_NAME_SIZE
OSMemNameSet() allows you to assign a name to a memory partition. The name is an ASCII string and the size of the name can contain up to OS_MEM_NAME_SIZE characters (including the NUL termination). This
function is typically used by a debugger to allow associating a name to a resource.
Arguments pmem
is a pointer to the memory partition that you want to name. This pointer is returned to your application when the memory partition is created (see OSMemCreate()).
pname
is a pointer to an ASCII string that contains the name for the resource. The size of the string must be smaller than or equal to OS_MEM_NAME_SIZE characters (including the NUL character).
err
a pointer to an error code and can be any of the following: OS_NO_ERR
If the name of the event flag group was copied to the array pointed to by pname.
OS_ERR_INVALID_PMEM
You passed a NULL pointer for pmem.
Returned Values none
Notes/Warnings 1.
The memory partition must be created before you can use this function to set the name of the resource.
450
Example OS_MEM *CommMem;
void Task (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { OSMemNameSet(CommMem, “Comm. Buffer”, &err); . . } }
451
OSMemPut() INT8U OSMemPut(OS_MEM *pmem, void *pblk);
Chapter 12
File
Called from Task or ISR
OS_MEM.C
Code enabled by OS_MEM_EN
OSMemPut() returns a memory block to a memory partition. It is assumed that you return the memory block to
the appropriate memory partition.
Arguments pmem
is a pointer to the memory-partition control block that is returned to your application from the OSMemCreate() call.
pblk
is a pointer to the memory block to be returned to the memory partition.
Returned Value OSMemPut()
returns one of the following error codes: OS_NO_ERR
if a memory block is available and returned to your application.
OS_MEM_FULL
if the memory partition can not accept more memory blocks. This code is surely an indication that something is wrong because you are returning more memory blocks than you obtained using OSMemGet().
OS_MEM_INVALID_PMEM
if pmem is a NULL pointer.
OS_MEM_INVALID_PBLK
if pblk is a NULL pointer.
Notes/Warnings 1.
Memory partitions must be created before they are used.
2.
You must return a memory block to the proper memory partition.
452
Example OS_MEM *CommMem; INT8U
*CommMsg;
void Task (void *pdata) { INT8U err;
pdata = pdata; for (;;) { err = OSMemPut(CommMem, (void *)CommMsg); if (err == OS_NO_ERR) { .
/* Memory block released
. } . . } }
453
*/
OSMemQuery() INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *pdata);
Chapter
File
12
Called from
OS_MEM.C
Code enabled by
Task or ISR
OS_MEM_EN && OS_MEM_QUERY_EN
OSMemQuery() obtains information about a memory partition. Basically, this function returns the same information found in the OS_MEM data structure but in a new data structure called OS_MEM_DATA. OS_MEM_DATA also contains an additional field that indicates the number of memory blocks in use.
Arguments pmem
is a pointer to the memory-partition control block that is returned to your application from the OSMemCreate() call.
pdata void */
is a pointer to a data structure of type OS_MEM_DATA, which contains the following fields *OSAddr;
/* Points to beginning address of the memory partition
void *OSFreeList; /* Points to beginning of the free list of memory blocks */ INT32U */
OSBlkSize;
/* Size (in bytes) of each memory block
INT32U */
OSNBlks;
/* Total number of blocks in the partition
INT32U */
OSNFree;
/* Number of memory blocks free
INT32U */
OSNUsed;
/* Number of memory blocks used
Returned Value OSMemQuery() returns one of the following error codes: OS_NO_ERR
if a memory block is available and returned to your application.
OS_MEM_INVALID_PMEM
if pmem is a NULL pointer.
OS_MEM_INVALID_PDATA
if pdata is a NULL pointer.
Notes/Warnings 1.
Memory partitions must be created before they are used.
454
Example OS_MEM
*CommMem;
void Task (void *pdata) { INT8U
err;
OS_MEM_DATA
mem_data;
pdata = pdata; for (;;) { . . err = OSMemQuery(CommMem, &mem_data); . . } }
455
OSMutexAccept() INT8U OSMutexAccept(OS_EVENT *pevent, INT8U *err);
Chapter 8
File
Called from Task
OS_MUTEX.C
Code enabled by OS_MUTEX_EN
OSMutexAccept() allows you to check to see if a resource is available. Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is not available. In other words, OSMutexAccept() is non-blocking.
Arguments pevent
is a pointer to the mutex that guards the resource. This pointer is returned to your application when the mutex is created [see OSMutexCreate()].
err
is a pointer to a variable used to hold an error code. OSMutexAccept() sets *err to one of the following: OS_NO_ERR
if the call is successful.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mutex.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_PEND_ISR
if you call OSMutexAccept() from an ISR.
Returned Value If the mutex is available, OSMutexAccept() returns 1. If the mutex is owned by another task, OSMutexAccept() returns 0.
Notes/Warnings 1.
Mutexes must be created before they are used.
2.
This function must not be called by an ISR.
3.
If you acquire the mutex through OSMutexAccept(), you must call OSMutexPost() to release the mutex when you are done with the resource.
456
Example OS_EVENT *DispMutex;
void Task (void *pdata) { INT8U
err;
INT8U
value;
pdata = pdata; for (;;) { value = OSMutexAccept(DispMutex, &err); if (value == 1) { .
/* Resource available, process */
. } else { .
/* Resource NOT available
. } . . } }
457
*/
OSMutexCreate() OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err);
Chapter
File
8
OS_MUTEX.C
Called from Task or startup code
Code enabled by OS_MUTEX_EN
OSMutexCreate() is used to create and initialize a mutex. A mutex is used to gain exclusive access to a
resource.
Arguments prio
is the priority inheritance priority (PIP) that is used when a high priority task attempts to acquire the mutex that is owned by a low priority task. In this case, the priority of the low priority task is raised to the PIP until the resource is released.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the mutex has been created.
OS_ERR_CREATE_ISR
if you attempt to create a mutex from an ISR.
OS_PRIO_EXIST
if a task at the specified priority inheritance priority already exists.
OS_ERR_PEVENT_NULL
if no more OS_EVENT structures are available.
OS_PRIO_INVALID
if you specify a priority with a higher number than OS_LOWEST_PRIO.
Returned Value A pointer to the event control block allocated to the mutex. If no event control block is available, OSMutexCreate() returns a NULL pointer.
Notes/Warnings 1.
Mutexes must be created before they are used.
2.
You must make sure that prio has a higher priority than any of the tasks that use the mutex to access the resource. For example, if three tasks of priority 20, 25, and 30 are going to use the mutex, then prio must be a number lower than 20. In addition, there must not already be a task created at the specified priority.
458
Example OS_EVENT *DispMutex;
void main (void) { INT8U
err;
. . OSInit();
/* Initialize µC/OS-II
*/ . . DispMutex = OSMutexCreate(20, &err);
/* Create Display Mutex
*/ . . OSStart();
/* Start Multitasking
*/ }
459
OSMutexDel() OS_EVENT *OSMutexDel(OS_EVENT *pevent, INT8U opt, INT8U *err);
Chapter
File
8
OS_MUTEX.C
Called from Task
Code enabled by OS_MUTEX_EN and OS_MUTEX_DEL_EN
OSMutexDel() is used to delete a mutex. This function is dangerous to use because multiple tasks could
attempt to access a deleted mutex. You should always use this function with great care. Generally speaking, before you delete a mutex, you must first delete all the tasks that can access the mutex.
Arguments pevent
is a pointer to the mutex. This pointer is returned to your application when the mutex is created [see OSMutexCreate()].
opt
specifies whether you want to delete the mutex only if there are no pending tasks (OS_DEL_NO_PEND) or whether you always want to delete the mutex regardless of whether tasks are pending or not (OS_DEL_ALWAYS). In this case, all pending task are readied.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the mutex has been deleted.
OS_ERR_DEL_ISR
if you attempt to delete a mutex from an ISR.
OS_ERR_INVALID_OPT
if you don’t specify one of the two options mentioned in the opt argument.
OS_ERR_TASK_WAITING
if one or more task are waiting on the mutex and you specify OS_DEL_NO_PEND.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a mutex.
OS_ERR_PEVENT_NULL
if no more OS_EVENT structures are available.
Returned Value A NULL pointer if the mutex is deleted or pevent if the mutex is not deleted. In the latter case, you need to examine the error code to determine the reason.
Notes/Warnings 1.
You should use this call with care because other tasks might expect the presence of the mutex.
460
Example OS_EVENT *DispMutex;
void Task (void *pdata) { INT8U
err;
pdata = pdata; while (1) { . . DispMutex = OSMutexDel(DispMutex, OS_DEL_ALWAYS, &err); if (DispMutex == (OS_EVENT *)0) { /* Mutex has been deleted */ } . . } }
461
OSMutexPend() void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
Chapter 8
File
Called from Task only
OS_MUTEX.C
Code enabled by OS_MUTEX_EN
OSMutexPend() is used when a task desires to get exclusive access to a resource. If a task calls OSMutexPend() and the mutex is available, then OSMutexPend() gives the mutex to the caller and returns to its caller. Note that nothing is actually given to the caller except for the fact that if err is set to OS_NO_ERR,
the caller can assume that it owns the mutex. However, if the mutex is already owned by another task, OSMutexPend() places the calling task in the wait list for the mutex. The task thus waits until the task that owns the mutex releases the mutex and thus the resource or until the specified timeout expires. If the mutex is signaled before the timeout expires, _C/OS-II resumes the highest priority task that is waiting for the mutex. Note that if the mutex is owned by a lower priority task, then OSMutexPend() raises the priority of the task that owns the mutex to the PIP, as specified when you created the mutex [see OSMutexCreate()].
Arguments pevent
is a pointer to the mutex. This pointer is returned to your application when the mutex is created [see OSMutexCreate()].
timeout
is used to allow the task to resume execution if the mutex is not signaled (i.e., posted to) within the specified number of clock ticks. A timeout value of 0 indicates that the task desires to wait forever for the mutex. The maximum timeout is 65,535 clock ticks. The timeout value is not synchronized with the clock tick. The timeout count starts being decremented on the next clock tick, which could potentially occur immediately.
err
is a pointer to a variable that is used to hold an error code. OSMutexPend() sets *err to one of the following: OS_NO_ERR
if the call is successful and the mutex is available.
OS_TIMEOUT
if the mutex is not available within the specified timeout.
OS_ERR_EVENT_TYPE
if you don’t pass a pointer to a mutex to OSMutexPend().
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_PEND_ISR
if you attempt to acquire the mutex from an ISR.
Returned Value none
Notes/Warnings 1.
Mutexes must be created before they are used.
2.
You should not suspend the task that owns the mutex, have the mutex owner wait on any other µC/OS-II objects (i.e., semaphore, mailbox, or queue), and delay the task that owns the mutex. In other words, your code should hurry up and release the resource as quickly as possible.
462
Example OS_EVENT *DispMutex;
void
DispTask (void *pdata)
{ INT8U
err;
pdata = pdata; for (;;) { . . OSMutexPend(DispMutex, 0, &err); . is if _ */ . signaled!
/* The only way this task continues /* _ the mutex is available or */
} }
463
OSMutexPost() INT8U OSMutexPost(OS_EVENT *pevent);
Chapter 8
File
Called from Task
OS_MUTEX.C
Code enabled by OS_MUTEX_EN
A mutex is signaled (i.e., released) by calling OSMutexPost(). You call this function only if you acquire the mutex by first calling either OSMutexAccept() or OSMutexPend(). If the priority of the task that owns the mutex has been raised when a higher priority task attempts to acquire the mutex, the original task priority of the task is restored. If one or more tasks are waiting for the mutex, the mutex is given to the highest priority task waiting on the mutex. The scheduler is then called to determine if the awakened task is now the highest priority task ready to run, and if so, a context switch is done to run the readied task. If no task is waiting for the mutex, the mutex value is simply set to available (0xFF).
Arguments pevent
is a pointer to the mutex. This pointer is returned to your application when the mutex is created [see OSMutexCreate()].
Returned Value OSMutexPost() returns one of these error codes: OS_NO_ERR
if the call is successful and the mutex is released.
OS_ERR_EVENT_TYPE
if you don’t pass a pointer to a mutex to OSMutexPost().
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_POST_ISR
if you attempt to call OSMutexPost() from an ISR.
OS_ERR_NOT_MUTEX_OWNER
if the task posting (i.e., signaling the mutex) doesn’t actually own the mutex.
Notes/Warnings 1.
Mutexes must be created before they are used.
2.
You cannot call this function from an ISR.
464
Example OS_EVENT
void
*DispMutex;
TaskX (void *pdata)
{ INT8U
err;
pdata = pdata; for (;;) { . . err = OSMutexPost(DispMutex); switch (err) { case OS_NO_ERR: /* Mutex signaled . . break;
case OS_ERR_EVENT_TYPE: . . break;
case OS_ERR_PEVENT_NULL: . . break;
case OS_ERR_POST_ISR: . . break;
} . . } }
465
*/
OSMutexQuery() INT8U OSMutexQuery(OS_EVENT *pevent, OS_MUTEX_DATA *pdata);
Chapter 8
File
Called from
OS_MUTEX.C
Task
Code enabled by OS_MUTEX_EN && OS_MUTEX_QUERY_EN
OSMutexQuery() is used to obtain run-time information about a mutex. Your application must allocate an OS_MUTEX_DATA data structure that is used to receive data from the event control block of the mutex. OSMutexQuery() allows you to determine whether any task is waiting on the mutex, how many tasks are waiting (by counting the number of 1s) in the .OSEventTbl[] field, obtain the PIP, and determine whether the mutex is available (1) or not (0). Note that the size of .OSEventTbl[] is established by the #define constant OS_EVENT_TBL_SIZE (see uCOS_II.H).
Arguments pevent
is a pointer to the mutex. This pointer is returned to your application when the mutex is created [see OSMutexCreate()].
pdata
is a pointer to a data structure of type OS_MUTEX_DATA, which contains the following fields
INT8U
OSMutexPIP;
/* The PIP of the mutex
*/
INT8U
OSOwnerPrio;
/* The priority of the mutex owner
*/
INT8U
OSValue;
/* The current mutex value, 1 means available, */ /* 0 means unavailable */
INT8U
OSEventGrp;
/* Copy of the mutex wait list
INT8U
OSEventTbl[OS_EVENT_TBL_SIZE];
*/
Returned Value OSMutexQuery() returns one of these error codes: OS_NO_ERR
if the call is successful.
OS_ERR_EVENT_TYPE
if you don’t pass a pointer to a mutex to OSMutexQuery().
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
OS_ERR_QUERY_ISR
if you attempt to call OSMutexQuery() from an ISR.
Notes/Warnings 1.
Mutexes must be created before they are used.
2.
You cannot call this function from an ISR.
466
Example In this example, we check the contents of the mutex to determine the highest priority task that is waiting for it. OS_EVENT *DispMutex;
void Task (void *pdata) { OS_MUTEX_DATA mutex_data; INT8U
err;
INT8U
highest;
INT8U
x;
INT8U
y;
/* Highest priority task waiting on mutex
*/
pdata = pdata; for (;;) { . . err = OSMutexQuery(DispMutex, &mutex_data); if (err == OS_NO_ERR) { if (mutex_data.OSEventGrp != 0x00) { y
= OSUnMapTbl[mutex_data.OSEventGrp];
x
= OSUnMapTbl[mutex_data.OSEventTbl[y]];
highest = (y 0) { .
/* Resource available,
process */ . } . . } }
486
OSSemCreate() OS_EVENT *OSSemCreate(INT16U value);
Chapter 7
File OS_SEM.C
Called from Task or startup code
Code enabled by OS_SEM_EN
OSSemCreate() creates and initializes a semaphore. A semaphore
•
allows a task to synchronize with either an ISR or a task (you initialize the semaphore to 0),
•
gains exclusive access to a resource (you initialize the semaphore to a value greater than 0), and
•
signals the occurrence of an event (you initialize the semaphore to 0).
Arguments is the initial value of the semaphore and can be between 0 and 65,535. A value of 0 indicates that a resource is not available or an event has not occurred.
value
Returned Value OSSemCreate() returns a pointer to the event control block allocated to the semaphore. If no event control block is available, OSSemCreate() returns a NULL pointer.
Notes/Warnings 1.
Semaphores must be created before they are used.
Example OS_EVENT *DispSem;
void main (void) { . . OSInit();
/* Initialize µC/OS-II
*/
/* Create Display Semaphore
*/
/* Start Multitasking
*/
. . DispSem = OSSemCreate(1); . . OSStart(); }
487
OSSemDel() OS_EVENT *OSSemDel(OS_EVENT *pevent, INT8U opt, INT8U *err);
Chapter 7
File
Called from
OS_SEM.C
Code enabled by
Task
OS_SEM_EN and OS_SEM_DEL_EN
OSSemDel() is used to delete a semaphore. This function is dangerous to use because multiple tasks could
attempt to access a deleted semaphore. You should always use this function with great care. Generally speaking, before you delete a semaphore, you must first delete all the tasks that can access the semaphore.
Arguments pevent
is a pointer to the semaphore. This pointer is returned to your application when the semaphore is created [see OSSemCreate()].
opt
specifies whether you want to delete the semaphore only if there are no pending tasks (OS_DEL_NO_PEND) or whether you always want to delete the semaphore regardless of whether tasks are pending or not (OS_DEL_ALWAYS). In this case, all pending task are readied.
err
is a pointer to a variable that is used to hold an error code. The error code can be one of the following: OS_NO_ERR
if the call is successful and the semaphore has been deleted.
OS_ERR_DEL_ISR
if you attempt to delete the semaphore from an ISR.
OS_ERR_INVALID_OPT
if you don’t specify one of the two options mentioned in the opt argument.
OS_ERR_TASK_WAITING
if one or more tasks are waiting on the semaphore.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a semaphore.
OS_ERR_PEVENT_NULL
if no more OS_EVENT structures are available.
Returned Value A NULL pointer if the semaphore is deleted or pevent if the semaphore is not deleted. In the latter case, you need to examine the error code to determine the reason.
Notes/Warnings 1.
You should use this call with care because other tasks might expect the presence of the semaphore.
2.
Interrupts are disabled when pended tasks are readied, which means that interrupt latency depends on the number of tasks that are waiting on the semaphore.
488
Example OS_EVENT *DispSem;
void Task (void *pdata) { INT8U
err;
pdata = pdata; while (1) { . . DispSem = OSSemDel(DispSem, OS_DEL_ALWAYS, &err); if (DispSem == (OS_EVENT *)0) { /* Semaphore has been deleted */ } . . } }
489
OSSemPend() void OSSemPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
Chapter 7
File
Called from Task only
OS_SEM.C
Code enabled by OS_SEM_EN
OSSemPend() is used when a task wants exclusive access to a resource, needs to synchronize its activities with an ISR or a task, or is waiting until an event occurs. If a task calls OSSemPend() and the value of the semaphore is greater than 0, OSSemPend() decrements the semaphore and returns to its caller. However, if the value of the semaphore is 0, OSSemPend() places the calling task in the waiting list for the semaphore. The task waits until a task or an ISR signals the semaphore or the specified timeout expires. If the semaphore is signaled before the timeout expires, µC/OS-II resumes the highest priority task waiting for the semaphore. A pended task that has been suspended with OSTaskSuspend() can obtain the semaphore. However, the task remains suspended until it is resumed by calling OSTaskResume().
Arguments pevent
is a pointer to the semaphore. This pointer is returned to your application when the semaphore is created [see OSSemCreate()].
timeout
allows the task to resume execution if a message is not received from the mailbox within the specified number of clock ticks. A timeout value of 0 indicates that the task waits forever for the message. The maximum timeout is 65,535 clock ticks. The timeout value is not synchronized with the clock tick. The timeout count begins decrementing on the next clock tick, which could potentially occur immediately.
err
is a pointer to a variable used to hold an error code. OSSemPend() sets *err to one of the following: OS_NO_ERR
if the semaphore is available.
OS_TIMEOUT
if the semaphore is not signaled within the specified timeout.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a semaphore.
OS_ERR_PEND_ISR
if you called this function from an ISR and µC/OS-II has to suspend it. You should not call OSSemPend() from an ISR. µC/OS-II checks for this situation.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
Returned Value none
Notes/Warnings 1.
Semaphores must be created before they are used.
490
Example OS_EVENT *DispSem;
void DispTask (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { . . OSSemPend(DispSem, 0, &err); .
/* The only way this task continues is if _ */
.
/* _ the semaphore is signaled!
} }
491
*/
OSSemPost() INT8U OSSemPost(OS_EVENT *pevent);
Chapter 7
File
Called from
Code enabled by
Task or ISR
OS_SEM.C
OS_SEM_EN
A semaphore is signaled by calling OSSemPost(). If the semaphore value is 0 or more, it is incremented, and OSSemPost() returns to its caller. If tasks are waiting for the semaphore to be signaled, OSSemPost() removes the highest priority task pending for the semaphore from the waiting list and makes this task ready to run. The scheduler is then called to determine if the awakened task is now the highest priority task ready to run.
Arguments pevent
is a pointer to the semaphore. This pointer is returned to your application when the semaphore is created [see OSSemCreate()].
Returned Value OSSemPost() returns one of these error codes: OS_NO_ERR
if the semaphore is signaled successfully.
OS_SEM_OVF
if the semaphore count overflows.
OS_ERR_EVENT_TYPE
if pevent is not pointing to a semaphore.
OS_ERR_PEVENT_NULL
if pevent is a NULL pointer.
Notes/Warnings 1.
Semaphores must be created before they are used.
492
Example OS_EVENT *DispSem;
void TaskX (void *pdata) { INT8U
err;
pdata = pdata; for (;;) { . . err = OSSemPost(DispSem); switch (err) { case OS_NO_ERR: /* Semaphore signaled break;
*/
case OS_SEM_OVF: /* Semaphore has overflowed */ break; . . } . . } }
493
OSSemQuery() INT8U OSSemQuery(OS_EVENT *pevent, OS_SEM_DATA *pdata);
Chapter
File
7
OS_SEM.C
Called from Task or ISR
Code enabled by OS_SEM_EN && OS_SEM_QUERY_EN
OSSemQuery() obtains information about a semaphore. Your application must allocate an OS_SEM_DATA data structure used to receive data from the event control block of the semaphore. OSSemQuery() allows you to determine whether any tasks are waiting on the semaphore and how many tasks are waiting (by counting the number of 1s in the .OSEventTbl[] field) and obtains the semaphore count. Note that the size of .OSEventTbl[] is established by the #define constant OS_EVENT_TBL_SIZE (see uCOS_II.H).
Arguments pevent
is a pointer to the semaphore. This pointer is returned to your application when the semaphore is created [see OSSemCreate()].
pdata
is a pointer to a data structure of type OS_SEM_DATA, which contains the following fields
INT16U OSCnt; */
/* Current semaphore count
INT8U */
OSEventTbl[OS_EVENT_TBL_SIZE];
/* Semaphore wait list
INT8U
OSEventGrp;
Returned Value OSSemQuery() returns one of these error codes: OS_NO_ERR
if the call is successful.
OS_ERR_EVENT_TYPE
if you don’t pass a pointer to a semaphore.
OS_ERR_PEVENT_NULL
if pevent is is a NULL pointer.
Notes/Warnings 1.
Semaphores must be created before they are used.
494
Example In this example, the contents of the semaphore is checked to determine the highest priority task waiting at the time the function call was made. OS_EVENT *DispSem;
void Task (void *pdata) { OS_SEM_DATA sem_data; INT8U
err;
INT8U
highest; /* Highest priority task waiting on sem. */
INT8U
x;
INT8U
y;
pdata = pdata; for (;;) { . . err = OSSemQuery(DispSem, &sem_data); if (err == OS_NO_ERR) { if (sem_data.OSEventGrp != 0x00) { y
= OSUnMapTbl[sem_data.OSEventGrp];
x
= OSUnMapTbl[sem_data.OSEventTbl[y]];
highest = (y OSTCBStkPtr = SS:SP
MOV
ES:[BX+2], SS
;
MOV
ES:[BX+0], SP
;
CALL
FAR
PTR
_OSTimeTick
; Process clock tick
.
; User Code to clear interrupt
. CALL FAR PTR _OSIntExit
; Notify µC/OS-II of end of ISR
POP
DS
; Restore processor registers
POP
ES
POPA ; IRET
; Return to interrupted task
531
_OSTickISR
ENDP
OSVersion() INT16U OSVersion(void);
Chapter 3
File
Called from Task or ISR
OS_CORE.C
Code enabled by N/A
OSVersion() obtains the current version of µC/OS-II.
Arguments none
Returned Value The version is returned as x.yy multiplied by 100. For example, v2.60 is returned as 260.
Notes/Warnings none
Example void TaskX (void *pdata) { INT16U os_version;
for (;;) { . . os_version = OSVersion();
/* Obtain µC/OS-II's version
. . } }
532
*/