1. Binary semaphore and counting semaphore
binary semaphore |
|
concept |
|
Application scenarios |
|
block |
|
counting semaphore |
|
concept |
|
Application scenarios |
|
block |
|
2. Related API functions
2.1, Create
|
|
|
|
Parameters |
Description |
void |
null |
Return value |
Description |
NULL |
Failed to create binary semaphore |
other values |
Create binary semaphore successfully |
|
|
|
|
Parameters |
Description |
uxMaxCount |
The maximum value of the counting signal. When the semaphore value is equal to this value, releasing the semaphore will fail. |
uxInitialCount |
Counting semaphore initial value |
Return value |
Description |
NULL |
Counting semaphore creation failed |
other values |
The counting semaphore is created successfully and the counting semaphore handle is returned. |
2.2, Release
|
|
|
|
Parameters |
Description |
xSemaphore |
The semaphore is to be released. This parameter is a variable of type SemaphoreHandle_t and must be created before use. |
Return value |
Description |
pdPASS |
Semaphore released successfully |
pdFAIL |
The semaphore release fails. If the semaphore is not acquired immediately, it will fail when releasing the semaphore again. |
|
|
|
|
Parameters |
Description |
xSemaphore |
The semaphore is to be released. This parameter is a variable of type SemaphoreHandle_t and must be created before use. |
pxHighPriorityWoken |
If there are multiple tasks waiting to obtain the semaphore and enter the blocking state, calling this function can unblock the tasks. If there is a task in the queue with a higher priority than the unblocked task, or the two have the same priority, then the value of pxHighPriorityWoken will be set to pdTRUE. If xpHighPriorityWoken is pdTRUE, a task switch must be performed before exiting the interrupt service function |
Return value |
Description |
pdTRUE |
Semaphore released successfully |
pdFAIL |
The semaphore release failed because the semaphore has been released but has not been acquired. |
2.3, Obtain
|
|
|
|
Parameters |
Description |
xSemaphore |
The semaphore to be obtained |
xBlockTime |
blocking time |
Return value |
Description |
pdTRUE |
Obtaining semaphore successfully |
pdFAIL |
Retrieval timed out or failed |
|
|
|
|
Parameters |
Description |
xSemaphore |
The semaphore to be obtained |
pxHighPriorityWoken |
Mark whether task switching is required before exiting the interrupt service function. The value is set by the function, the user only provides the stored variable. If the value of pxHighPriorityWoken is pdTRUE, a task switch must be performed before exiting the interrupt function. |
Return value |
Description |
pdPASS |
Obtaining semaphore successfully |
pdFALSE |
Failed to obtain semaphore |
3. Experiment
3.1. Experimental design
-
Create a start task. In the start task, create the binary semaphore, task 1 and task 2, and then delete the start task;
-
After task 1 runs 10 times, a semaphore is released;
-
Task 2 keeps getting the semaphore, and after getting it, prints the information;
3.2. Experimental procedures
k_task_handle_t task1_handle; //task 1 handle #define TSK1_PRIO 3 //task 1 priority #define TASK1_STK_SIZE (1*1024) //The stack size allocated by task 1 k_task_handle_t task2_handle; //task 2 handle #define TSK2_PRIO 2 //task 2 priority #define TASK2_STK_SIZE (1*1024) //The stack size allocated by task 2 k_task_handle_t start_task_handle; //start task handle #define START_TSK_PRIO 1 //start task priority #define START_TSK_STK_SIZE (1*1024) //Start task allocated stack size #define TEST_TIME_QUANTA 100 k_sem_handle_t g_usSem; //Semaphore void task1(void) { uint8_t count = 0; while(1) { count + + ; my_printf("task 1 run %d times!!!\r\\ ", count); if(count == 10) { if(0 != csi_kernel_sem_post(g_usSem)) { my_printf("---task 1 give sem fail!!!\r\\ "); } else { my_printf("---task 1 give sem sucess!!!\r\\ "); } count = 0; } csi_kernel_delay_ms(1000); } } void task2(void) { while(1) { if(0 != csi_kernel_sem_wait(g_usSem, -1)) { my_printf("task 2 take sem fail!!!\r\\ "); } else { my_printf("task 2 take sem sucess,task 2 is working now!!!\r\\ "); } } } void start_task(void) { //Enter the critical section taskENTER_CRITICAL(); //Create a binary semaphore g_usSem = csi_kernel_sem_new(1, 0); if (g_usSem == NULL) { printf("fail to create semaphore.\\ "); } //Create task 1 csi_kernel_task_new((k_task_entry_t)task1, "task1", NULL, TSK1_PRIO, TEST_TIME_QUANTA, NULL, TASK1_STK_SIZE, &task1_handle); if (task1_handle == NULL) { csi_kernel_sched_resume(0); my_printf("Fail to create task 1!\r\\ "); } //Create task 2 csi_kernel_task_new((k_task_entry_t)task2, "task2", NULL, TSK2_PRIO, TEST_TIME_QUANTA, NULL, TASK2_STK_SIZE, &task2_handle); if (task2_handle == NULL) { csi_kernel_sched_resume(0); my_printf("Fail to create task 2!\r\\ "); } //Delete the start task if(0 != csi_kernel_task_del(csi_kernel_task_get_cur())) { my_printf("Fail to delete start_task!\r\\ "); } //Exit critical section taskEXIT_CRITICAL(); } void freertos_demo(void) { my_printf("\r\\ -->this is freertos task test demo!!!\r\\ "); //system initialization csi_kernel_init(); //Create a start task csi_kernel_task_new((k_task_entry_t)start_task, "start_task", 0, START_TSK_PRIO, 0, 0, START_TSK_STK_SIZE, &start_task_handle); //Task scheduling starts csi_kernel_start(); }
3.3. Experimental phenomena
-
After the start task is created, task 1 and task 2 will be deleted immediately after it is created.
-
In the initial stage, task 1 is running, and task 2 is in a blocked state because the semaphore obtained at this time has not been released yet.
-
After task 1 runs 10 times, a semaphore is released. After task 2 obtained the semaphore, it executed the printing action
-
At this time, the operation of task 2 is controlled by the semaphore. It is blocked before acquiring the semaphore, fully releasing the CPU usage rights.