Ucos源码分析------事件控制块与事件控制

Ucos源码分析

1.Ucos源码分析------任务控制块与任务调度
2.Ucos源码分析------事件控制块与事件控制
3.Ucos源码分析------信号量
4.Ucos源码分析------邮箱与队列
5.Ucos源码分析------事件标志组
6.Ucos源码分析------内存管理
7.Ucos源码分析------临界区与中断管理
8.Ucos源码分析------OS启动
9.Ucos总结



1.事件控制块

事件控制块成员
OSEventType定义事件的具体类型
OSEventCnt信号量的计数器
*OSEventPtr定义邮箱或者消息队列时,指向一个消息或消息队列控制块
OSEventGrp等待任务所在的组
OSEventType构成事件控制块的等待任务列表,类似于任务就绪表

OSEventType

宏名说明
OS_EVENT_SEM信号量
OS_EVENT_TYPE_UNUSED未分配
OS_EVENT_TYPE_MBOX消息邮箱
OS_EVENT_TYPE_Q消息队列
OS_EVENT_TYPE_MUTEX互斥信号量

任务与事件着重关注:任务状态的变化;就绪表的变化;事件控制块等待任务表的变化

2.事件的基本函数

2.1任务等待事件

将任务从就绪表移除
事件控制块的等待任务表置位

void  OS_EventTaskWait (OS_EVENT *pevent)
{
    //设置任务控制块的事件指针
    OSTCBCur->OSTCBEventPtr = pevent;            /* Store pointer to event control block in TCB        */
    //将任务从就绪表移除
    if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {   /* Task no longer ready      */
        OSRdyGrp &= ~OSTCBCur->OSTCBBitY;        /* Clear event grp bit if this was only task pending  */
    }
    //等待任务表置位
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
    //等待任务组置位
    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
}

2.2等待事件任务就绪

将任务从事件控制块的等待任务表移除
任务状态相应的等待事件清楚
将任务加入到就绪表

INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
{
    OS_TCB *ptcb;
    INT8U   x;
    INT8U   y;
    INT8U   bitx;
    INT8U   bity;
    INT8U   prio;

    //获取等待该事件的任务的最高优先级
    y    = OSUnMapTbl[pevent->OSEventGrp];            /* Find highest prio. task waiting for message   */
    bity = OSMapTbl[y];
    x    = OSUnMapTbl[pevent->OSEventTbl[y]];
    bitx = OSMapTbl[x];
    prio = (INT8U)((y << 3) + x);                     /* Find priority of task getting the msg         */
    //将该任务从事件等待列表移除
    if ((pevent->OSEventTbl[y] &= ~bitx) == 0x00) {   /* Remove this task from the waiting list        */
        pevent->OSEventGrp &= ~bity;                  /* Clr group bit if this was only task pending   */
    }
    //获取该任务任务控制块
    ptcb                 =  OSTCBPrioTbl[prio];       /* Point to this task's OS_TCB                   */
    //将该任务的任务控制块的延时清零,防止系统滴答定时器导致任务再次进入就绪
    ptcb->OSTCBDly       =  0;                        /* Prevent OSTimeTick() from readying task       */
    //移除该任务的任务控制块的事件
    ptcb->OSTCBEventPtr  = (OS_EVENT *)0;             /* Unlink ECB from this task                     */
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
    ptcb->OSTCBMsg       = msg;                       /* Send message directly to waiting task         */
#else
    msg                  = msg;                       /* Prevent compiler warning if not used          */
#endif
    //清除调用该函数的事件类型的位,进一步判断任务是不是手动挂起
    ptcb->OSTCBStat     &= ~msk;                      /* Clear bit associated with event type          */
    //清除该事件后,如果任务处于就绪态,并且没有手动挂起
    if (ptcb->OSTCBStat == OS_STAT_RDY) {             /* See if task is ready (could be susp'd)        */
    //将任务加入到就绪列表
        OSRdyGrp        |=  bity;                     /* Put task in the ready to run list             */
        OSRdyTbl[y]     |=  bitx;
    }
    return (prio);
}

2.3任务事件等待超时

