The whole truth about RTOS. Article # 19. Semaphores: introduction and basic services

 
3r3-31. The whole truth about RTOS. Article # 19. Semaphores: introduction and basic services 3r3612.  
3r3612.  
Semaphores have been mentioned in a previous article (# 5). Their main task is to control access to resources. 3r3612.  
Article # 18. Event flag groups: ancillary services and data structures 3r3612.  
Article # 17. Event flag groups: introduction and basic services 3r361717. 3r3612.  
Article # 16. Signals 3r31717. 3r3612.  
Article # 15. Memory sections: services and data structures
3r3612.  
3r3331. Article # 14. Memory sections: introduction and basic services 3r361717. 3r3612.  
3r3335. Article # 13. Task data structures and unsupported API calls 3r336177. 3r3612.  
Article # 12. Service to work with tasks 3r3612.  
Article # 11. Tasks: configuration and introduction to API 3r3612.  
Article # 10. Scheduler: Advanced Features and Context Preservation 3-3-33617. 3r3612.  
Article # 9. Scheduler: Implementation
3r3612.  
3r3355. Article # 8. Nucleus SE: internal design and deployment
3r3612.  
Article # 7. Nucleus SE: Introduction 3r3612.  
3r3633. Article # 6. Other RTOS services
3r3612.  
Article # 5. Interaction between tasks and synchronization 3r3612.  
Article # 4. Tasks, context switching and interrupts 3r3-3617. 3r3612.  
3r375. Article # 3. Tasks and planning 3r3-31717. 3r3612.  
Article # 2. RTOS: Structure and Real Time 3r3-3612.  
Article # 1. RTOS: introduction. 3r3612.  
3r31717. 3r3612.  

The use of semaphores

3r3612.  
In Nucleus SE, semaphores are defined at the assembly stage. An application can have up to 16 semaphores. If semaphores are not specified, the code for service calls and data structures is not included in the application. 3r3612.  
3r3612.  
A semaphore is a 3r-31414 type counter. U8 3r3615. which is controlled in such a way that several tasks can use it. A task can reduce the semaphore count (capture) or increase it (release). Attempting to capture a semaphore with a null value may result in an error or a suspension of the task, depending on the selected API call parameters and the configuration of the Nucleus SE. 3r3612.  
3r3612.  

Setting up semaphores

3r3612.  
3r33469. The number of semaphores
3r3612.  
As with most Nucleus SE objects, the semaphore setting is determined by the directives 3r-31414. #define [/b] in 3r3614. nuse_config.h [/b] . The main parameter is NUSE_SEMAPHORE_NUMBER that determines the number of semaphores in the application. By default, the parameter is set to 0 (semaphores are not used in the application) and can take any value up to 16. An incorrect value will result in a compilation error, which will be generated by checking in 3r3614. nuse_config_check.h [/b] (this file is included in 3r3146. nuse_config.c 3r3-3615., which means it is compiled with this module), as a result, the directive 3r?33614 will work. #error [/b] . 3r3612.  
3r3612.  
The choice of a non-zero value serves as the main activator for semaphores. This parameter is used when defining data structures and their size depends on its size (for more details, read later in this article). In addition, a non-zero value activates the API settings. 3r3612.  
3r3612.  
3r33469. Activate API calls
3r3612.  
Each API function (service call) in Nucleus SE is activated by the directive 3r-33614. #define [/b] in 3r3614. nuse_config.h [/b] . For semaphores, these include: 3r36122.  
3r3-3568. NUSE_SEMAPHORE_OBTAIN
 
NUSE_SEMAPHORE_RELEASE
 
NUSE_SEMAPHORE_RESET 3r336126.  
NUSE_SEMAPHORE_INFORMATION
 
NUSE_SEMAPHORE_COUNT
 
3r3602. 3r3612.  
By default, they are assigned the value FALSE 3r315615. thus disabling every service call and blocking the inclusion of the code that implements them. To set up the semaphores, you need to select the necessary API calls and set the corresponding directives to 3r-33614. TRUE 3R3-3615. . 3r3612.  
3r3612.  
Below is an excerpt from the file nuse_config.h default. 3r3612.  
3r? 3567. 3r3-3568. #define NUSE_SEMAPHORE_NUMBER 0 /* Number of semaphores in
the system - 0-16 * /
#define NUSE_SEMAPHORE_OBTAIN FALSE /* Service call enabler * /
#define NUSE_SEMAPHORE_RELEASE FALSE /* Service call enabler * /
#define NUSE_SEMAPHORE_RESET FALSE /* Service call enabler * /
#define NUSE_SEMAPHORE_INFORMATION FALSE /* Service call enabler * /
#define NUSE_SEMAPHORE_COUNT FALSE /* Service call enabler * /
3r3602.
3r3612.  
An activated API function in the absence of semaphores in the application will result in a compilation error (except 3r3-33614. NUSE_Semaphore_Count () 3r336155., Which is always enabled). If your code uses an API call that has not been activated, a build error will occur because the implementation code was not included in the application. 3r3612.  
3r3612.  

Service calls semaphores

3r3612.  
Nucleus RTOS supports eight service calls that provide the following functionality: 3r-33612.  
3r3190.  
Capture semaphore. The Nucleus SE is implemented in function 3r3-3144. NUSE_Semaphore_Obtain ()
.
 
Semaphore release. The Nucleus SE is implemented in function 3r3-3144. NUSE_Semaphore_Release () 3r33615. .
 
Returning the semaphore to an unused state with the release of all suspended tasks (reboot). The Nucleus SE is implemented in 3r33614. NUSE_Semaphore_Reset () 3r336155. .
 
Providing information about a specific semaphore. The Nucleus SE is implemented in 3r33614. NUSE_Semaphore_Information () 3r33615. .
 
Returns the number of configured semaphores in the application. The Nucleus SE is implemented in 3r33614. NUSE_Semaphore_Count () 3r3361515. .
 
Adding a new semaphore to the application. Nucleus SE is not implemented.
 
Remove semaphore from application. Nucleus SE is not implemented.
 
Return pointers to all semaphores. Nucleus SE is not implemented.
 
3r3612.  
The implementation of each service call is described in detail below. 3r3612.  
3r3612.  
Service calls capture and release of semaphores 3r3-33234. 3r3612.  
The fundamental operations that can be performed on semaphores are capture and release (decrease and increase in value). Nucleus RTOS and Nucleus SE provide two basic API calls for these operations. 3r3612.  
3r3612.  
3r33469. Capture semaphore
3r3612.  
The Nucleus RTOS service call to capture a semaphore is very flexible and allows you to suspend tasks implicitly or with a specific timeout if the operation cannot be performed at the moment, for example, if you try to capture a zero-value semaphore. Nucleus SE provides the same functions, only task suspension is optional, and timeout is not implemented. 3r3612.  
3r3612.  
3r31414. 3r33554. The call to capture the semaphore in the Nucleus RTOS 3r33555. 3r3615. 3r3612.  
Service Call Prototype: 3r33612.  
3r31414. STATUS NU_Obtain_Semaphore (NU_SEMAPHORE * semaphore, UNSIGNED suspend); 3r3615. 3r3612.  
3r3612.  
Parameters: 3r3612.  
3r31414. semaphore [/b] - pointer to user-supplied semaphore control block; 3r3612.  
3r31414. suspend [/b] - the option to pause the task; it can take the values ​​3r-33614. NU_NO_SUSPEND [/b] or 3r31414. NU_SUSPEND [/b] , as well as the timeout value. 3r3612.  
3r3612.  
Return value: 3r33612.  
3r31414. NU_SUCCESS [/b] - the call was successfully completed; 3r3612.  
3r31414. NU_UNAVAILABLE [/b] - the semaphore had a zero value; 3r3612.  
3r31414. NU_INVALID_SEMAPHORE [/b] - invalid pointer to semaphore; 3r3612.  
3r31414. NU_INVALID_SUSPEND [/b] - an attempt to suspend a non-task related thread; 3r3612.  
3r31414. NU_SEMAPHORE_WAS_RESET [/b] - The semaphore was dropped while the task was suspended. 3r3612.  
3r3612.  
3r31414. 3r33554. Call to capture the semaphore in the Nucleus SE [/i] 3r3615. 3r3612.  
This API call supports Nucleus RTOS API key functionality. 3r3612.  
3r3612.  
Service Call Prototype: 3r33612.  
3r31414. STATUS NUSE_Semaphore_Obtain (NUSE_SEMAPHORE semaphore, U8 suspend); 3r3615. 3r3612.  
3r3612.  
Parameters: 3r3612.  
3r31414. semaphore [/b] - the index (ID) of the semaphore used; 3r3612.  
3r31414. suspend [/b] - the option to pause the task; it can take the value 3r-33614. NUSE_NO_SUSPEND [/b] or 3r31414. NUSE_SUSPEND [/b] . 3r3612.  
3r3612.  
Return value: 3r33612.  
3r31414. NUSE_SUCCESS [/b] - the call was successfully completed; 3r3612.  
3r31414. NUSE_UNAVAILABLE [/b] - the semaphore had a zero value; 3r3612.  
3r31414. NUSE_INVALID_SEMAPHORE [/b] - incorrect semaphore index; 3r3612.  
3r31414. NUSE_INVALID_SUSPEND [/b] - an attempt to suspend from a thread that is not associated with the task or when the API blocking functionality is disabled; 3r3612.  
3r31414. NUSE_SEMAPHORE_WAS_RESET [/b] - the semaphore was discarded while the task was suspended; 3r3612.  
3r3612.  
3r31414. 3r33554. Implementing semaphore capture in the Nucleus SE 3r33555. 3r3615. 3r3612.  
Variant of the function code 3r31414. NUSE_Semaphore_Obtain () [/b] (after checking the parameters) is selected using conditional compilation depending on whether support for blocking (suspending) tasks is activated or not. Consider both options. 3r3612.  
3r3612.  
If the lock is not activated, the logic of this API call is quite simple: 3r336122.  
3r? 3567. 3r3-3568. if (NUSE_Semaphore_Counter[semaphore]! = 0) /* semaphore available * /
{
NUSE_Semaphore_Counter[semaphore]-;
return_value = NUSE_SUCCESS;
}
else /* semaphore unavailable * /
{
return_value = NUSE_UNAVAILABLE;
}
3r3602.
3r3612.  
The value of the semaphore counter is checked, and, if it is not zero, is reduced. 3r3612.  
3r3612.  
If task lock is activated, the logic becomes more complex: 3r33612.  
3r? 3567. 3r3-3568. do
{
if (NUSE_Semaphore_Counter[semaphore]! = 0) /* semaphore available * /
{
NUSE_Semaphore_Counter[semaphore]-;
return_value = NUSE_SUCCESS;
suspend = NUSE_NO_SUSPEND;
}
else /* semaphore unavailable * /
{
if (suspend == NUSE_NO_SUSPEND)
{
return_value = NUSE_UNAVAILABLE;
}
else
{/* block task * /
NUSE_Semaphore_Blocking_Count[semaphore]++;
NUSE_Suspend_Task (NUSE_Task_Active,
Semaphore 4) | NUSE_SEMAPHORE_SUSPEND);
return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active];
if (return_value! = NUSE_SUCCESS)
{
suspend = NUSE_NO_SUSPEND;
}
}
}
} while (suspend == NUSE_SUSPEND);
3r3602.
3r3612.  
3r3612.  
Some explanations may be helpful. 3r3612.  
3r3612.  
The code is placed in a cycle. do while which is executed while parameter suspend has a value of 3r3614. NUSE_SUSPEND [/b] . 3r3612.  
3r3612.  
If the semaphore has a nonzero value, it is reduced. The variable suspend is assigned the value NUSE_NO_SUSPEND , and the API call ends and returns the value 3r33614. NUSE_SUCESS [/b] . 3r3612.  
3r3612.  
If the semaphore is zero, the variable is 3r33614. suspend [/b] set to 3r31414. NUSE_NO_SUSPEND [/b] The API call returns the value 3r31414. NUSE_UNAVAILABLE [/b] . If the suspensione was assigned the value of 3r3144. NUSE_SUSPEND [/b] , the task is suspended. After the end of the call (for example, when the task is resumed), if the return value is 3r-33614. NUSE_SUCCESS [/b] (which indicates that the task was resumed after the semaphore was released, and not after a reset), the cycle starts from the beginning. 3r3612.  
3r3612.  
3r33469. Release semaphore
3r3612.  
The Nucleus RTOS API service call to release a semaphore is quite simple: the value of the semaphore counter increases and a success message is returned. Nucleus SE provides the same features, only with an additional check for overflow. 3r3612.  
3r3612.  
3r31414. 3r33554. The call to release semaphores in the Nucleus RTOS [/i] 3r3615. 3r3612.  
Service Call Prototype: 3r33612.  
3r31414. STATUS NU_Release_Semaphore (NU_SEMAPHORE * semaphore); 3r3615. 3r3612.  
3r3612.  
Parameters: 3r3612.  
3r31414. semaphore [/b] - pointer to user-supplied semaphore control block. 3r3612.  
3r3612.  
Return value: 3r33612.  
3r31414. NU_SUCCESS [/b] - the call was successfully completed; 3r3612.  
3r31414. NU_INVALID_SEMAPHORE [/b] - invalid pointer to semaphore. 3r3612.  
3r3612.  
3r31414. 3r33554. The call to release the semaphore in the Nucleus SE [/i] 3r3615. 3r3612.  
This API call supports the core Nucleus RTOS API. 3r3612.  
3r3612.  
Service Call Prototype: 3r33612.  
3r31414. STATUS NUSE_Semaphore_Release (NUSE_SEMAPHORE semaphore); 3r3615. 3r3612.  
3r3612.  
Parameters: 3r3612.  
3r31414. semaphore [/b] - The index (ID) of the semaphore being released. 3r3612.  
3r3612.  
Return value: 3r33612.  
3r31414. NUSE_SUCCESS [/b] - the call was successfully completed; 3r3612.  
3r31414. NUSE_INVALID_SEMAPHORE [/b] - incorrect semaphore index; 3r3612.  
3r31414. NUSE_UNAVAILABLE [/b] - the semaphore has a value of 25? and it cannot be increased. 3r3612.  
3r3612.  
3r31414. 3r33554. Implementing semaphore release in the Nucleus SE [/i] 3r3615. 3r3612.  
The function code is 3r3614. NUSE_Semaphore_Release () 3r33615. (after checking the parameters) general, regardless of whether the task lock is activated or not. The value of the semaphore counter is checked, and if it is less than 25? it increases. 3r3612.  
3r3612.  
Further code is selected using conditional compilation, if support for blocking API calls (task suspension) is activated: 3r-3122.  
3r? 3567. 3r3-3568. NUSE_CS_Enter ();
. If (NUSE_Semaphore_Counter[semaphore] < 255)
{
NUSE_Semaphore_Counter[semaphore]++;
return_value = NUSE_SUCCESS;
#if NUSE_BLOCKING_ENABLE
if (NUSE_Semaphore_Blocking_Count[semaphore]= 0)
{
U8 index;.! /* Check whether a task is blocked * /
/* on this semaphore * /
NUSE_Semaphore_Blocking_Count[semaphore]-; 3) 3r?6359. NUSE_SEMAPHORE_SUSPEND)
&& (HINIB (NUSE_Task_Status[index]) ==
semaphore))
{
NUSE_Task_Blocking_Return[index]=
NUSE_SUCCESS;
NUSE_Wake_Task (index);
break;
}
}
}
#endif
}
else
{
return_value = NUSE_UNAVAILABLE;
}
NUSE_CS_Exit ();
return return_value;
3r3602.
3r3612.  
If any tasks are suspended on this semaphore, the first one is resumed. 3r3612.  
3r3612.  
The next article will describe the additional API calls related to semaphores and their data structures. 3r3612.  
3r3612.  
3r31414. About the author: [/b] Colin Walls has been working in the electronics industry for over thirty years, devoting much of his time to embedded software. He is now the firmware engineer for Mentor Embedded (a division of Mentor Graphics). Colin Walls often speaks at conferences and seminars, author of numerous technical articles and two books on embedded software. Lives in the UK. Professional 3r31616. Colin's blog
, e-mail: [email protected] 3r33625.
3r3622. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () ();
3r33625.
+ 0 -

Add comment