• 嵌入式实时操作系统μCOS原理与实践+事件部分代码



    //事件等待表的初始化函数;pevent表示事件控制块的指针
    #if (OS_EVENT_EN)
    void  OS_EventWaitListInit (OS_EVENT *pevent)
    {
        INT8U  i;
        pevent->OSEventGrp = 0u;                     /* No task waiting on event                           */
        for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
            pevent->OSEventTbl[i] = 0u;
        }
    }






        //事件等待表的初始化函数;pevent表示事件控制块的指针
        #if (OS_EVENT_EN)
        void  OS_EventWaitListInit (OS_EVENT *pevent)
        {
            INT8U  i;
            pevent->OSEventGrp = 0u;                     /* No task waiting on event                           */
            for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
            pevent->OSEventTbl[i] = 0u;
            }
        }
        #endif



        //事件控制块的初始化
        static  void  OS_InitEventList (void)
        {
            //OS_EVENT_EN判断是否使用事件管理--事件是否大于0
        #if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
        #if (OS_MAX_EVENTS > 1u)//OS_MAX_EVENTS=10
            INT16U     ix;
            INT16U     ix_next;
            //指向事假控制块的指针变量
            OS_EVENT  *pevent1;
            OS_EVENT  *pevent2;
            
            //清空事件表---但是可能其他事件给清0了
            OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table                   */
            //初始事件控制块OS_MAX_EVENTS=10--
            for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++) {        /* Init. list of free EVENT control blocks */
            ix_next = ix + 1u;
            pevent1 = &OSEventTbl[ix];
            pevent2 = &OSEventTbl[ix_next];
            pevent1->OSEventType    = OS_EVENT_TYPE_UNUSED;
            pevent1->OSEventPtr     = pevent2;
        #if OS_EVENT_NAME_EN > 0u
                    //给事件区名称
            pevent1->OSEventName    = (INT8U *)(void *)"?";     /* Unknown name                            */
        #endif
            }
            //OS_EVENT_TYPE_UNUSED=0--ix=9-表尾部
            pevent1                         = &OSEventTbl[ix];
            pevent1->OSEventType            = OS_EVENT_TYPE_UNUSED;
            pevent1->OSEventPtr             = (OS_EVENT *)0;
        #if OS_EVENT_NAME_EN > 0u
            pevent1->OSEventName            = (INT8U *)(void *)"?"; /* Unknown name                            */
        #endif
            //OSEventFreeList指向控制块的头部--基本就是初始化成功
            OSEventFreeList                 = &OSEventTbl[0];
        #else
            OSEventFreeList                 = &OSEventTbl[0];       /* Only have ONE event control block       */
            OSEventFreeList->OSEventType    = OS_EVENT_TYPE_UNUSED;
            OSEventFreeList->OSEventPtr     = (OS_EVENT *)0;
        #if OS_EVENT_NAME_EN > 0u
            OSEventFreeList->OSEventName    = (INT8U *)"?";         /* Unknown name                            */
        #endif
        #endif
        #endif
        }



        //移除任务控制块
        #if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u))
        void  OS_EventTaskRemoveMulti (OS_TCB    *ptcb,
                           OS_EVENT **pevents_multi)
        {
            OS_EVENT **pevents;
            OS_EVENT  *pevent;
            INT8U      y;
            OS_PRIO    bity;
            OS_PRIO    bitx;


            y       =  ptcb->OSTCBY;
            bity    =  ptcb->OSTCBBitY;
            bitx    =  ptcb->OSTCBBitX;
            pevents =  pevents_multi;
            pevent  = *pevents;
            while (pevent != (OS_EVENT *)0) {                   /* Remove task from all events' wait lists     */
            pevent->OSEventTbl[y]  &= (OS_PRIO)~bitx;
            if (pevent->OSEventTbl[y] == 0u) {
                pevent->OSEventGrp &= (OS_PRIO)~bity;
            }
            pevents++;
            pevent = *pevents;
            }
        }



        //取消事件的等待;
        #if (OS_EVENT_EN)
        void  OS_EventTaskRemove (OS_TCB   *ptcb,
                      OS_EVENT *pevent)
        {
            INT8U  y;
            
            //在事件等待表删除事件等待标志
            y                       =  ptcb->OSTCBY;
            pevent->OSEventTbl[y]  &= (OS_PRIO)~ptcb->OSTCBBitX;    /* Remove task from wait list              */
            //若该行已没有任务等待
            if (pevent->OSEventTbl[y] == 0u) {
                //删除事件等待组的事件等待标志;
            pevent->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
            }
        }
        #endif



        #if (OS_EVENT_EN)
        //事件等待函数
        void  OS_EventTaskWait (OS_EVENT *pevent)
        {
            INT8U  y;
            //在tcb的OSTCBEventPtr域存储ecb指针-以后通过该任务的tcb可直接找到正事件的ecb
            OSTCBCur->OSTCBEventPtr               = pevent;                 /* Store ptr to ECB in TCB         */
            //在事件等待组和事件等待表中进行标识
            pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;    /* Put task in waiting list        */
            pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
            //OSTCBY指把任务优先级右移三位;任务优先级低三位OSTCBBitX具体在哪个位置
            //以上将该任务在ecb中登记完毕,下面将阻塞这个任务-等待任务事件的发生
            y             =  OSTCBCur->OSTCBY;            /* Task no longer ready                              */
            //把就绪表中给删除掉 取反 在与操作-给对应位给清掉;
            OSRdyTbl[y]  &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
            if (OSRdyTbl[y] == 0u) {                      /* Clear event grp bit if this was only task pending */
            //得给就绪表里是否没有事件发生了;
                OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
            }
        }
        #endif


        //等待事件的任务就绪函数
        #if (OS_EVENT_EN)
        INT8U  OS_EventTaskRdy (OS_EVENT  *pevent,//对应ecb指针
                    void      *pmsg,//信息指针
                    INT8U      msk,//信息状态位的掩码--清除tcb状态位
                    INT8U      pend_stat)//等待事件的原因/OS_STAT_PEND_OK/OS_STAT_PEND_ABORT
        {
            OS_TCB   *ptcb;
            INT8U     y;
            INT8U     x;
            INT8U     prio;
            //判断优先级
        #if OS_LOWEST_PRIO > 63u
            OS_PRIO  *ptbl;
        #endif

        #if OS_LOWEST_PRIO <= 63u
            //在事件等待等待表和事件组找到优先级最高的任务;
            y    = OSUnMapTbl[pevent->OSEventGrp];              /* Find HPT waiting for message                */
            x    = OSUnMapTbl[pevent->OSEventTbl[y]];
            prio = (INT8U)((y << 3u) + x);                      /* Find priority of task getting the msg       */
        #else
            if ((pevent->OSEventGrp & 0xFFu) != 0u) {           /* Find HPT waiting for message                */
            y = OSUnMapTbl[ pevent->OSEventGrp & 0xFFu];
            } else {
            y = OSUnMapTbl[(OS_PRIO)(pevent->OSEventGrp >> 8u) & 0xFFu] + 8u;
            }
            //查找优先级指标表找到对应的TCB指针;
            ptbl = &pevent->OSEventTbl[y];
            if ((*ptbl & 0xFFu) != 0u) {  //若不为0 调度器每个时钟滴答对该值-1 减到0后 将任务就绪;
            x = OSUnMapTbl[*ptbl & 0xFFu];
            } else {
                //本函数发生冲突--强制为0
            x = OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u;
            }
            prio = (INT8U)((y << 4u) + x);                      /* Find priority of task getting the msg       */
        #endif
            //任务控制块ptcb
            ptcb                  =  OSTCBPrioTbl[prio];        /* Point to this task's OS_TCB                 */
            ptcb->OSTCBDly        =  0u;                        /* Prevent OSTimeTick() from readying task     */
        #if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u)
           //给TCB中信息指针赋值
            ptcb->OSTCBMsg        =  pmsg;                      /* Send message directly to waiting task       */
        #else
            //防止编译器发送警告
            pmsg                  =  pmsg;                      /* Prevent compiler warning if not used        */
        #endif
            //清除任务状态中对应等待标志,--任务已经不再等待给事件了
            ptcb->OSTCBStat      &= (INT8U)~msk;                /* Clear bit associated with event type        */
            //s设置等待状态
            ptcb->OSTCBStatPend   =  pend_stat;                 /* Set pend status of post or abort            */
             //判断任务数是否被挂起 为0 不是挂起 -就让他就绪;挂起的任务不能因为事件的发生而就绪;                                                   /* See if task is ready (could be susp'd)      */
            if ((ptcb->OSTCBStat &   OS_STAT_SUSPEND) == OS_STAT_RDY) {
            OSRdyGrp         |=  ptcb->OSTCBBitY;           /* Put task in the ready to run list           */
            OSRdyTbl[y]      |=  ptcb->OSTCBBitX;
            }
            //在事件等待表删除该任务;
            OS_EventTaskRemove(ptcb, pevent);                   /* Remove this task from event   wait list     */
        #if (OS_EVENT_MULTI_EN > 0u)
            if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) {   /* Remove this task from events' wait lists    */
            OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
            ptcb->OSTCBEventPtr       = (OS_EVENT  *)pevent;/* Return event as first multi-pend event ready*/
            }
        #endif

            return (prio);
        }
        #endif


        //时钟中断
        void  OSTimeTick (void)
        {
            OS_TCB    *ptcb;
            BOOLEAN    step;
            OSTimeTickHook();                                      /*调用用户钩子函数,默认是空函数                     */

        #if OS_TIME_GET_SET_EN > 0u
            OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter               */
            OSTime++; //调度计数+1
            OS_EXIT_CRITICAL();
        #endif
            //成立表示已经启动多任务
            if (OSRunning == OS_TRUE) {
        #if OS_TICK_STEP_EN > 0u
            switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
                case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
                 step = OS_TRUE;
                 break;

                case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
                 step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
                 break;

                case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
                 step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
                 OSTickStepState = OS_TICK_STEP_WAIT;
                 break;

                default:                                       /* Invalid case, correct situation              */
                 step            = OS_TRUE;
                 OSTickStepState = OS_TICK_STEP_DIS;
                 break;
            }
            if (step == OS_FALSE) {                            /* Return if waiting for step command           */
                return;
            }
        #endif
                 /* Point at first TCB in TCB list */
            ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
            while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
                OS_ENTER_CRITICAL();
                if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO     */
                ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay       */
                        //Check for timeout
                        if (ptcb->OSTCBDly == 0u) {                /* Check for timeout                            */
                            //若有任务等待一事件的发生
                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                                // Clear status flag  
                                ptcb->OSTCBStat  &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag   */
                    ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout    */
                    } else {
                    ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
                    }
                            //如果任务不是被挂起的
                    if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended?       */
                    OSRdyGrp               |= ptcb->OSTCBBitY;             /* No,  Make ready          */
                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                    }
                }
                }
                    // Point at next TCB in TCB list
                ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
                OS_EXIT_CRITICAL();
            }
            }
        }

  • 相关阅读:
    远景GIS云产品规划
    远景GIS云上线
    远景WEBGIS平台实现客户端SHP文件加载
    GIS平台结构设计
    一款基于HTML5的高性能WEBGIS介绍
    Git分布式工作流程
    Git服务器搭建
    Linux入门-9 软件管理基础(CentOS)
    Linux入门-8 Linux系统启动详解
    Linux入门-7 Linux管道、重定向以及文本处理
  • 原文地址:https://www.cnblogs.com/wxb20/p/6111614.html
Copyright © 2020-2023  润新知