UCOSIII semaphores and mutually exclusive semaphores

Posted by titangf on Sat, 20 Nov 2021 04:46:10 +0100

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 nameeffect
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 nameeffect
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 nameeffect
OSTaskSemPend()Wait for a task semaphore
OSTaskSemPendAbrot()Cancel waiting task semaphore
OSTaskSemPost()Publish task semaphore
OSTaskSemSet()Force task semaphore count

Topics: Single-Chip Microcomputer stm32