UCOSIII信号量和互斥信号量
Posted 想成为大师啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UCOSIII信号量和互斥信号量相关的知识,希望对你有一定的参考价值。
1、UCOSIII信号量
1.1、信号量简介:
信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。
信号量用来控制对共享资源的保护,但是现在基本用来做任务同步用
要想获取资源的任务必须执行 “等待” 操作,如果该资源对应的信号量有效值大于1,则任务可以获得该资源,任务继续运行。如果该信号量的有效值为0,则任务加入等待信号量的任务表中。如果等待时间超过某一个设定值,该信号量仍然没有被释放掉,则等待信号量的任务就进入就绪态,如果将等待时间设置为0的话任务就将一直等待该信号量
信号量通常分为两种:二进制信号量和计数型信号量
- 二进制信号量只能取0和1两个值,计数型信号量的信号量值大于1,计数型信号量的范围由 0S_SEM_STR决定,OS_SEM_CTR可以为8位,16位和32位,取值范围分别为:
0~255、0~65535和0~4294967295
- 二值信号量用于那些一次只能一个任务使用的资源,比如 I/O 设备,打印机计,数型信号量用于某些资源可以同时被几个任务所使用,比如一个缓存池有10个缓存块,那么同时最多可以支持10个任务来使用内存池。
1.2、信号量API函数:
函数名 | 作用 |
---|---|
OSSemCreate() | 建立一个信号量 |
OSSemDel() | 删除一个信号量 |
OSSemPend() | 等待一个信号量 |
OSSemPendAbrot() | 取消等待 |
OSSemPost() | 释放或者发出一个信号量 |
OSSemSet() | 强制设置一个信号量的值 |
OSSemCreate 创建信号量:
void OSSemCreate (OS_SEM *p_sem,
CPU_CHAR *p_name,
OS_SEM_CTR cnt,
OS_ERR *p_err)
-
OS_SEM 信号量:
typedef struct os_sem OS_SEM;
-
CPU_CHAR 信号量命名:
typedef char CPU_CHAR; /* 8-bit character */
-
OS_SEM_CTR 信号量初始值:
typedef CPU_INT32U OS_SEM_CTR; /* Semaphore value 16/<32> */
-
OS_ERR 信号量返回错误信息:
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 请求信号量:
OS_SEM_CTR OSSemPend (OS_SEM *p_sem,
OS_TICK timeout,
OS_OPT opt,
CPU_TS *p_ts,
OS_ERR *p_err)
2、UCOSIII互斥信号量
2.1、优先级反转:
优先级反转在可剥夺反转内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果
任务优先级:任务H > 任务M > 任务L
时间线从左往右
2.2、互斥信号量:
为了避免优先级反转这个问题,UCOSIII支持一种特殊的二进制信号量:互斥信号量,用它可以解决优先级反转问题。
2.2、互斥信号量API函数:
函数名 | 作用 |
---|---|
OSMutexCreate() | 建立一个互斥信号量 |
OSMutexDel() | 删除一个互斥信号量 |
OSMutexPend() | 等待一个互斥信号量 |
OSMutexPendAbrot() | 取消等待 |
OSMutexPost() | 释放或者发布一个互斥信号量 |
3、UCOSIII任务内嵌信号量
在UCOSIII中每个任务都有自己的内嵌的信号量,这种功能不仅能够简化代码,而且比使用独立的信号量更有效。任务信号量是直接内嵌在UCOSIII中的,任务信号量相关代码在 os_task.c 中
函数名 | 作用 |
---|---|
OSTaskSemPend() | 等待一个任务信号量 |
OSTaskSemPendAbrot() | 取消等待任务信号量 |
OSTaskSemPost() | 发布任务信号量 |
OSTaskSemSet() | 强行设置任务信号量计数 |
以上是关于UCOSIII信号量和互斥信号量的主要内容,如果未能解决你的问题,请参考以下文章