浅析μCOS/II v2.85内核OSFlagPend()和OSFlagPost()

浅析μCOS/II v2.85内核OSFlagPend()OSFlagPost()函数工作原理
http://gliethttp.cublog.cn
//对于flag--"事件组"的使用,可以用一个简单的例子做说明:
// 比如,我现在用迅雷下载一部10集的连续剧,我打算10集全部下载完成之后,
//才开始正式看,现在3~10集因为种子原因,先早下完了,现在第1集下到了82%,
//2集下到了97%,因为我的计划是10集全部下完才开始看,而第1集和第2
//由于网络,种子等等各种原因,迟迟不能下载完成,进而导致我的计划被悬停,不能进行,
//已下载的8,也因为前2集没能下完,而白白等待---这就等同于flag事件组,
//1~10,每一集都是一个事件,因为我内定,10个事件全部完成之后,才进入下一事件--"观看"
//所以及早完成自己事件的第3~10,将主动把自己通过flag事件组函数OSFlagPost()登记到事件组上,
//他们不关心,其他友邻事件完成否,只专注自己的事件是否完成,自己的事件一旦完成
//就登记到事件组上,最后3~10,都把自己登记上去了,只剩下第1集和第2,
//一旦某天的某个时刻,2集下完了,那么第2集也把自己登记到事件组上,这样整个事件距离完成
//还剩下一个事件,就是第1集是否下载完成,只要第1集下载完成,那么我内定的"观看"计划
//开始启动,过了3分钟,由于网速提高,竟以300k的速度开始下载第1,1分钟之后,
//1集也下载完成了,1集立即调用OSFlagPost事件组函数,将自己登记到事件组上,
//ok,OSFlagPost()检测到所有事件已经完成,OSFlagPost()将是""自动进入下一事件---"观看"
// 还有一点就是关于flag事件组和Sem,Mbox,Queue的区别之处,flag事件组不使用事件控制矩阵来
//管理被阻塞在事件上的task进程,flag事件组使用pgrp的双向链表来挂接起所有task,
//OSFlagPost()中将遍历这个链表,查找符合当前flag事件的task,将该task从双向链表中摘下
//然后放入就绪控制矩阵中,之所以这样,是因为flag事件组不像Sem,Mbox,Queue那样具有二值性,
//Sem,Mbox,Queue,要么有,要么没有,flag事件组,还要进一步判断,有的话,是什么程度的有.
//----------------------------------------------------------------------
//1.OSFlagPend()函数
OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *perr)
{
    OS_FLAG_NODE node;
    OS_FLAGS flags_rdy;
    INT8U result;
    INT8U pend_stat;
    BOOLEAN consume;
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr = 0;
#endif

#if OS_ARG_CHK_EN > 0
    if (perr == (INT8U *)0) {
        return ((OS_FLAGS)0);
    }
    if (pgrp == (OS_FLAG_GRP *)0) {
        *perr = OS_ERR_FLAG_INVALID_PGRP;
        return ((OS_FLAGS)0);
    }
#endif
    if (OSIntNesting > 0) {
//ISR,不能使用OSFlagPend()
        *perr = OS_ERR_PEND_ISR;
        return ((OS_FLAGS)0);
    }
    if (OSLockNesting > 0) {
//μCOS/II v2.85内核已经被强制锁住
        *perr = OS_ERR_PEND_LOCKED;
        return ((OS_FLAGS)0);
    }
    if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {
//确保该event控制块是flag类型
        *perr = OS_ERR_EVENT_TYPE;
        return ((OS_FLAGS)0);
    }
    result = (INT8U)(wait_type & OS_FLAG_CONSUME);
    if (result != (INT8U)0) {
//收到指定事件们之后,复位flag事件组,将相应的事件标志清0
        wait_type &= ~(INT8U)OS_FLAG_CONSUME;
        consume = OS_TRUE;
    } else {
        consume = OS_FALSE;
    }
    OS_ENTER_CRITICAL();
    switch (wait_type) {
        case OS_FLAG_WAIT_SET_ALL:
            //2007-09-09 gliethttp
            //flag事件组中所有事件都置位才唤醒
             flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags);
             if (flags_rdy == flags) {
            //flag事件组中指定的所有事件都已经登记了
                 if (consume == OS_TRUE) {
            //清除flag事件组中的相应事件标志位
                     pgrp->OSFlagFlags &= ~flags_rdy;
                 }
                 OSTCBCur->OSTCBFlagsRdy = flags_rdy;//返回成功的flag事件组值
                 OS_EXIT_CRITICAL();
                 *perr = OS_ERR_NONE

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值