...
Anchor
0
, and the task continues execution (owning the resource). If the semaphore’s value is 0, the task performing a Wait on the semaphore is placed in a waiting list. µC/OS-III allows a timeout to be specified. If the semaphore is not available within a certain amount of time, the requesting task is made ready-to-run, and an error code (indicating that a timeout has occurred) is returned to the caller.anchor1
. If there is at least one task waiting for the semaphore, the highest-priority task waiting on the semaphore is made ready-to-run, and the semaphore value is not incremented. If the readied task has a higher priority than the current task (the task releasing the semaphore), a context switch occurs and the higher-priority task resumes execution. The current task is suspended until it again becomes the highest-priority task that is ready-to-run. Anchor
Code Block |
---|
...
| ||
OS_SEM MySem; (1)
void main (void)
{
OS_ERR err;
:
:
OSInit(&err);
:
OSSemCreate(&MySem, (2)
"My Semaphore", (3)
1, (4)
&err); (5)
/* Check "err" */
:
/* Create task(s) */
:
OSStart(&err);
(void)err;
} |
Panel | ||||
---|---|---|---|---|
| ||||
(1) The application must declare a semaphore as a variable of |
...
type |
...
(2) You create a semaphore by |
...
calling |
...
and pass the address to the semaphore allocated in (1). The semaphore must be created before it can be used by other tasks. Here, the semaphore is initialized in startup code (i.e., |
...
(3) You can assign an ASCII name to the semaphore, which can be used by debuggers or µC/Probe to easily identify the semaphore. Storage for the ASCII characters is typically in ROM, which is typically more plentiful than RAM. If it is necessary to change the name of the semaphore at runtime, you can store the characters in an array in RAM and simply pass the address of the array |
...
to |
...
(4) You specify the initial value of the semaphore. You should initialize the semaphore to 1 when the semaphore is used to access a single shared resource (as in this example). |
...
(5) |
...
returns an error code based on the outcome of the call. If all the arguments are valid, |
...
will contain |
...
of |
...
in Appendix A, µC/OS-III API |
...
Reference for a list of other error codes and their meaning. |
...
Code Block |
---|
...
HTML Table | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
summary | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class | Code_Listing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Table Row (tr) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Table Cell (td) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070849 | 1070849 | void Task1 (void
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void Task1 (void *p_arg) Anchor | | 1070850 | 1070850 | {||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070851 | 1070851 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070852 | 1070852 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070853 | 1070853 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070854 | 1070854 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070855 | 1070855 | while|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070856 | 1070856 | :|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070857 | 1070857 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070858 | 1070858 | 0, (2)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070859 | 1070859 | OS_OPT_PEND_BLOCKING, (3)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070860 | 1070860 | &ts, (4)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070861 | 1070861 | &err); (5)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070862 | 1070862 | switch (err) {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070863 | 1070863 | case OS_ERR_NONE:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070864 | 1070864 | Access Shared Resource; (6)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070865 | 1070865 | OSSemPost(&MySem, (7)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070866 | 1070866 | OS_OPT_POST_1, (8)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070867 | 1070867 | &err); (9)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070868 | 1070868 | /* Check “err” */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070869 | 1070869 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070870 | 1070870 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070871 | 1070871 | case OS_ERR_PEND_ABORT:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070872 | 1070872 | /* The pend was aborted by another task */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070873 | 1070873 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070874 | 1070874 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070875 | 1070875 | case OS_ERR_OBJ_DEL:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070877 | 1070877 | /* The semaphore was deleted */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070878 | 1070878 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070879 | 1070879 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070880 | 1070880 | default:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070881 | 1070881 | /* Other errors */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070882 | 1070882 | }|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070883 | 1070883 | :|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070884 | 1070884 | }|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070885 | 1070885 | }
...
(1)
0, (2)
OS_OPT_PEND_BLOCKING, (3)
&ts, (4)
&err); (5)
switch (err) {
case OS_ERR_NONE:
Access Shared Resource; (6)
OSSemPost(&MySem, (7)
OS_OPT_POST_1, (8)
&err); (9)
/* Check "err" */
break;
case OS_ERR_PEND_ABORT:
/* The pend was aborted by another task */
break;
case OS_ERR_OBJ_DEL:
/* The semaphore was deleted */
break;
default:
/* Other errors */
}
:
}
} |
Panel | ||
---|---|---|
| ||
(1) The task pends (or waits) on the semaphore by |
...
calling |
...
(2) The next argument is a timeout specified in number of clock ticks. The actual timeout depends on the tick rate. If the tick rate ( |
...
see |
...
(3) The third argument specifies how to wait. There are two options: |
...
and |
...
calling |
...
will wait until the semaphore is posted or until the timeout expires. The non-blocking option indicates that if the semaphore is not available, |
...
will return immediately and not wait. This last option is rarely used when using a semaphore to protect a shared resource. |
...
(4) When the semaphore is posted, µC/OS-III reads a “timestamp” and returns this timestamp |
...
when |
...
returns. This feature allows the application to know “when” the post happened and the semaphore was released. At this point, |
...
is read to get the current timestamp and you can compute the difference, indicating the length of the wait. |
...
(5) |
...
returns an error code based on the outcome of the call. If the call is successful, |
...
will contain |
...
Appendix A, µC-OS-III |
...
Configuration Manual for a list of possible error code |
...
for |
...
(6) The resource can be accessed |
...
when |
...
returns, if there are no errors. |
...
(7) When finished accessing the resource, you simply |
...
call |
...
and specify the semaphore to be released. |
...
(8) |
...
indicates that the semaphore is signaling a single task, if there are many tasks waiting on the semaphore. In fact, you should always specify this option when a semaphore is used to access a shared resource. |
...
(9) As with most µC/OS-III functions, you specify the address of a variable that will |
...
HTML Table | |
---|---|
summary | |
class | Code_Listing | Table Row (tr) | Table Cell (td) | Anchor | | 1070918 | 1070918 | void Task2 (void
Code Block | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void Task2 (void *p_arg) Anchor | | 1070919 | 1070919 | {||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070920 | 1070920 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070921 | 1070921 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070922 | 1070922 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070923 | 1070923 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070924 | 1070924 | while (DEF_ON) {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070925 | 1070925 | :|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070926 | 1070926 | OSSemPend(&MySem, (1)|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070927 | 1070927 | 0,|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070928 | 1070928 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070929 | 1070929 | &ts,|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070930 | 1070930 | &err);|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070931 | 1070931 | switch (err) {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070932 | 1070932 | case OS_ERR_NONE:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070933 | 1070933 | Access Shared Resource;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070934 | 1070934 | OSSemPost(&MySem,|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070935 | 1070935 | OS_OPT_POST_1,|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070936 | 1070936 | &err);|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070937 | 1070937 | /* Check “err” */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070938 | 1070938 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070939 | 1070939 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070940 | 1070940 | case OS_ERR_PEND_ABORT:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070941 | 1070941 | /* The pend was aborted by another task */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070942 | 1070942 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070943 | 1070943 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070944 | 1070944 | case OS_ERR_OBJ_DEL:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070946 | 1070946 | /* The semaphore was deleted */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070947 | 1070947 | break;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070948 | 1070948 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070949 | 1070949 | default:|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070950 | 1070950 | /* Other errors */|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070951 | 1070951 | }|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070952 | 1070952 | :|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070953 | 1070953 | }|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070954 | 1070954 | }
...
&ts,
&err);
switch (err) {
case OS_ERR_NONE:
Access Shared Resource;
OSSemPost(&MySem,
OS_OPT_POST_1,
&err);
/* Check "err" */
break;
case OS_ERR_PEND_ABORT:
/* The pend was aborted by another task */
break;
case OS_ERR_OBJ_DEL:
/* The semaphore was deleted */
break;
default:
/* Other errors */
}
:
}
} |
Panel | ||
---|---|---|
| ||
(1) Another task wanting to access the shared resource needs to use the same procedure to access the shared resource. |
...
Semaphores are especially useful when tasks share I/O devices. Imagine what would happen if two tasks were allowed to send characters to a printer at the same time. The printer would contain interleaved data from each task. For instance, the printout from Task 1 Task 1 printing “I am Task 1Task 1,” and Task 2 Task 2 printing “I am Task 2Task 2,” could result in “I Ia amm T Tasask k1 2”. In this case, you can use a semaphore and initialize it to 1 (i.e., a binary semaphore). The rule is simple: to access the printer each task must first obtain the resource’s semaphore. Figure 13-1 The figure below shows tasks competing for a semaphore to gain exclusive access to the printer. Note that a key, indicating that each task must obtain this key to use the printer, represents the semaphore symbolically.anchor
...
Panel |
---|
...
|
...
The above example implies that each task knows about the existence of the semaphore to access the resource. It is almost always better to encapsulate the critical section and its protection mechanism. Each task would therefore not know that it is acquiring a semaphore when accessing the resource. For example, an RS-232C port is used by multiple tasks to send commands and receive responses from a device connected at the other end as shown in Figure 13-2the figure below. Anchor
...
...
Panel | ||
---|---|---|
|
...
CommSendCmd()
is called with three arguments: the ASCII string containing the command, a pointer to the response string from the device, and finally, a timeout in case the device does not respond within a certain amount of time. The pseudo-code for this function is shown in Listing 13-8the listing below.anchorCode Block |
---|
...
HTML Table | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
summary | ||||||||||||||||||||||||||||||||||||||||||
class | Code_Listing | |||||||||||||||||||||||||||||||||||||||||
Table Row (tr) | ||||||||||||||||||||||||||||||||||||||||||
Table Cell (td) | ||||||||||||||||||||||||||||||||||||||||||
Anchor | 1070974 | 1070974
| ||||||||||||||||||||||||||||||||||||||||
APP_ERR CommSendCmd (CPU_CHAR *cmd, Anchor | | 1070975 | 1070975 | |||||||||||||||||||||||||||||||||||||||
Anchor | 1070976 | 1070976 | OS_TICK timeout)||||||||||||||||||||||||||||||||||||||||
Anchor | 1070977 | 1070977 | {||||||||||||||||||||||||||||||||||||||||
Anchor | 1070979 | 1070979 | Acquire serial port’s semaphore;||||||||||||||||||||||||||||||||||||||||
Anchor | 1070980 | 1070980 | Send “cmd” to device;||||||||||||||||||||||||||||||||||||||||
Anchor | 1070981 | 1070981 | Wait for response with “timeout”;||||||||||||||||||||||||||||||||||||||||
Anchor | 1070982 | 1070982 | if (timed out) {||||||||||||||||||||||||||||||||||||||||
Anchor | 1070984 | 1070984 | Release serial port’s semaphore;||||||||||||||||||||||||||||||||||||||||
Anchor | 1070985 | 1070985 | return (error code);||||||||||||||||||||||||||||||||||||||||
Anchor | 1070986 | 1070986 | } else {||||||||||||||||||||||||||||||||||||||||
Anchor | 1070988 | 1070988 | Release serial port’s semaphore;||||||||||||||||||||||||||||||||||||||||
Anchor | 1070989 | 1070989 | return (no error);||||||||||||||||||||||||||||||||||||||||
Anchor | 1070990 | 1070990 | }||||||||||||||||||||||||||||||||||||||||
Anchor | 1070991 | 1070991 | }
...
*response,
OS_TICK timeout)
{
Acquire serial port's semaphore;
Send "cmd" to device;
Wait for response with "timeout";
if (timed out) {
Release serial port's semaphore;
return (error code);
} else {
Release serial port's semaphore;
return (no error);
}
} |
Each task that needs to send a command to the device must call this function. The semaphore is assumed to be initialized to 1 (i.e., available) by the communication driver initialization routine. The first task that calls CommSendCmd()
acquires the semaphore, proceeds to send the command, and waits for a response. If another task attempts to send a command while the port is busy, this second task is suspended until the semaphore is released. The second task appears simply to have made a call to a normal function that will not return until the function performs its duty. When the semaphore is released by the first task, the second task acquires the semaphore and is allowed to use the RS-232C port.