Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use the API function of FreeRTOS semaphore

2025-03-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "how to use the API function of FreeRTOS semaphore". The editor shows you the operation process through the actual case. The operation method is simple, fast and practical. I hope this article "how to use the API function of FreeRTOS semaphore" can help you solve the problem.

Preface

The semaphore of FreeRTOS includes binary semaphore, counting semaphore, mutex semaphore (hereafter referred to as mutex) and recursive mutex semaphore (hereafter referred to as recursive mutex). We can regard mutexes and recursive mutexes as special semaphores.

The semaphore API function is actually a macro that uses the existing queuing mechanism. These macros are defined in the semphr.h file. If you use semaphores or mutexes, you need to include the semphr.h header file.

The creation API functions of binary semaphores, counting semaphores and mutex semaphores are independent, but the acquisition and release API functions are the same; the creation, acquisition and release API functions of recursive mutex semaphores are independent.

1 create binary semaphore 1.1 function description

SemaphoreHandle_t xSemaphoreCreateBinary (void)

This function is used to create a binary semaphore. Binary semaphores are either valid or invalid, which is why they are called binary.

The newly created semaphore is in an invalid state, which means that you need to give the signal before using the API function xSemaphoreTake () to get the signal.

Binary semaphores and mutexes are very similar, but there are subtle differences: mutexes have a priority inheritance mechanism, while binary semaphores do not. This makes binary semaphores more suitable for synchronization (between tasks or between tasks and interrupts) and mutexes for interlocking.

Once the binary semaphore is obtained without recovery, one task or interrupt constantly generates the signal, while the other task constantly takes away the signal to achieve synchronization in this way.

When a low-priority task has a mutex, if another high-priority task also attempts to obtain this semaphore, the priority of the low-priority task will be temporarily raised to the same priority as the high-priority task. This means that the mutex must be released, otherwise the high priority task will not be able to obtain the mutex, and the low priority task with the mutex will never be deprived, which is the priority flipping in the operating system.

Mutexes and binary semaphores are of type SemaphoreHandle_t and can be used in any API function with such parameters.

1.2 return value

NULL: failed to create semaphore because of insufficient FreeRTOS stack. Other values: semaphore created successfully. This return value stores the semaphore handle.

1.3 examples of usage

SemaphoreHandle_t xSemaphore;void vATask (void * pvParameters) {/ * create semaphore * / xSemaphore = xSemaphoreCreateBinary (); if (xSemaphore = = NULL) {/ * semaphore creation failed due to insufficient stack. Here you can handle the failure * /} else {/ * semaphore. The semaphore handle is stored in the variable xSemahore. If you call the API function xSemahoreTake () here to get the semaphore, it must fail, because the semaphore created is initially invalid (empty). * /}} 2 create a count semaphore

2.1 function description

SemaphoreHandle_t xSemaphoreCreateCounting (UBaseType_t uxMaxCount, UBaseType_t uxInitialCount)

Create a count semaphore, which is usually used in the following two situations:

Event counting: in this application, whenever an event occurs, the event handler "generates" a semaphore (the semaphore count is incremented), and each time the task handles the event, a semaphore is taken away (the semaphore count is decremented). Therefore, after the event occurs or the event is processed, the count value will change.

Resource management: in this application, the count value represents the number of effective resources. In order to obtain resources, the task first needs to obtain a semaphore-decreasing semaphore count value. When the count value is 0, there are no resources available. When the task of occupying the resource is completed, it will release the resource and the corresponding semaphore count will be increased by one. A count that reaches the initial value (maximum) indicates that all resources are available.

2.2 Parameter description

UxMaxCount: the maximum count value, when the signal reaches this value, it no longer grows.

UxInitialCount: the initial value when the semaphore was created.

2.3 return value

NULL indicates that semaphore creation failed, otherwise semaphore handle is returned.

2.4 examples of usage

Void vATask (void * pvParameters) {xSemaphoreHandle xSemaphore; / / you must create a semaphore before you can use it / / the maximum value that a semaphore can count is 10, and the initial count value is 0. XSemaphore = xSemaphoreCreateCounting (10,0); if (xSemaphore! = NULL) {/ / semaphore created successfully / / semaphores can now be used. }} 3 create a mutex

3.1 function description

SemaphoreHandle_t xSemaphoreCreateMutex (void)

Create a mutex.

