可以把信号量当成一个全局变量来看
一:信号创建
OS_EVENT *OSSemCreate(INT16U value); //信号创建
创建了一个信号量 系统会分配一个时间控制块给用户
就是这个信号量控制块
OS_EVENT
typedef struct os_event {
INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_xxxx) */
void *OSEventPtr; /* Pointer to message or queue structure */
INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */
OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
#if OS_EVENT_NAME_EN > 0u
INT8U *OSEventName; //允许给控制块命名 新加的特性
#endif
} OS_EVENT;
这个结构体里面有 事件类型 事件控制块指针 事件/消息计数器 后面两个暂时不了解
Value
value就是信号量初始值 每接收一次信号量 Value就会减1
二 : 信号接收
信号的接收有两个函数
分别是:
INT16U OSSemAccept(OS_EVENT *pevent);
void OSSemPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr);
同样的 任意一个接收函数 每接收到一个信号量 Value都会自减1 但是返回的信号量的值是减1之前的值
第一个函数使用比较简单 参数是一个事件控制块的指针 返回值是一个 INT16U 类型的变量 也就是Value没有减1前的值
如果信号量已经变为零 那每次返回的都是零 不会再做减法运算
这个函数的性质有点像
if判断语句 如果信号量获取不成功就会直接去执行下面的语句
INT16U OSSemAccept (OS_EVENT *pevent)
{
INT16U cnt;
#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 (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (0u);
}
OS_ENTER_CRITICAL();
cnt = pevent->OSEventCnt;
if (cnt > 0u) { /* See if resource is available */
pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
}
OS_EXIT_CRITICAL();
return (cnt); /* Return semaphore count */
}
关于使用
pevent->OSEventCnt 和
使用 cnt 的区别
如果使用的是第一个 那么在信号接收函数之后使用 得到的是已经执行减法操作的数
如果使用的是第二个 那么在信号接收函数之后使用 得到的是没有执行减法操作的数
第二个函数 传入事件控制块的指针
timeout:
等待的时间
参数0是无限等待
单位是毫秒
perr: 指向错误代码变量的指针
OS_ERR_NONE 信号量不为 0。
OS_ERR_TIMEOUT 信号量未在指定的超时周期内置起。
OS_ERR_PEND_ABORT
等待中止。 是由于另一个任务或 ISR 通过调用 OSSemPendAbort ()。
OS_ERR_EVENT_TYPE
pevent 不是指向一个信号量。
OS_ERR_PEND_LOCKED
在调用本函数时,调度器被锁定。
OS_ERR_PEND_ISR
尝试从一个 ISR 调用 OSSemPend (), 不允
n许。
OS_ERR_PEVENT_NULL
pevent 传入的是一个空指针。
这个函数的性质有点类似
while()语句 在设定的等待时间范围内
如果等不到信号量 就会一直停在这里 后面的语句也不能执行 这个函数不可以用在中断函数里 如果使用在中断函数里 系统会返回一个错误代码
最好不要把等待时间设置为0 不然信号量减到零的时候 就会一直卡在那里
三:信号发送
INT8U OSSemPost(OS_EVENT *pevent);
返回值是错误类型的枚举
函数参数是事件指针 就是哪个事件的指针
执行一次信号量就加1