1. UCOSIII semaphore
1.1 introduction to semaphore:
The semaphore is like a locking mechanism. The code can continue to execute only after obtaining the corresponding key. Once the key is obtained, it means that the task has the permission to enter the locked part of the code. Once executed to the locked code segment, the task waits until the key corresponding to the locked part of the code is released again.
Semaphores are used to control the protection of shared resources, but now they are basically used for task synchronization
To obtain the resource, the task must perform the "wait" operation. If the effective value of the semaphore corresponding to the resource is greater than 1, the task can obtain the resource and continue to run. If the effective value of the semaphore is 0, the task is added to the task table waiting for the semaphore. If the waiting time exceeds a set value and the semaphore is still not released, the task waiting for the semaphore will enter the ready state. If the waiting time is set to 0, the task will always wait for the semaphore
Semaphores are usually divided into two types: binary semaphores and counting semaphores
- Binary semaphores can only take two values: 0 and 1. The semaphore value of counting semaphore is greater than 1, and the range of counting semaphore is 0S_SEM_STR decision, OS_SEM_CTR can be 8 bits, 16 bits and 32 bits, and the value ranges are 0 ~ 255, 0 ~ 65535 and 0 ~ 4294967295 respectively
- Binary semaphores are used for resources that can only be used by one task at a time, such as I/O devices, printers and meters. Digital semaphores are used for some resources that can be used by several tasks at the same time. For example, if there are 10 cache blocks in a cache pool, at most 10 tasks can be supported to use the memory pool at the same time.
1.2 semaphore API function:
Function name | effect |
---|---|
OSSemCreate() | Establish a semaphore |
OSSemDel() | Delete a semaphore |
OSSemPend() | Wait for a semaphore |
OSSemPendAbrot() | Cancel waiting |
OSSemPost() | Release or send a semaphore |
OSSemSet() | Force the setting of a semaphore value |
OSSemCreate create semaphore:
void OSSemCreate (OS_SEM *p_sem, CPU_CHAR *p_name, OS_SEM_CTR cnt, OS_ERR *p_err)
-
OS_SEM semaphore:
typedef struct os_sem OS_SEM;
-
CPU_CHAR semaphore naming:
typedef char CPU_CHAR; /* 8-bit character */
-
OS_SEM_CTR semaphore initial value:
typedef CPU_INT32U OS_SEM_CTR; /* Semaphore value 16/<32> */
-
OS_ Error message returned by err semaphore:
typedef enum os_err { OS_ERR_NONE = 0u, OS_ERR_A = 10000u, OS_ERR_ACCEPT_ISR = 10001u, OS_ERR_B = 11000u, OS_ERR_C = 12000u, OS_ERR_CREATE_ISR = 12001u, OS_ERR_D = 13000u, OS_ERR_DEL_ISR = 13001u, OS_ERR_E = 14000u, OS_ERR_F = 15000u, OS_ERR_FATAL_RETURN = 15001u, OS_ERR_FLAG_GRP_DEPLETED = 15101u, OS_ERR_FLAG_NOT_RDY = 15102u, OS_ERR_FLAG_PEND_OPT = 15103u, OS_ERR_FLUSH_ISR = 15104u, OS_ERR_G = 16000u, OS_ERR_H = 17000u, OS_ERR_I = 18000u, OS_ERR_ILLEGAL_CREATE_RUN_TIME = 18001u, OS_ERR_INT_Q = 18002u, OS_ERR_INT_Q_FULL = 18003u, OS_ERR_INT_Q_SIZE = 18004u, OS_ERR_INT_Q_STK_INVALID = 18005u, OS_ERR_INT_Q_STK_SIZE_INVALID = 18006u, OS_ERR_J = 19000u, OS_ERR_K = 20000u, OS_ERR_L = 21000u, OS_ERR_LOCK_NESTING_OVF = 21001u, OS_ERR_M = 22000u, OS_ERR_MEM_CREATE_ISR = 22201u, OS_ERR_MEM_FULL = 22202u, OS_ERR_MEM_INVALID_P_ADDR = 22203u, OS_ERR_MEM_INVALID_BLKS = 22204u, OS_ERR_MEM_INVALID_PART = 22205u, OS_ERR_MEM_INVALID_P_BLK = 22206u, OS_ERR_MEM_INVALID_P_MEM = 22207u, OS_ERR_MEM_INVALID_P_DATA = 22208u, OS_ERR_MEM_INVALID_SIZE = 22209u, OS_ERR_MEM_NO_FREE_BLKS = 22210u, OS_ERR_MSG_POOL_EMPTY = 22301u, OS_ERR_MSG_POOL_NULL_PTR = 22302u, OS_ERR_MUTEX_NOT_OWNER = 22401u, OS_ERR_MUTEX_OWNER = 22402u, OS_ERR_MUTEX_NESTING = 22403u, OS_ERR_N = 23000u, OS_ERR_NAME = 23001u, OS_ERR_NO_MORE_ID_AVAIL = 23002u, OS_ERR_O = 24000u, OS_ERR_OBJ_CREATED = 24001u, OS_ERR_OBJ_DEL = 24002u, OS_ERR_OBJ_PTR_NULL = 24003u, OS_ERR_OBJ_TYPE = 24004u, OS_ERR_OPT_INVALID = 24101u, OS_ERR_OS_NOT_RUNNING = 24201u, OS_ERR_OS_RUNNING = 24202u, OS_ERR_P = 25000u, OS_ERR_PEND_ABORT = 25001u, OS_ERR_PEND_ABORT_ISR = 25002u, OS_ERR_PEND_ABORT_NONE = 25003u, OS_ERR_PEND_ABORT_SELF = 25004u, OS_ERR_PEND_DEL = 25005u, OS_ERR_PEND_ISR = 25006u, OS_ERR_PEND_LOCKED = 25007u, OS_ERR_PEND_WOULD_BLOCK = 25008u, OS_ERR_POST_NULL_PTR = 25101u, OS_ERR_POST_ISR = 25102u, OS_ERR_PRIO_EXIST = 25201u, OS_ERR_PRIO = 25202u, OS_ERR_PRIO_INVALID = 25203u, OS_ERR_PTR_INVALID = 25301u, OS_ERR_Q = 26000u, OS_ERR_Q_FULL = 26001u, OS_ERR_Q_EMPTY = 26002u, OS_ERR_Q_MAX = 26003u, OS_ERR_Q_SIZE = 26004u, OS_ERR_R = 27000u, OS_ERR_REG_ID_INVALID = 27001u, OS_ERR_ROUND_ROBIN_1 = 27002u, OS_ERR_ROUND_ROBIN_DISABLED = 27003u, OS_ERR_S = 28000u, OS_ERR_SCHED_INVALID_TIME_SLICE = 28001u, OS_ERR_SCHED_LOCK_ISR = 28002u, OS_ERR_SCHED_LOCKED = 28003u, OS_ERR_SCHED_NOT_LOCKED = 28004u, OS_ERR_SCHED_UNLOCK_ISR = 28005u, OS_ERR_SEM_OVF = 28101u, OS_ERR_SET_ISR = 28102u, OS_ERR_STAT_RESET_ISR = 28201u, OS_ERR_STAT_PRIO_INVALID = 28202u, OS_ERR_STAT_STK_INVALID = 28203u, OS_ERR_STAT_STK_SIZE_INVALID = 28204u, OS_ERR_STATE_INVALID = 28205u, OS_ERR_STATUS_INVALID = 28206u, OS_ERR_STK_INVALID = 28207u, OS_ERR_STK_SIZE_INVALID = 28208u, OS_ERR_STK_LIMIT_INVALID = 28209u, OS_ERR_T = 29000u, OS_ERR_TASK_CHANGE_PRIO_ISR = 29001u, OS_ERR_TASK_CREATE_ISR = 29002u, OS_ERR_TASK_DEL = 29003u, OS_ERR_TASK_DEL_IDLE = 29004u, OS_ERR_TASK_DEL_INVALID = 29005u, OS_ERR_TASK_DEL_ISR = 29006u, OS_ERR_TASK_INVALID = 29007u, OS_ERR_TASK_NO_MORE_TCB = 29008u, OS_ERR_TASK_NOT_DLY = 29009u, OS_ERR_TASK_NOT_EXIST = 29010u, OS_ERR_TASK_NOT_SUSPENDED = 29011u, OS_ERR_TASK_OPT = 29012u, OS_ERR_TASK_RESUME_ISR = 29013u, OS_ERR_TASK_RESUME_PRIO = 29014u, OS_ERR_TASK_RESUME_SELF = 29015u, OS_ERR_TASK_RUNNING = 29016u, OS_ERR_TASK_STK_CHK_ISR = 29017u, OS_ERR_TASK_SUSPENDED = 29018u, OS_ERR_TASK_SUSPEND_IDLE = 29019u, OS_ERR_TASK_SUSPEND_INT_HANDLER = 29020u, OS_ERR_TASK_SUSPEND_ISR = 29021u, OS_ERR_TASK_SUSPEND_PRIO = 29022u, OS_ERR_TASK_WAITING = 29023u, OS_ERR_TCB_INVALID = 29101u, OS_ERR_TLS_ID_INVALID = 29120u, OS_ERR_TLS_ISR = 29121u, OS_ERR_TLS_NO_MORE_AVAIL = 29122u, OS_ERR_TLS_NOT_EN = 29123u, OS_ERR_TLS_DESTRUCT_ASSIGNED = 29124u, OS_ERR_TICK_PRIO_INVALID = 29201u, OS_ERR_TICK_STK_INVALID = 29202u, OS_ERR_TICK_STK_SIZE_INVALID = 29203u, OS_ERR_TICK_WHEEL_SIZE = 29204u, OS_ERR_TIME_DLY_ISR = 29301u, OS_ERR_TIME_DLY_RESUME_ISR = 29302u, OS_ERR_TIME_GET_ISR = 29303u, OS_ERR_TIME_INVALID_HOURS = 29304u, OS_ERR_TIME_INVALID_MINUTES = 29305u, OS_ERR_TIME_INVALID_SECONDS = 29306u, OS_ERR_TIME_INVALID_MILLISECONDS = 29307u, OS_ERR_TIME_NOT_DLY = 29308u, OS_ERR_TIME_SET_ISR = 29309u, OS_ERR_TIME_ZERO_DLY = 29310u, OS_ERR_TIMEOUT = 29401u, OS_ERR_TMR_INACTIVE = 29501u, OS_ERR_TMR_INVALID_DEST = 29502u, OS_ERR_TMR_INVALID_DLY = 29503u, OS_ERR_TMR_INVALID_PERIOD = 29504u, OS_ERR_TMR_INVALID_STATE = 29505u, OS_ERR_TMR_INVALID = 29506u, OS_ERR_TMR_ISR = 29507u, OS_ERR_TMR_NO_CALLBACK = 29508u, OS_ERR_TMR_NON_AVAIL = 29509u, OS_ERR_TMR_PRIO_INVALID = 29510u, OS_ERR_TMR_STK_INVALID = 29511u, OS_ERR_TMR_STK_SIZE_INVALID = 29512u, OS_ERR_TMR_STOPPED = 29513u, OS_ERR_U = 30000u, OS_ERR_V = 31000u, OS_ERR_W = 32000u, OS_ERR_X = 33000u, OS_ERR_Y = 34000u, OS_ERR_YIELD_ISR = 34001u, OS_ERR_Z = 35000u } OS_ERR;
OSSemPend request semaphore:
OS_SEM_CTR OSSemPend (OS_SEM *p_sem, OS_TICK timeout, OS_OPT opt, CPU_TS *p_ts, OS_ERR *p_err)
2. UCOSIII mutex semaphore
2.1. Priority reversal:
Priority inversion is very common in the deprivable inversion kernel. This phenomenon is not allowed in the real-time system, which will destroy the expected sequence of tasks and may lead to serious consequences
Task priority: task H > task m > task L
Timeline from left to right
2.2 mutually exclusive semaphores:
In order to avoid the problem of priority inversion, ucosiiii supports a special binary semaphore: mutually exclusive semaphore, which can be used to solve the problem of priority inversion.
2.2. Mutually exclusive semaphore API function:
Function name | effect |
---|---|
OSMutexCreate() | Create a mutex semaphore |
OSMutexDel() | Delete a mutex semaphore |
OSMutexPend() | Wait for a mutex semaphore |
OSMutexPendAbrot() | Cancel waiting |
OSMutexPost() | Releases or publishes a mutex semaphore |
3. UCOSIII task embedded semaphore
In ucosiiii, each task has its own embedded semaphore. This function can not only simplify the code, but also be more effective than using independent semaphores. Task semaphores are directly embedded in UCOSIII, and task semaphore related codes are in UCOSIII_ In task. C
Function name | effect |
---|---|
OSTaskSemPend() | Wait for a task semaphore |
OSTaskSemPendAbrot() | Cancel waiting task semaphore |
OSTaskSemPost() | Publish task semaphore |
OSTaskSemSet() | Force task semaphore count |