OSMboxPend()

来源:互联网 发布:云计算概念技术与架构 编辑:程序博客网 时间:2024/05/20 19:19

void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif    
    void      *msg;


    if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
        return ((void *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    msg = pevent->OSEventPtr;             ;首先将消息邮箱的指针成员(数据缓冲区指针)赋值给局部变量msg
    if (msg != (void *)0) {                          ; 检测是否为空指针,如果不是空指针,就将消息邮箱的指针赋给msg,并
        pevent->OSEventPtr = (void *)0;     ;将err指针指向的值赋于常数OS_NO_ERR,然后把msg即消息邮          
        OS_EXIT_CRITICAL();                      ;箱里的指针返回。
        *err = OS_NO_ERR;
        return (msg);                                 
    }
    OSTCBCur->OSTCBStat |= OS_STAT_MBOX;              ;如果消息邮箱的指针不可用,就将当前任务控制块的
    OSTCBCur->OSTCBDly   = timeout;                              ;表征当前任务状态的成员赋值表示任务由于等待消息邮
    OS_EventTaskWait(pevent);                         ;箱而处于挂起状态,任务等待的时限为timeout
    OS_EXIT_CRITICAL();
    OS_Sched();                                    ;该任务已经挂起,使用调度器进行任务调度。如果中断程序都结束、调度器没有锁定、就绪表中优先级别最高的任务不是当前任务,那么进行任务调度,切换程序;否则,从调度其中返回,不做任务diaod
    OS_ENTER_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;                 ;将当前任务控制块指向消息邮箱的指针又给了局部变量msg
    if (msg != (void *)0) {                             ;如果msg指针有效,则改变任务控制块相应的成员变量,给err指针返回
        OSTCBCur->OSTCBMsg      = (void *)0;         ;无错信息,并返回msg指针,即返回消息邮箱的指针。
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;      /* No longer waiting for event                   */
        OS_EXIT_CRITICAL();
        *err                    = OS_NO_ERR;
        return (msg);                                 /* Return the message received                   */
    }
    OS_EventTO(pevent);                               ;任务等待该消息邮箱的时限到
    OS_EXIT_CRITICAL();
    *err = OS_TIMEOUT;                                ;返回超时标志到err指针
    return ((void *)0);                               /* Return a NULL message                         */
}
请求消息邮箱的工作主要有:第一, 检查是在中断服务程序中调用请求消息邮箱,如果是则给err指针返回常数OS_ERR_PEND_ISR,程序返回一个空指针;第二,检查所请求的邮箱是否有效,如果无效,则给err指针返回常数OS_ERR_PEVENT_NULL,程序返回一个空指针;第三,检查所请求的消息邮箱的类型是否为邮箱类型,如果不是,则给err指针返回OS_ERR_EVENT_TYPE,程序返回一个空指针;第四,获得所请求的邮箱指针,若果该指针有效,将消息邮箱中的指针清空(表示已经被获得),然后给err指针返回常数OS_NO_ERR,然后程序返回邮箱的指针;第五,如果获得的邮箱指针无效,就将任务控制块的状态设为等待状态,并告诉任务控制块要等待的时限,然后调用OS_EventTaskWait ,删除掉任务在就绪表中的相应位置,置位任务在事件等待列表中的相应位置;第六,调用OS_Sched()进行任务调度,如果调度成功,则进行任务切换,如果调度条件不满足,又返回到该程序;第七,将任务控块成员OSTCBCur->OSTCBMsg指针值(即邮箱的指针)给了msg指针,如果这个指针不空,将OSTCBCur->OSTCBMsg  清零,任务未就绪状态,给err 指针返回常数OS_NO_ERR,程序返回邮箱指针msg;第八,调用OS_EventTO(pevent);等待时限到,给err指针返回常数OS_TIMEOUT,程序返回一个空指针,程序结束。

void  OS_EventTaskWait (OS_EVENT *pevent)
{
    INT8U  y;


    OSTCBCur->OSTCBEventPtr = pevent;            ;把事件控制块的指针保存在任务控制块成员OSTCBEventPtr里
    y                       = OSTCBCur->OSTCBY;             ;把当前任务从任务就绪表中删除
    OSRdyTbl[y]            &= ~OSTCBCur->OSTCBBitX;
    if (OSRdyTbl[y] == 0x00) {                   
        OSRdyGrp &= ~OSTCBCur->OSTCBBitY;        /* Clear event grp bit if this was only task pending  */
    }
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;         ;把当前任务在事件控制块的
    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;                           ;列表中的相应位置位。
}该函数主要完成的工作:第一,把事件控制块的指针保存在等待该事件的任务的任务控制块的成员OSTCBEventPtr 里面;第二,把该任务在任务就绪表中的相应位删除,即该任务处于挂起等待状态,等待消息邮箱的状态;第三,把该任务要等待的事件的事件控制块里的等待任务列表的相应位置位,表示这个任务要等到这个事件的发生。

void  OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
    OS_CPU_SR  cpu_sr;
#endif    
    INT8U      y;


    OS_ENTER_CRITICAL();
    if (OSIntNesting == 0) {                          ;所有的中断服务程序结束并且调度器没有锁定,才进行调度
        if (OSLockNesting == 0) {                     
            y             = OSUnMapTbl[OSRdyGrp];     ;找出任务就绪表中优先级别最高的就绪任务
            OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
            if (OSPrioHighRdy != OSPrioCur) {          ;如果就绪表中的优先级别最高的任务不是当前任务就进行调度
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
                OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task      */
#endif
                OSCtxSwCtr++;                          /* Increment context switch counter             */
                OS_TASK_SW();                          /* Perform a context switch                     */
            }
        }                                                      ;如果就绪表中优先级最高的任务就是当前的任务,就不再进行任务调度,从
    }                                                          ;调度器返回。
    OS_EXIT_CRITICAL();
}调度器完成的主要工作有:第一,在所有中断服务结束并且调度器没有被锁定时才进行任务调度;第二,找出任务就绪表中优先级别最高的就绪任务;第三,如果优先级别最高的就绪任务不再是当前任务,就进行任务调度,转去执行优先级别最高的任务,如果就绪表中优先级别最高的任务还是当前任务,那么不进行任务调度,调度其返回到调用它的程序里面。

void  OS_EventTO (OS_EVENT *pevent)
{
    INT8U  y;


    y                      = OSTCBCur->OSTCBY;
    pevent->OSEventTbl[y] &= ~OSTCBCur->OSTCBBitX;
    if (pevent->OSEventTbl[y] == 0x00) {
        pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY;
    }
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;       /* Set status to ready                                */
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;     /* No longer waiting for event                        */
};任务等待事件的时限到,删除事件控制块等待任务列表中该任务的相应位,是任务的状态处于就绪状态。

原创粉丝点击