Mutexes can be accessed using the API functions xSemaphoreTake () and xSemaphoreGive (), but never with xSemaphoreTakeRecursive () and xSemaphoreGiveRecursive ().

Binary semaphores and mutexes are very similar, but there are subtle differences: mutexes have a priority inheritance mechanism, while binary semaphores do not. This makes binary semaphores more suitable for synchronization (between tasks or between tasks and interrupts) and mutexes for interlocking.

Once the binary semaphore is obtained without recovery, one task or interrupt constantly generates the signal, while the other task constantly takes away the signal to achieve synchronization in this way.

When a low-priority task has a mutex, if another high-priority task also attempts to obtain this semaphore, the priority of the low-priority task will be temporarily raised to the same priority as the high-priority task. This means that the mutex must be released, otherwise the high priority task will not be able to obtain the mutex, and the low priority task with the mutex will never be deprived, which is the priority flipping in the operating system.

Mutexes and binary semaphores are of type SemaphoreHandle_t and can be used in any API function with such parameters.

3.2 return value

NULL indicates that semaphore creation failed, otherwise semaphore handle is returned.

3.3 examples of usage

XSemaphoreHandle xSemaphore;voidvATask (void * pvParameters) {/ / mutex is not available before it is created xSemaphore = xSemaphoreCreateMutex (); if (xSemaphore! = NULL) {/ / created successfully / / here you can use this mutex}} 4 to create a recursive mutex

4.1 function description

SemaphoreHandle_t xSemaphoreCreateRecursiveMutex (void)

Used to create recursive mutexes. The mutexes created can be used by the API functions xSemaphoreTakeRecursive () and xSemaphoreGiveRecursive (), but not by the API functions xSemaphoreTake () and xSemaphoreGive ().

The mutex of the recursive type can be obtained repeatedly by the owner. Tasks with mutexes must call the API function xSemaphoreGiveRecursive () to release all the recursive mutexes before the semaphore is really released. For example, if a task successfully obtains the same mutex five times, the task will have to release the mutex five times before other tasks can get it.

Recursive mutexes have a priority inheritance mechanism, so the task must do a release operation after getting a signal.

Mutex type signals cannot be used in interrupt service routines.

4.2 return value

NULL indicates that mutex creation failed, otherwise a mutex handle is returned.

4.3 examples of usage

XSemaphoreHandle xMutex;void vATask (void * pvParameters) {/ / mutex cannot be used before it is created xMutex = xSemaphoreCreateRecursiveMutex (); if (xMutex! = NULL) {/ / created successfully / / here create mutex}} 5 delete semaphore

5.1 function description

Void vSemaphoreDelete (SemaphoreHandle_t xSemaphore)

Delete semaphore. If a task is blocked on this semaphore, do not delete the semaphore.

5.2 Parameter description

XSemaphore: semaphore handle

6 get semaphore

6.1 function description

XSemaphoreTake (SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait)

Get the semaphore. Semaphores must be pre-created through the API functions xSemaphoreCreateBinary (), xSemaphoreCreateCounting (), and xSemaphoreCreateMutex (). Note that recursive mutex type semaphores cannot be used, and do not need to be used in interrupt service programs.

6.2 Parameter description

XSemaphore: semaphore handle

XTickToWait: the maximum waiting time for a task when the semaphore is invalid, in units of the number of system beat cycles. Use the macro _ PERIOD_MS to help convert the number of system beats into actual time (in milliseconds). If set to 0, the wait time is not set. If INCLUDE_vTaskSuspend is set to 1 and the parameter xTickToWait is portMAX_DELAY, you can wait indefinitely.

6.3 return value

PdTRUE is returned if the semaphore is successfully obtained, otherwise pdFALSE is returned.

6.4 examples of usage

