快速回顾
本文进一步解析事件模型中,信号量类型的函数源码。
先回顾一下上一节的通用事件控制块类型OS_EVENT:
//ucos_ii.h
typedef struct os_event {
INT8U OSEventType; /* 事件类型,有六种(其中一种是UNUSED) */
void *OSEventPtr; /* OSEventPtr是一个多用途的指针,当作为链表时,可以指向下一个控制块;当作为具体的事件控制块时,指向具体的事件结构,如OS_Q。信号量不使用该指针 */
INT16U OSEventCnt; /* 信号量计数器,其它事件类型不使用该成员 */
OS_PRIO OSEventGrp; /* 等待信号的任务优先级组,和OSEventTbl共同组成”事件等待表“ */
OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待信号的组内优先级 */
#if OS_EVENT_NAME_EN > 0u
INT8U *OSEventName; //事件名称
#endif
} OS_EVENT;
信号量的创建
信号量的创建函数为OSSemCreate(cnt),传入的cnt会作为初始值填入OSEventCnt成员,由于信号量没有自己的专属结构,因此OSEventPtr指向空。
//os_sem.c
OS_EVENT *OSSemCreate (INT16U cnt)
{
OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u /* 初始化临界区变量 */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508 //IEC标准,可以忽略
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
if (OSIntNesting > 0u) { /* 不能在中断中创建信号量 */
return ((OS_EVENT *)0);
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* 从空白事件控制块链表中取一个 */
if (OSEventFreeList != (OS_EVENT *)0) { /* 如果空白事件控制块链表还有剩余,则将链表头指向下一个,以便下一次获取 */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { /* 只有非空的事件控制块才能填装 */
pevent->OSEventType = OS_EVENT_TYPE_SEM;
pevent->OSEventCnt = cnt; /* 填装传入的信号量初始值 */
pevent->OSEventPtr = (void *)0; /* 内部指针指向空,断开和原链表的联系,信号量也没有自己的事件结构需要链接 */
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
OS_EventWaitListInit(pevent); /* 初始化等待任务表,就是把OSEventGrp和OSEventTbl清零 */
}
return (pevent);
}
信号量的操作
信号量的操作有很多种,最常用的就是等待(Pend)和释放(Post)了,接下来依次探究各个信号量操作函数源码。
OSSemPend(OS_EVENT *pevent, INT32U timeout, INT8U *perr)
先描述该函数的作用:
①任务使用该语句时,表明需要等待信号量pevent,当信号量计数器大于0时,直接减1并返回继续执行任务;当计数器等于0时,则要等待其它任务释放信号量。
②如果给定了timeout不为0,则若timeout减至0时都没有取得信号量,直接返回执行;若传入的timeout为0,则一直等待直到获得信号量。
//os_sem.c
void OSSemPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
#if OS_CRITICAL_METHOD == 3u /* 初始化临界区变量 */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL //IEC标准,可以忽略
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) {

最低0.47元/天 解锁文章
1456

被折叠的 条评论
为什么被折叠?



