Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Also, the small hourglass close to the receiving task indicates that the task has an option to specify a timeout. This timeout indicates that the task is willing to wait for the semaphore to be signaled (or posted to) within a certain amount of time. If the semaphore is not signaled within that time, µC/OS-III resumes the task and returns an error code indicating that the task was made ready-to-run because of a timeout and not the semaphore was signaled.

Panel
borderWidth0
titleµC/OS-III Semaphore Services

...

The figure below shows that a task can be synchronized with an ISR (or another task) by using a semaphore. In this case, no data is exchanged, however there is an indication that the ISR or the task (on the left) has occurred. Using a semaphore for this type of synchronization is called a unilateral rendez-vous.

Panel
borderWidth0
titleUnilateral Rendezvous

A unilateral rendez-vous is used when a task initiates an I/O operation and waits (i.e., call OSSemPend()) for the semaphore to be signaled (posted). When the I/O operation is complete, an ISR (or another task) signals the semaphore (i.e., calls OSSemPost()), and the task is resumed. This process is also shown on the timeline of the figure below and described below. The code for the ISR and task is shown in the listing follows the figure below.

Panel
borderWidth0
titleUnilateral Rendezvous, Timing Diagram

...

As previously mentioned, a semaphore “remembers” how many times it was signaled (or posted to). In other words, if the ISR occurs multiple times before the task waiting for the event becomes the highest-priority task, the semaphore will keep count of the number of times it was signaled. When the task becomes the highest priority ready-to-run task, it will execute without blocking as many times as there were ISRs signaled. This is called Credit Tracking and is illustrated in the figure below and described below.

Panel
borderWidth0
titleSemaphore Credit Tracking

...

It is possible for more than one task to wait on the same semaphore, each with its own timeout as illustrated in the figure below.

Panel
borderWidth0
titleMultiple tasks waiting on a Semaphore

...

Code Block
titleOS_SEM data type
typedef  struct  os_sem  OS_SEM;              (1) 
 
 
struct  os_sem {
    OS_OBJ_TYPE          Type;                (2) 
    CPU_CHAR            *NamePtr;             (3) 
    OS_PEND_LIST         PendList;            (4) 
    OS_SEM_CTR           Ctr;                 (5) 
    CPU_TS               TS;                  (6) 
};


Panel
bgColor#f0f0f0

(1) In µC/OS-III, all structures are given a data type. In fact, all data types start with “OS_” and are all uppercase. When a semaphore is declared, simply use OS_SEM as the data type of the variable used to declare the semaphore.

(2) The structure starts with a “Type” field, which allows it to be recognized by µC/OS-III as a semaphore. In other words, other kernel objects will also have a “Type” as the first member of the structure. If a function is passed a kernel object, µC/OS-III will confirm that it is being passed the proper data type (assuming OS_CFG_OBJ_TYPE_CHK_EN is set to DEF_ENABLED in os_cfg.h). For example, if passing a message queue (OS_Q) to a semaphore service (for example OSSemPend()), µC/OS-III will recognize that an invalid object was passed, and return an error code accordingly.

(3) Each kernel object can be given a name to make them easier to be recognized by debuggers or µC/Probe. This member is simply a pointer to an ASCII string, which is assumed to be NUL terminated.

(4) Since it is possible for multiple tasks to be waiting (or pending) on a semaphore, the semaphore object contains a pend list as described in Pend Lists.

(5) A semaphore contains a counter. As explained above, the counter can be implemented as either an 8-, 16- or 32-bit value, depending on how the data type OS_SEM_CTR is declared in os_type.h. µC/OS-III keeps track of how many times the semaphore is signaled with this counter and this field is typically initialized to zero by OSSemCreate().

(6) A semaphore contains a time stamp, which is used to indicate the last time the semaphore was signaled (or posted to). µC/OS-III assumes the presence of a free-running counter that allows the application to make time measurements. When the semaphore is signaled, the free-running counter is read and the value is placed in this field, which is returned when OSSemPend() is called. This value allows the application to determine either when the signal was performed, or how long it took for the task to get control of the CPU from the signal. In the latter case, you should call OS_TS_GET() to determine the current timestamp and compute the difference.

...

Panel
bgColor#f0f0f0

(1) Your task signals (or posts to) the semaphore by calling OSSemPost(). You specify the semaphore to post by passing its address. The semaphore must have been previously created.

(2) The next argument specifies how the task wants to post. There are a number of options to choose from.

When you specify OS_OPT_POST_1, you are indicating that you want to post to only one task (in case there are multiple tasks waiting on the semaphore). The task that will be made ready-to-run will be the highest-priority task waiting on the semaphore. If there are multiple tasks at the same priority, only one of them will be made ready-to-run. As shown in the figure below, tasks waiting are in priority order (HPT means High Priority Task and LPT means Low Priority Task). So, it is a fast operation to extract the HPT from the list.

If specifying OS_OPT_POST_ALL, all tasks waiting on the semaphore will be posted and made ready-to-run.

The calling task can “add” the option OS_OPT_POST_NO_SCHED to either of the two previous options to indicate that the scheduler is not to be called at the end of OSSemPost(), possibly because additional postings will be performed, and rescheduling should only take place when finished. This means that the signal is performed, but the scheduler is not called even if a higher-priority task was waiting for the semaphore to be signaled. This allows the calling task to perform other post functions (if needed) and make all the posts take effect simultaneously. Note that OS_OPT_POST_NO_SCHED is “additive,” meaning that it can be used with either of the previous options. You can thus specify:

OS_OPT_POST_1 
OS_OPT_POST_ALL
OS_OPT_POST_1   + OS_OPT_POST_NO_SCHED
OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
Panel
bgColor#f0f0f0
borderWidth0
titleTasks waiting for Semaphore

(3) OSSemPost() returns an error code based on the outcome of the call. If the call was successful, err will contain OS_ERR_NONE. If not, the error code will indicate the reason for the error (see Appendix A, µC-OS-III API Reference for a list of possible error codes for OSSemPost()).

...