SemaphoreHandle_t xSemaphore = NULL;/* this task creates semaphores * / void vATask (void * pvParameters) {/ * create mutually exclusive semaphores to protect shared resources. * / xSemaphore = xSemaphoreCreateMutex ();} / * this task uses semaphores * / void vAnotherTask (void * pvParameters) {/ *. Do other things. * / if (xSemaphore! = NULL) {/ * if the semaphore is invalid, wait up to 10 system beat cycles. * / if (xSemaphoreTake (xSemaphore, (TickType_t) 10) = = pdTRUE) {/ * here we get the semaphore, and now we can access the shared resource * / / *. * / * after you finish accessing the shared resource, you must release the semaphore * / xSemaphoreGive (xSemaphore). } else {/ * did not get the semaphore, so the exception is handled here. * /}} 7 get semaphore (with interrupt protection)

7.1 function description

XSemaphoreTakeFromISR (SemaphoreHandle_t xSemaphore

SignedBaseType_t * pxHigherPriorityTaskWoken)

Another version of the API function xSemaphoreTake (), used to interrupt the service program.

7.2 Parameter description

XSemaphore: semaphore handle

PxHigherPriorityTaskWoken: if * pxHigherPriorityTaskWoken is pdTRUE, you need to manually switch the context before the interrupt exits. Starting with FreeRTOS V7.3.0, this parameter is optional and can be set to NULL.

7.3 return value

PdTRUE is returned if the semaphore is successfully obtained, otherwise pdFALSE is returned.

8 get recursive mutexes

8.1 function description

XSemaphoreTakeRecursive (SemaphoreHandle_t xMutex, TickType_t xTicksToWait)

Gets the recursive mutex semaphore. Mutexes must be of the type created by the API function xSemaphoreCreateRecursiveMutex ().

The macro configUSE _ RECURSIVE_MUTEXES in the file FreeRTOSConfig.h must be set to 1 for this function to be valid.

A task that has already obtained a recursive mutex can repeatedly get the recursive mutex.

If you use the xSemaphoreTakeRecursive () function to successfully get a recursive mutex several times, you need to return it several times using the xSemaphoreGiveRecursive () function. Until then, the recursive mutex is in an invalid state. For example, if a task successfully gets a recursive mutex five times, the mutex is not valid for other tasks until it returns the recursive mutex five times.

8.2 Parameter description

XMutex: mutex handle, which must be returned using the API function xSemaphoreCreateRecursiveMutex ().

XTickToWait: when the mutex is invalid, the maximum waiting time of the task is the number of beat cycles of the system. Use the macro _ PERIOD_MS to help convert the number of system beats into actual time (in milliseconds). If set to 0, the wait time is not set. If the task already has a semaphore, xSemaphoreTakeRecursive () returns immediately, regardless of the value of xTickToWait.

8.3 return value

PdTURE is returned if the recursive mutex is successfully obtained, otherwise pdFALSE is returned.

8.4 examples of usage

SemaphoreHandle_t xMutex = NULL;// this task creates a mutex void vATask (void * pvParameters) {/ / this mutex is used to protect shared resources xMutex = xSemaphoreCreateRecursiveMutex ();} / / this task uses a mutex void vAnotherTask (void * pvParameters) {/ /. Do other things. If (xMutex! = NULL) {/ / if the mutex is invalid, wait up to 10 system clock beats. If (xSemaphoreTakeRecursive (xMutex, (TickType_t) 10) = = pdTRUE) {/ / here we have successfully obtained mutexes and can access shared resources / /. / / for some reason, some code needs to call the API function / / xSemaphoreTakeRecursive () multiple times in a task. Of course, unlike the continuous / / call in this example, the actual code will have a more complex structure xSemaphoreTakeRecursive (xMutex, (TickType_t) 10); xSemaphoreTakeRecursive (xMutex, (TickType_t) 10); / / We get a mutex three times, so we have to release the mutex three times before it becomes effective. Once again, the actual code may be more complex. XSemaphoreGiveRecursive (xMutex); / / here, this shared resource can be used by other tasks. } else {/ / handle exception} 9 release semaphore

9.1 function description

XSemaphoreGive (SemaphoreHandle_t xSemaphore)

Used to release a semaphore. The semaphore must be created by the API function xSemaphoreCreateBinary (), xSemaphoreCreateCounting (), or xSemaphoreCreateMutex (). You must use the API function xSemaphoreTake () to get this semaphore.

This function must never be used in interrupt service routines, and you can use the interrupt-protected version of the API function xSemaphoreGiveFromISR () to achieve the same function.

This function cannot be used for recursive mutexes created using the API function xSemaphoreCreateRecursiveMutex ().

9.2 Parameter description

XSemaphore: semaphore handle.

9.3 return value

The semaphore is released successfully and returns pdTRUE, otherwise it returns pdFALSE.

9.4 examples of usage

SemaphoreHandle_t xSemaphore = NULL;voidvATask (void * pvParameters) {/ / create a mutex to protect the shared resource xSemaphore = xSemaphoreCreateMutex () If (xSemaphore! = NULL) {if (xSemaphoreGive (xSemaphore)! = pdTRUE) {/ / We hope this function call fails, because the first step is to get the mutex} / / get the semaphore Do not wait for if (xSemaphoreTake (xSemaphore, (TickType_t) 0)) {/ / now we have mutexes and can safely access the shared resource if (xSemaphoreGive (xSemaphore)! = pdTRUE) {/ / We do not want this function call to fail Because we have to / / to release the acquired mutex}} 10 release semaphore (with interrupt protection)

10.1 function description

XSemaphoreGiveFromISR (SemaphoreHandle_t xSemaphore

Signed BaseType_t * pxHigherPriorityTaskWoken)

Release the semaphore. Is another version of the API function xSemaphoreGive (), which interrupts the service program. The semaphore must be created through the API function xSemaphoreCreateBinary () or xSemaphoreCreateCounting (). There is no mutex here because mutexes cannot be used in interrupt service programs.

10.2 Parameter description

XSemaphore: semaphore handle

PxHigherPriorityTaskWoken: if * pxHigherPriorityTaskWoken is pdTRUE, you need to perform a context switch artificially before the interrupt exits. Starting with FreeRTOS V7.3.0, this parameter is optional and can be set to NULL.

10.3 return value

The semaphore is released successfully and returns pdTURE, otherwise it returns errQUEUE_FULL.

10.4 examples of usage

# define LONG_TIME 0xffff#define TICKS_TO_WAIT 10SemaphoreHandle_t xSemaphore = NULL;/* Repetitive task. * / void vATask (void * pvParameters) {/ * We use semaphore synchronization, so first create a binary semaphore. You must ensure that the interrupt does not access the binary semaphore before it is created. * / xSemaphore = xSemaphoreCreateBinary (); for (;;) {/ * We want the task to run every 10 timer interruptions. * / if (xSemaphoreTake (xSemaphore, LONG_TIME) = = pdTRUE) {/ * the semaphore has been successfully obtained here * /... / * We have successfully executed it once. Because this is an endless loop, the task will still block the waiting semaphore. The semaphore is released by ISR. * /}} / * timer ISR * / void vTimerISR (void * pvParameters) {static unsigned char ucLocalTickCount = 0; static signed BaseType_txHigherPriorityTaskWoken; / * timer interrupt occurs * /. Do I need to run vATask () to execute other code? * / xHigherPriorityTaskWoken = pdFALSE; ucLocalTickCount++; if (ucLocalTickCount > = TICKS_TO_WAIT) {/ * release semaphore to unblock vATask task * / xSemaphoreGiveFromISR (xSemaphore, & xHigherPriorityTaskWoken); / * reset counter * / ucLocalTickCount = 0 } / * if the xHigherPriorityTaskWoken expression is true, you need to perform a context switch * / portYIELD_FROM_ISR (xHigherPriorityTaskWoken);} 11 release recursive mutexes

11.1 function description

XSemaphoreGiveRecursive (SemaphoreHandle_t xMutex)

Releases a recursive mutex. Mutexes must be created using the API function xSemaphoreCreateRecursiveMutex (). The macro configUSE_RECURSIVE_MUTEXES in the file FreeRTOSConfig.h must be set to 1 this function to be valid.

11.2 Parameter description

XMutex: mutex handle. Must be the value returned by the function xSemaphoreCreateRecursiveMutex ().

11.3 return value

If the recursive mutex is released successfully, pdTRUE is returned.

11.4 examples of usage

See "8 get recursive mutexes".

12 get the mutex to hold the handle to the task

12.1 function description

TaskHandle_t xSemaphoreGetMutexHolder (SemaphoreHandle_t xMutex)

Returns the mutex that holds the handle to the task, if any, specified by the parameter xMutex.

If the task calling this function holds a mutex, you can reliably return the task handle, but if another task holds a mutex, it is not always reliable.

The macro configUSE_MUTEXES in the file FreeRTOSConfig.h must be set to 1 this function to be valid.

12.2 Parameter description

XMutex: mutex handle

12.3 return value

Returns the mutex that holds the handle to the task. Returns NULL if the parameter xMutex is not a mutex, or if the mutex is valid but is not held by any task.

This is the end of the introduction about "how to use the API function of FreeRTOS semaphore". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report