Follow+Star PublicAccount, don’t miss out on exciting content
Author | strongerHuang
WeChat Official Account | strongerHuang
A semaphore essentially conveys an “event”. For example: Task A completes sending data, and notifies Task B through the semaphore.
OSSemPost(EventSem_SendOK);
We mainly want to convey“the completion of sending data“ as this “event“.
The principle of queues is somewhat similar to that of semaphores, but here it is a “variable”. For example: after a serial port receives a complete frame of data, it sends it to Task B through the queue.
OSQPost(UARTRcvQueue, RcvBuf);
Compared to semaphores, queues can convey a larger amount of data, as the effective data conveyed by queues is generally an “array“.
There are also mailboxes, which are similar to queues and can be understood as “two-dimensional arrays”.
By this point, you will find that whether it is a semaphore or a queue, the underlying essence is also passing “variables” and “arrays”.
Now the question arises: Why doesn’t RTOS use global variables for inter-task communication?
This question is quite common, and I have seen discussions about it in my technical group, so I will simply share my views.
What are the issues with global variables?

Principles of Semaphore and Queue Communication
INT8U OSSemPost (OS_EVENT *pevent){#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u;#endif
#if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ return (OS_ERR_PEVENT_NULL); }#endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ return (OS_ERR_EVENT_TYPE); } OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */ /* Ready HPT waiting on event */ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); OS_EXIT_CRITICAL(); OS_Sched(); /* Find HPT ready to run */ return (OS_ERR_NONE); } if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */ pevent->OSEventCnt++; /* Increment semaphore count to register event */ OS_EXIT_CRITICAL(); return (OS_ERR_NONE); } OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */ return (OS_ERR_SEM_OVF);}
Although we only need to convey effective information with one variable, it manages the “critical section” and predicts some erroneous situations, etc.
In the end, RTOS source code can also be considered an excellent project, especially those RTOS that are currently widely used and have a large installed base, such asµC/OS, FreeRTOS, RT-Thread, ThreadX etc.
Lastly, if you have time, I encourage you to read the RTOS source code, as the RTOS kernel I recommend is µC/OS. Reading the source code will help you grasp some software architecture knowledge and understand common issues in the development process.
———— END ————

●Column “Embedded Tools”
●Column “Embedded Development”
●Column “Keil Tutorials”
●Selected Tutorials from Embedded Column
Click “Read Original” for more shares.