OS_CORE.C(2)
多任务挂起函数,先附一张流程图:
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON MULTIPLE EVENTS
* 多任务挂起
* Description: This function waits for multiple events. If multiple events are ready at the start of the
* pend call, then all available events are returned as ready. If the task must pend on the
* multiple events, then only the first posted or aborted event is returned as ready.
*描述:该功能是用来等待多个事件。如果在挂起调用开始时,多个事件已准备充分,那么这些事件被转化为就绪状态。
如果一个任务必须挂起多个事件,那么只将第一个准备好的事件转为就绪状态。
* Arguments : pevents_pend is a pointer to a NULL-terminated array of event control blocks to wait for.
*参数: --pevent_pend 是一个指向指针(1)的指针(2),(1)指针指向挂起的事件控制块数组;(2)指针指向(1)指针构成的数组。该数组用null作为结束
* pevents_rdy is a pointer to an array to return which event control blocks are available
* or ready. The size of the array MUST be greater than or equal to the size
* of the 'pevents_pend' array, including terminating NULL.
* --pevents_rdy指向一个指针数组,也是指针(1)的指针(2),(1)指针指向可用或就绪的事件控制块数组;(2)指针指向(1)指针数组。(2)指针指向的数组的大小必须大于或等于pevents_pend指向的数组的大小(包括最后的null)。
* pmsgs_rdy is a pointer to an array to return messages from any available message-type
* events. The size of the array MUST be greater than or equal to the size of
* the 'pevents_pend' array, excluding the terminating NULL. Since NULL
* messages are valid messages, this array cannot be NULL-terminated. Instead,
* every available message-type event returns its messages in the 'pmsgs_rdy'
* array at the same index as the event is returned in the 'pevents_rdy' array.
* All other 'pmsgs_rdy' array indices are filled with NULL messages.
* --pmsgs_rdy也是指针(1)的指针(2)。(1)指针指向消息数组;(2)指针指向(1)指针数组。该数组用来返回从信息类型事件获得的消息。数组的大小必须大于或等于pevents_pend指向数组的大小(除去最后的NULL)。由于null消息是无效的消息,因而这个数组不能是以null结束的。每个可用的信息类型的事件返回它在pmsgs_rdy数组中的消息。该消息与该事件的下标同步变化。所有其他pmsgs_rdy数组索引都用空消息填充
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for the resources up to the amount of time specified by this argument.
* If you specify 0, however, your task will wait forever for the specified
* events or, until the resources becomes available (or the events occur).
* --timeout是一个可选择的超时片(时钟节拍),也就是请求资源的时间。如果超时,就进入睡眠状态。如果非0,任务将等待资源直到满足该参数指定的时间数。如果是0,任务将永远处于睡眠状态,除非有专门的事件或者可以获得资源(或该事件发生)
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
* --perr是一个指向错误信息将被存放的地方的指针。可能的错误信息如下:
* OS_ERR_NONE The call was successful and your task owns the resources
* or, the events you are waiting for occurred; check the
* 'pevents_rdy' array for which events are available.--OS_ERR_NONE无错误:该调用时成功的,你的任务获得了资源或者正在等待的事件发生了;然后检测pevents_rdy数组,看哪个事件是准备就绪的。
* OS_ERR_PEND_ABORT The wait on the events was aborted; check the
* 'pevents_rdy' array for which events were aborted.--OS_ERR_PEND_ABORT取消挂起事件:取消正在等待的事件:检测pevents_rdy数组,确定是哪个事件被取消
* OS_ERR_TIMEOUT The events were not received within the specified
* 'timeout'.-- OS_ERR_TIMEOUT超时错:事件在规定时间片内没有被接收处理
* OS_ERR_PEVENT_NULL If 'pevents_pend', 'pevents_rdy', or 'pmsgs_rdy' is a
* NULL pointer.--OS_ERR_PEVENT_NULL空指针:pevents_pend,pevents_rdy,pmsgs_rdy为空指针
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an array of semaphores,
* mailboxes, and/or queues.--OS_ERR_EVENT_TYPE事件类型错:没有指针指向信号量、邮箱或者队列
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.--OS_ERR_PEND_ISR中断:如果调用了该中断函数,就会引发一个中断
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked.
* --OS_ERR_PEND_LOCKED挂起锁:调度程序被锁时调用该功能会引发错误
* Returns : > 0 the number of events returned as ready or aborted.
* == 0 if no events are returned as ready because of timeout or upon error.
*返回值:>0:当就绪或取消时返回的任务数量=0:由于超时或者以上的错误而无法准备就绪而导致没有返回的事件时,返回值为0
* Notes : 1) a. Validate 'pevents_pend' array as valid OS_EVENTs :
* semaphores, mailboxes, queues
* --a:当OS_EVENT有效时(是信号量、邮箱或者队列),pevents_pend数组才有效
* b. Return ALL available events and messages, if any
* --b:如果有可用的事件和消息时,返回所有的事件和消息
* c. Add current task priority as pending to each events's wait list
* Performed in OS_EventTaskWaitMulti()
* --c:将当前挂起任务的优先级添加到每个事件的等待列表中。具体操作在OS_EventTaskWaitMulti()函数中执行
* d. Wait on any of multiple events
* --d:等待多事件的任何一个
* e. Remove current task priority as pending from each events's wait list
* Performed in OS_EventTaskRdy(), if events posted or aborted
* --e:如果事件延迟或被取消,将当前挂起任务的优先级从每个事件等待列表中移除。具体操作在OS_EventTaskRdy()函数中执行。
* f. Return any event posted or aborted, if any
* else
* Return timeout
* --f:如果有事件被取消或延迟,返回该事件,否则的话返回timeout
* 2) 'pevents_rdy' initialized to NULL PRIOR to all other validation or function handling in
* case of any error(s).--pevents_rdy在所有其他有效值或功能前初始化为null,以防出错。
*********************************************************************************************************
*/
/*$PAGE*/
#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) /*如果可以生成事件并且可以生成多个事件*/
INT16U OSEventPendMulti(OS_EVENT **pevents_pend, /*调用多个事件挂起函数(事件挂起指针、就绪事件指针、就绪消息指针、时间片、错误码指针)*/OS_EVENT **pevents_rdy, void **pmsgs_rdy,INT32U timeout,INT8U *perr)
{OS_EVENT **pevents; /*指针的指针,最终指向事件控制块*/OS_EVENT *pevent; /*指针,指向事件控制块*/
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) /*如果允许生成队列并且最大队列数>0*/OS_Q *pq; /*指定一个指向队列的指针*/
#endifBOOLEAN events_rdy; /*事件就绪*/INT16U events_rdy_nbr; /*准备好的事件数目*/INT8U events_stat; /*事件状态*/
#if (OS_CRITICAL_METHOD == 3u) /* Allocate storage for CPU status register中断类型为3 */OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICAL /*定义安全中断*/if (perr == (INT8U *)0) { /*如果错误信息为0号错误*/OS_SAFETY_CRITICAL_EXCEPTION(); /*调用安全中断异常函数*/}
#endif#if (OS_ARG_CHK_EN > 0u) /*检查参数*/if (pevents_pend == (OS_EVENT **)0) { /* Validate 'pevents_pend'有效化 pevents_pend */*perr = OS_ERR_PEVENT_NULL; /*pevents_pend为0时,将错误信息置为OS_ERR_PEVENT_NULL*/return (0u); /*返回值为0*/}if (*pevents_pend == (OS_EVENT *)0) { /* Validate 'pevents_pend'有效化*pevents_pend*/*perr = OS_ERR_PEVENT_NULL; /* *pevents_pend为0时,将错误信息置为OS_ERR_PEVENT_NULL*/return (0u); /*返回值为0*/}if (pevents_rdy == (OS_EVENT **)0) { /* Validate 'pevents_rdy'有效化pevents_rdy */*perr = OS_ERR_PEVENT_NULL; /*pevents_rdy为0时,将错误信息置为OS_ERR_PEVENT_NULL*/return (0u); /*返回值为0*/}if (pmsgs_rdy == (void **)0) { /* Validate 'pmsgs_rdy'有效化pmsgs_rdy */*perr = OS_ERR_PEVENT_NULL; /*当pmsgs_rdy为0时,将错误信息设置为OS_ERR_PEVENT_NULL*/return (0u); /*返回值为0*/}
#endif*pevents_rdy = (OS_EVENT *)0; /* Init array to NULL in case of errors将数组初始化为null以防错误 */pevents = pevents_pend; /*将pevents_pend指针赋值给pevents。此时pevents和pevents_pend的指向一样,指向指针数组*/pevent = *pevents; /*将指针数组首地址下的指针赋值给pevent,此时pevent为指向事件控制块的指针*//*将首地址下的内容赋值给*/while (pevent != (OS_EVENT *)0) { /*当pevent不为0时,即有指向的事件控制块时*/switch (pevent->OSEventType) { /* Validate event block types有效化事件块类型,看此时pevent指向的事件类型*/
#if (OS_SEM_EN > 0u) /*如果允许生成信号量*/case OS_EVENT_TYPE_SEM: break;
#endif
#if (OS_MBOX_EN > 0u) /*如果生成邮箱*/case OS_EVENT_TYPE_MBOX:break;
#endif
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) /*如果允许生成队列并且队列最大数>0*/case OS_EVENT_TYPE_Q:break;
#endif
/*上面三个if下的情况:事件块类型为信号量、邮箱或者队列时,不做任何处理,跳出循环进行下一步*/case OS_EVENT_TYPE_MUTEX: /*如果是事件块类型互斥量或者是标志类型或者默认情况,将错误信息设置成错误事件类型OS_ERR_EVENT_TYPE,返回值为0*/case OS_EVENT_TYPE_FLAG:default:*perr = OS_ERR_EVENT_TYPE;return (0u);}pevents++; /*指向指针数组的指针加1,看下一个事件控制块*/pevent = *pevents; /*找到事件控制块*/}if (OSIntNesting > 0u) { /* See if called from ISR ... 看是否是调用中断函数 */*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR 如果是,中断函数不能被挂起。错误信息置为OS_ERR_PEND_ISR*/return (0u); /*返回值为0*/}if (OSLockNesting > 0u) { /* See if called with scheduler locked ...看调度程序是否调用了已加锁的函数*/*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked 不能将已上锁的函数挂起 */return (0u); /*返回值为0*/}/*$PAGE*/OS_ENTER_CRITICAL(); /*关中断*/events_rdy = OS_FALSE; /*将事件就绪标志设置为false,即没有事件准备好*/events_rdy_nbr = 0u; /*准备好的事件数目为0*/events_stat = OS_STAT_RDY; /*事件状态设置为就绪态*/pevents = pevents_pend; /*该行和下一行表示找到准备好的事件控制块*/pevent = *pevents; while (pevent != (OS_EVENT *)0) { /* See if any events already available 看是否有事件是可获得的,即已经准备好。!=0说明有 */switch (pevent->OSEventType) { /*查看事件类型*/
#if (OS_SEM_EN > 0u) /*如果允许生成信号量*/case OS_EVENT_TYPE_SEM: /*如果是信号量*/if (pevent->OSEventCnt > 0u) { /* If semaphore count > 0, resource available; 如果信号量数量>0,资源也是可获得的*/pevent->OSEventCnt--; /* ... decrement semaphore, 则将信号量数目减1... */*pevents_rdy++ = pevent; /* ... and return available semaphore event 并且返回可用的信号量事件。将该事件控制块放到就绪事件数组中 */events_rdy = OS_TRUE; /*将事件设置为就绪态*/*pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores对于信号量没有信息可以返回,置为0,但是索引(指针)跟着一起变化,最上面的注释提到过 */events_rdy_nbr++; /*就绪事件数量加1*/}else {events_stat |= OS_STAT_SEM; /* Configure multi-pend for semaphore events将信号量事件设置为多事件挂起状态*/}break;
#endif#if (OS_MBOX_EN > 0u) /*允许生成邮箱*/case OS_EVENT_TYPE_MBOX: /*如果为邮箱类型*/if (pevent->OSEventPtr != (void *)0) { /* If mailbox NOT empty;邮箱不为空 ... *//* ... return available message,返回可获得的消息 ... */*pmsgs_rdy++ = (void *)pevent->OSEventPtr;/*将该消息地址(指针)放到消息就绪数组中*/pevent->OSEventPtr = (void *)0; /*将指向消息的指针重新设置为0,即请求了一个邮箱,邮箱旧有非空态变为空*/*pevents_rdy++ = pevent; /* ... and return available mailbox event并且返回可用的邮箱事件*/events_rdy = OS_TRUE; /*将事件就绪标志设置为true*/events_rdy_nbr++; /*就绪事件数目加1*/}else {events_stat |= OS_STAT_MBOX; /* Configure multi-pend for mailbox events 邮箱事件的多事件挂起状态 */}break;
#endif#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) /*如果允许生成队列并且最大队列数>0*/case OS_EVENT_TYPE_Q: /*如果事件类型是队列*/pq = (OS_Q *)pevent->OSEventPtr; /*事件控制块中的事件指针强制转化为队列类型*/if (pq->OSQEntries > 0u) { /* If queue NOT empty; 队列不为空 ... *//* ... return available message,返回可用的消息,即把队列的消息保存在pmsgs_rdy数组中*/*pmsgs_rdy++ = (void *)*pq->OSQOut++;if (pq->OSQOut == pq->OSQEnd) { /* If OUT ptr at queue end, ... */pq->OSQOut = pq->OSQStart; /* ... wrap to queue start队列的链表要将首尾连接起来*/}pq->OSQEntries--; /* Update number of queue entries 队列数量减一:请求了一个队列,队列的数量就要减1 */*pevents_rdy++ = pevent; /* ... and return available queue event返回可用的队列事件*/events_rdy = OS_TRUE; /*将事件就绪标志设置为true*/events_rdy_nbr++; /*将就绪事件数量加1*/}else {events_stat |= OS_STAT_Q; /* Configure multi-pend for queue events队列事件设置为多事件挂起状态 */}break;
#endifcase OS_EVENT_TYPE_MUTEX: /*如果事件类型是互斥量或者标志量或默认情况*/case OS_EVENT_TYPE_FLAG:default:OS_EXIT_CRITICAL(); /*开中断*/*pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array将null返回到事件数组 *///因为是先保存再加,所以出现错误后不会有后续判断,所以这里就不用++*perr = OS_ERR_EVENT_TYPE; /*将错误信息置为OS_ERR_EVENT_TYPE*/return (events_rdy_nbr); /*返回就绪事件数*/}pevents++; /*指针后移,进行下一个事件的判断*/pevent = *pevents;}if (events_rdy == OS_TRUE) { /* Return any events already available 如果事件就绪标志为true*/
*pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array所有的事件都判断完了补上一个 (OS_EVENT *)0的结束标志 */
OS_EXIT_CRITICAL();/*关中断*/
*perr = OS_ERR_NONE;/*将错误中断设置为OS_ERR_NONE*/
return (events_rdy_nbr);/*返回就绪事件的数量*/
}/* Otherwise, must wait until any event occurs 否则的话,就必须等待直到任何一个事件发生,就会一直进行上面的while循环*/
这一部分主要说的是:如果有准备好的事件,分析其事件类型(邮箱、信号量还是队列),然后分别执行相应的操作。
这篇是该函数的一部分,下篇介绍另一部分。
OS_CORE.C(2)相关推荐
- OS_CORE.C(11)
OS_SchedNew(void)找到将要运行的最高优先级任务函数 和任务调度函数OS_Sched(void): /* **************************************** ...
- OS_CORE.C(10)
今天看os_core.c文件中的各种初始化函数. OS_EventWaitListInit(OS_EVENT *pevent)初始化事件控制块的等待列表: /*$PAGE*/ /*2018/2/8 * ...
- Error: L6406E: No space in execution regions with .ANY selector matching os_core.o(.bss).
试验原因 正在移植ucosii. 移植前的环境是STM32F103VE + lwip2.1.2 在ucosii_v2.92.07文件迁移进工程后, 可以编译过. 这时要修改启动文件 startup_s ...
- OS_CORE.C(总结)
在内核的功能模块中,重点函数为: static void OS_InitEventList(void);/*初始化事件列表*/ static void OS_InitMisc(void);/* ...
- OS_CORE.C(9)
本篇介绍以下几个函数: OSVersion()获得版本号函数. OS_Dummy()虚拟函数. OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U ...
- OS_CORE.C(8)
本篇介绍的是OSStart()函数和OSStatInit()函数和OSTimeTick()函数. OSStart()多任务开始函数: /*$PAGE*/ /* ******************** ...
- OS_CORE.C(7)
本篇介绍的是调度器的上锁和解锁: 调度器上锁函数OSSchedlock()的功能是用于禁止任务调度,使任务保持对CPU的控制权. 调度器开锁函数OSSchedUnlock()的功能是解除对任务调度的禁 ...
- OS_CORE.C(6)
先介绍一下优先级反转的相关知识: 优先级翻转是当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,因此造成高优先级任务被许多具有较低优先级任务阻塞,实时性难以得到保证. 例 ...
- OS_CORE.C(5)
/*$PAGE*/ /* *************************************************************************************** ...
- OS_CORE.C(4)
/*$PAGE*/ /* *************************************************************************************** ...
最新文章
- Canvas入门-利用Canvas绘制好玩的电子时钟
- mysql出现ERROR1698(28000):Access denied for user root@localhost错误解决方法
- 让 Netty “榨干” 你的CPU!
- python【蓝桥杯vip练习题库】ADV-105 不同单词个数统计(集合)
- MailScanner相关规则设置
- android面试题总结加强
- 【原创】user.id字段
- aspnet_regsql在哪里 怎么运行它 以及功能介绍
- apk 反编译_APK反编译与回编译修改包名实现分身
- 清华大学 计算机 林伟,研究人员
- FreeMarker模板文件的组成(2)
- VC窗口形状的绘制---SetWindowRgn
- notepad设置中文
- redis源码剖析(四)跳表
- mysql工作表格制作教程_Access制作复杂报表
- Bootstrap让内容块居中
- vue项目中npm install初始化报错以及‘cross-env’ 不是内部或外部命令问题
- od send断点 下_Win7 od下send断点
- linux sed
- netstat -an|awk '/^tcp/ {++s[$NF]} END {for( a in s) {print a,s[a]}}'