uc/os-ii信号量
来源:互联网 发布:个人信息管理系统源码 编辑:程序博客网 时间:2024/05/08 15:40
信号量有两种类型:一种是只有0和1两种值的信号量,称为二值信号量;另一种是可以有多种值的信号量,称为计数式信号量。计数式信号量的值的大小取决于信号量的数据类型,如若是8位整型变量,则其值可以是0~255;若是16位整型变量,则其值可以是0~65 535。
µC/OS-Ⅱ的信号量由两个部分组成:一个是信号量的计数值,范围是0~65 535;另一个是由等待该信号量的任务组成的等待任务列表。
信号量可以使用在如下场合:
- 允许一个任务与其它任务或中断同步;
- 取得共享资源的使用权;
- 标志事件的发生。
对µC/OS-Ⅱ信号量初始值的赋值方法如下:
- 信号量的初始值为0~65 535;
- 如果表示一个或者多个事件的发生,那么初始值应设为0;
- 如果是用于对共享资源的访问,那么该初始值应设为1。例如,把它当作二值信号量使用;
- 如果是用来表示允许任务访问n个相同的资源,那么该初始值应该是n,并把该信号量作为可计数的信号量使用。
µC/OS-Ⅱ提供了6种对信号量进行管理的函数,所属文件是OS_SEM.C。
OSSemDel()
函数用于删除一个信号量,调用者只能是任务在使用OSSemDel()
函数时应注意如下事项:- 由于其它函数可能还会用到这个信号量,因此在删除信号量之前,必须首先删除等待该信号量的所有任务。
- 当挂起的任务进入就绪状态时,中断是关闭的,这就是说中断延迟与等待信号量的任务的数量密切相关。
- opt:定义信号量删除条件的选项。它有两个选择:①
OS_DEL_NO_PEND
:规定只能在已经没有任何任务等待信号量时,才能删除该信号量。②OS_DEL_ALWAYS
:规定不管有没有任务在等待,都立即删除这个信号量,删除后所有等待该信号量的任务立即进入就绪状态,并执行一次任务调度。 - 如果信号量删除成功,则返回空指针;若信号量没有能被删除,则返回pevent,这时应该检查出错代码,以查明原因。
OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr){ BOOLEAN tasks_waiting; OS_EVENT *pevent_return;#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0;#endif#if OS_ARG_CHK_EN > 0 if (perr == (INT8U *)0) { /* Validate 'perr' */ return (pevent); } if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return (pevent); }#endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return (pevent); } if (OSIntNesting > 0) { /* See if called from ISR ... */ *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ return (pevent); } OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0) { /* See if any tasks waiting on semaphore */ tasks_waiting = OS_TRUE; /* Yes */ } else { tasks_waiting = OS_FALSE; /* No */ } switch (opt) { case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ if (tasks_waiting == OS_FALSE) {#if OS_EVENT_NAME_SIZE > 1 pevent->OSEventName[0] = '?'; /* Unknown name */ pevent->OSEventName[1] = OS_ASCII_NUL;#endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ } else { OS_EXIT_CRITICAL(); *perr = OS_ERR_TASK_WAITING; pevent_return = pevent; } break; case OS_DEL_ALWAYS: /* Always delete the semaphore */ while (pevent->OSEventGrp != 0) { /* Ready ALL tasks waiting for semaphore */ (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); }#if OS_EVENT_NAME_SIZE > 1 pevent->OSEventName[0] = '?'; /* Unknown name */ pevent->OSEventName[1] = OS_ASCII_NUL;#endif pevent->OSEventType = OS_EVENT_TYPE_UNUSED; pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ pevent->OSEventCnt = 0; OSEventFreeList = pevent; /* Get next free event control block */ OS_EXIT_CRITICAL(); if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ OS_Sched(); /* Find highest priority task ready to run */ } *perr = OS_ERR_NONE; pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ break; default: OS_EXIT_CRITICAL(); *perr = OS_ERR_INVALID_OPT; pevent_return = pevent; break; } return (pevent_return);}
- 当任务需要请求信号量时,就需要使用
OSSemPend()
函数。被OSSemPend()
函数挂起的任务,只能被一下三种条件下回复:1. 直到有其它的任务/中断调用OSSemPost()
置位信号量; 2. 信号量超出等待的预期时间; 3. 被OSSemPendAbort
恢复。如果在预期的时钟节拍内信号量被置位,那么μC/OS-Ⅱ默认最高优先级的任务取得信号量并转入就绪。
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0;#endif#if OS_ARG_CHK_EN > 0 if (perr == (INT8U *)0) { /* Validate 'perr' */ return; } if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ *perr = OS_ERR_PEVENT_NULL; return; }#endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ *perr = OS_ERR_EVENT_TYPE; return; } if (OSIntNesting > 0) { /* See if called from ISR ... */ *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ return; } if (OSLockNesting > 0) { /* See if called with scheduler locked ... */ *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ return; } OS_ENTER_CRITICAL(); if (pevent->OSEventCnt > 0) { /* 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 > 0) OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;#endif OS_EXIT_CRITICAL();}
OSSemPost()
函数用于置位指定的信号量,或者说用于发送信号量。如果没有任务在等待信号量,那么OSSem Post()
函数使该信号量加1并返回;如果有任务在等待信号量,那么最高优先级的任务将得到信号量并进入就绪状态。任务调度函数将进行任务调度,决定当前运行的任务是否仍然为最高优先级的任务。
INT8U OSSemPost (OS_EVENT *pevent){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0;#endif#if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ return (OS_ERR_PEVENT_NULL); }#endif if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ return (OS_ERR_EVENT_TYPE); } OS_ENTER_CRITICAL(); if (pevent->OSEventGrp != 0) { /* 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); } 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);}
0 0
- uc/os-ii信号量
- uc/os-ii互斥型信号量
- uc/os-ii信号量集
- uC/OS-II 学习笔记之:信号量
- uC/OS-II的信号量及其操作
- uC/OS-II 学习笔记:信号量
- uC/OS-II 学习笔记:信号量实验
- uc/os-ii信号量的理解
- uc/os-ii实验1:信号量
- uc/os-ii 实验2:信号量
- 移植uC/OS-II到瑞萨的单片机,添加信号量功能
- uC/OS-II互斥信号量与任务优先级反转
- uC/OS-II 函数之信号量相关函数
- UC/OS II事件管理(2)之信号量管理
- UC/OS II事件管理之信号量管理实例
- UC/OS-II基础知识之信号量及其操作
- [uC/OS-II原理及应用]信号量集
- [uC/OS-II原理及应用]信号量集
- Visual C++ Tips: warning C4996: 'stricmp' was declared deprecated
- 矩阵相乘
- 十六进制转换为BCD码
- 《Java课程实习》日志(周二)
- 线程之间的同步与互斥mutex
- uc/os-ii信号量
- Android5.0L因SystemUI ANR导致的黑屏问题分析
- SharedPreferences自动登录系统
- 【Linux】readv与writev
- 函数适配器
- 别被技术绑架
- 移动端混合型 App(hybrid app)自动化测试选型与实践
- 正则里的 /x7f-/xff 这样东西
- 积累linux常用的命令