UCOSII源码-信号量理解
来源:互联网 发布:淘宝甩货文案 编辑:程序博客网 时间:2024/05/22 12:13
UCOSII-Version : V2.92.07
信号量作用
用于从一个任务向另一个任务传递一个开关量的BOOL信号。
事件控制块
一个任务或者中断服务子程序可以通过事件控制块 ECB(Event Control Blocks)来向另外的任务发信号。这里,所有的信号都被看成是事件(Event)。把用于通讯的数据结构叫做事件控制块。
µC/OS-II通过uCOS_II.H 中定义的 OS_EVENT数据结构来维护一个事件控制块的所有信息,也就是这里讲到的事件控制块 ECB。该结构中除了包含了事件本身的定义,如用于信号量的计数器,用于指向邮箱的指针,以及指向消息队列的指针数组等,还定义了等待该事件的所有任务的列表。
typedef struct{ void *OSEventPtr; /* 指向消息或者消息队列的指针 */ INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 等待任务列表 */ INT16U OSEventCnt; /* 计数器(当事件是信号量时) */ INT8U OSEventType; /* 时间类型 */ INT8U OSEventGrp; /* 等待任务所在的组 */} OS_EVENT;
0S_EVENT *OSSemCreate (INT16U cnt)注解
OS_EVENT *OSSemCreate (INT16U cnt){ OS_EVENT *pevent;/*ucosii采用方法3来开关中断,os_cpu_sr是用来存cpu状态寄存器*/#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u;#endif/*未定义宏*/#ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == OS_TRUE) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((OS_EVENT *)0); }#endif /*如果中断子程序调用,一般不会,防御性编程*/ if (OSIntNesting > 0u) { /* See if called from ISR ... */ return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ } OS_ENTER_CRITICAL(); /*从空闲任务控制块链表中得到一个事件控制块*/ pevent = OSEventFreeList; /* Get next free event control block */ /*空闲事件控制块链表指针非空闲事件快,即指向下一个空闲事件控制块*/ if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; } OS_EXIT_CRITICAL(); /*如果该控制块可用*/ if (pevent != (OS_EVENT *)0) { /* Get an event control block */ /*该任务控制块的事件类型设置成信号量,防止其他类型任务控制块操作,如邮箱*/ pevent->OSEventType = OS_EVENT_TYPE_SEM; /*信号量值初始化*/ pevent->OSEventCnt = cnt; /* Set semaphore value */ /*不链接空闲任务控制块*/ pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */#if OS_EVENT_NAME_EN > 0u pevent->OSEventName = (INT8U *)(void *)"?";#endif /*等待任务列表进行初始化*/ OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */ } return (pevent);}
INT8U OSSemPost (OS_EVENT *pevent)注解
INT8U OSSemPost (OS_EVENT *pevent){/*ucosii采用方法3来开关中断,os_cpu_sr是用来存cpu状态寄存器*/#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 (OS_ERR_PEVENT_NULL); }#endif /*检查参数指针pevent指向的任务控制块是否是OSSemCreate()创建*/ if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ return (OS_ERR_EVENT_TYPE); } OS_ENTER_CRITICAL(); /*检查是否有任务在等待该信号量,非0值即有等待该信号量*/ if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */ /* Ready HPT waiting on event */ /*任务进入就绪状态*/ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); OS_EXIT_CRITICAL(); /*任务调度,如果就绪任务满足最高优先级,即任务切换*/ OS_Sched(); /* Find HPT ready to run */ return (OS_ERR_NONE); } /*无等待该信号量,信号量计数值加1*/ if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */ pevent->OSEventCnt++; /* Increment semaphore count to register event */ OS_EXIT_CRITICAL(); return (OS_ERR_NONE); } OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */ return (OS_ERR_SEM_OVF);}
void OSSemPend(OS_EVENT *pevent,INT32U timeout,INT8U *perr)注解
void OSSemPend (OS_EVENT *pevent,INT32U timeout,INT8U *perr)//timeout为0的时候表示无限等待{/*ucosii采用方法3来开关中断,os_cpu_sr是用来存cpu状态寄存器*/#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u;#endif/*未定义宏*/#ifdef OS_SAFETY_CRITICAL if (perr == (INT8U *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; }#endif/*未定义宏*/#if OS_ARG_CHK_EN > 0u if (pevent == (OS_EVENT *)0) { /* Validate "pevent" */ *perr = OS_ERR_PEVENT_NULL; return; }#endif /*检查参数指针pevent指向的任务控制块是否是OSSemCreate()创建*/ if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return; } /*如果中断子程序调用,即不能请求*/ if (OSIntNesting > 0u) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can"t PEND from an ISR */ return; } /*如果调度器被锁,即不能请求*/ if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return; } OS_ENTER_CRITICAL(); /*当前信号量大于0,将其计数值减1*/ if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */ pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; return; } /* Otherwise, must wait until event occurs */ OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ OS_EXIT_CRITICAL(); OS_Sched(); /* Find next highest priority task ready */ OS_ENTER_CRITICAL(); switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ case OS_STAT_PEND_OK: *perr = OS_ERR_NONE; break; case OS_STAT_PEND_ABORT: *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ break; case OS_STAT_PEND_TO: default: OS_EventTaskRemove(OSTCBCur, pevent); *perr = OS_ERR_TIMEOUT; /* Indicate that we didn"t get event within TO */ break; } OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */#if (OS_EVENT_MULTI_EN > 0u) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;#endif OS_EXIT_CRITICAL();}
Version2.92.07的OSSemPend()中挂起任务及任务切换的处理和ucos-ii中文书(邵贝贝)PDF版的处理差异目前借助英文注释理解,其理解还停留在表层,待深入理解后再跟进。
信号量像一把钥匙,任务要运行下去,需先拿到这把钥匙。
消息邮箱是一个指针型变量。可以向一个任务或一个中断服务子程序发送一则消息(一个指针),同样,一个或多个任务通过内核服务,可以接收这则消息。消息邮箱也可以当作2值的信号量来用。
消息队列实际上是邮箱阵列。
阅读全文
0 0
- UCOSII源码-信号量理解
- UCOSII信号量
- uCOSii-信号量
- UCOSii-信号量
- 信号量流程图 UCOSII
- ucosii---------信号量&邮箱
- UCOSII 信号量的使用
- ucosII 关于事件控制块,信号量,邮箱,消息队列,自己的理解。
- 浅析ucosII互斥信号量
- UcosII 的信号量和邮箱
- UCOSII 信号量和信号量集实例
- ucosii源码分析
- UCOSII信号量的三个主要的函数
- ucosII 信号量的原理及应用
- STM32上使用UCOSII--信号量和邮箱
- 信号量理解
- UcosII 就绪表的理解
- STM32上使用UCOSII--消息队列和信号量集
- 前端项目知识点整理-滚动加载更多
- find_first_of()和 find_last_of()
- scala编程02--变量
- Wannafly挑战赛3 C.位数差(树状数组)
- java.io 包
- UCOSII源码-信号量理解
- 接口 Closeable
- 接口 DataInput
- 接口 DataOutput
- Java的系统Property
- List转数组toArray方法
- Util包中Arrays
- java生成UUID通用唯一识别码
- python常用字符串函数