将任务从事件控制块的等待任务表移除
任务状态设置为就绪态
任务加入到就绪列表是在OSTimeTick** 实现

void  OS_EventTO (OS_EVENT *pevent)
{
    //从事件等待列表移除
    if ((pevent->OSEventTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0x00) {
        pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
    }
    //修改当前任务为就绪态
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;       /* Set status to ready                                */
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;     /* No longer waiting for event                        */
}

因为OSTaskSuspend与OSTaskResume 是手动挂起和手动恢复的,和后面的文章不好分类,在这哪里出来。

3.任务挂起

INT8U OSTaskSuspend (INT8U prio) 实现任务手动挂起
参数prio :指定要获取挂起的任务优先级
  如果挂起当前任务进行任务调度,挂起当前任务可以传入当前任务的优先级或者
  OS_PRIO_SELF,OS_PRIO_SELF的优势是不需要知道当前任务优先级。

INT8U  OSTaskSuspend (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif
    BOOLEAN    self;
    OS_TCB    *ptcb;
#if OS_ARG_CHK_EN > 0
    if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to suspend idle task    */
        return (OS_TASK_SUSPEND_IDLE);
    }
    if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {       /* Task priority valid ?               */
        return (OS_PRIO_INVALID);
    }
#endif
    OS_ENTER_CRITICAL();
    if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */
        //获取当前任务的优先级
        //self = TRUE; 需进行调度
        prio = OSTCBCur->OSTCBPrio;
        self = TRUE;
    }
    //判断是否是调用此函数的任务的任务优先级
    else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */
        self = TRUE;
    } else {
        self = FALSE;                                           /* No suspending another task          */
    }
    //获取待挂起任务的任务控制块
    ptcb = OSTCBPrioTbl[prio];
    if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */
        OS_EXIT_CRITICAL();
        return (OS_TASK_SUSPEND_PRIO);
    }
    //任务从就绪表移除
    if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { /* Make task not ready                 */
        OSRdyGrp &= ~ptcb->OSTCBBitY;
    }
    //添加挂起状态
    ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */
    OS_EXIT_CRITICAL();
    //如果是当前任务被挂起,需要进行任务调度
    if (self == TRUE) {                                         /* Context switch only if SELF         */
        OS_Sched();
    }
    return (OS_NO_ERR);
}

4.挂起任务的恢复

用 OSTaskSuspend()挂起的任务只能用 OSTaskResume ()唤醒
如果挂起恢复后,任务为就绪态,此时将任务加入就绪表,并进行任务调度

NT8U  OSTaskResume (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif
    OS_TCB    *ptcb;


#if OS_ARG_CHK_EN > 0
    if (prio >= OS_LOWEST_PRIO) {                               /* Make sure task priority is valid    */
        return (OS_PRIO_INVALID);
    }
#endif
    OS_ENTER_CRITICAL();
    //获取任务控制块
    ptcb = OSTCBPrioTbl[prio];
    //判断任务控制块是否有效
    if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */
        OS_EXIT_CRITICAL();
        return (OS_TASK_RESUME_PRIO);
    }
    // 判断任务是否处于挂起状态
    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) {              /* Task must be suspended   */
        //ptcb->OSTCBStat &= ~OS_STAT_SUSPEND  清除任务挂起状态位
        //ptcb->OSTCBDly  == 0          代表任务处于不等待事件情况

        // 恢复手动挂起 任务没有等待事件       条件1 = 1;条件2 =1;
        // 恢复手动挂起并且任务等待的事件 已 得到 条件1 = 1;条件2 =1;  
        // 恢复手动挂起并且任务等待的事件 未 得到 条件1 = 0;条件2 =0;                

        if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&      /* Remove suspension        */
             (ptcb->OSTCBDly  == 0)) {                                     /* Must not be delayed      */
             //任务加入就绪表
            OSRdyGrp               |= ptcb->OSTCBBitY;                     /* Make task ready to run   */
            OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
            OS_EXIT_CRITICAL();
             //系统调度
            OS_Sched();
        } else {
            OS_EXIT_CRITICAL();
        }
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();
    return (OS_TASK_NOT_SUSPENDED);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值