久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

ucos OSEventPendMulti 函數(shù)解析

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年04月27日   【字體:

 這個(gè)函數(shù)是請(qǐng)求信號(hào)量,郵箱,消息隊(duì)列的,但是對(duì)互斥信號(hào)量和標(biāo)志不起作用。

#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u))
INT16U  OSEventPendMulti (OS_EVENT  **pevents_pend,//掛起的事件組(需要請(qǐng)求資源)
                          OS_EVENT  **pevents_rdy, //就緒的事件組
                          void      **pmsgs_rdy,   //保存請(qǐng)求中返回的信息
                          INT32U      timeout,     //請(qǐng)求資源的時(shí)間,如果超時(shí)任務(wù)進(jìn)入休眠態(tài)
                          INT8U      *perr)        
{
    OS_EVENT  **pevents;
    OS_EVENT   *pevent;
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
    OS_Q       *pq;             //如果使用隊(duì)列且最大隊(duì)列控制塊數(shù)大于0則申請(qǐng)一個(gè)隊(duì)列控制塊指針
#endif
    BOOLEAN     events_rdy;     //是否有準(zhǔn)備好的事件標(biāo)志
    INT16U      events_rdy_nbr; //準(zhǔn)備好的事件數(shù)
    INT8U       events_stat;    //事件狀態(tài)
#if (OS_CRITICAL_METHOD == 3u)  
    OS_CPU_SR   cpu_sr = 0u;
#endif
 
#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
    }
#endif
//驗(yàn)證各個(gè)參數(shù)的有效性
#if (OS_ARG_CHK_EN > 0u)
    if (pevents_pend == (OS_EVENT **)0) {      
       *perr =  OS_ERR_PEVENT_NULL;
        return (0u);
    }
    if (*pevents_pend  == (OS_EVENT *)0) {    
       *perr =  OS_ERR_PEVENT_NULL;
        return (0u);
    }
    if (pevents_rdy  == (OS_EVENT **)0) {      
       *perr =  OS_ERR_PEVENT_NULL;
        return (0u);
    }
    if (pmsgs_rdy == (void **)0) {            
       *perr =  OS_ERR_PEVENT_NULL;
        return (0u);
    }
#endif
//初始化指向就緒事件數(shù)組的指針為NULL
   *pevents_rdy = (OS_EVENT *)0;              
//pevents指向掛起等待的事件組,已經(jīng)處于就緒態(tài)的事件組是不需要再判斷的,pevent指向該事件組中的事件.
    pevents     =  pevents_pend;
    pevent      = *pevents;
//對(duì)事件組中的所有事件進(jìn)行類型檢查
    while  (pevent != (OS_EVENT *)0) {
        switch (pevent->OSEventType) {        
#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))
            case OS_EVENT_TYPE_Q:
                 break;
#endif
 
            case OS_EVENT_TYPE_MUTEX:
            case OS_EVENT_TYPE_FLAG:
            default:
                *perr = OS_ERR_EVENT_TYPE;
                 return (0u);
        }
        pevents++;        //即數(shù)組地址+1
        pevent = *pevents;//指向下一個(gè)元素
    }
//不能在中斷程序中調(diào)用
    if (OSIntNesting  > 0u) {                  
       *perr =  OS_ERR_PEND_ISR;                
        return (0u);
    }
//任務(wù)被鎖住也是不能掛起的
    if (OSLockNesting > 0u) {                  
       *perr =  OS_ERR_PEND_LOCKED;            
        return (0u);
    }
 
    OS_ENTER_CRITICAL();                 //進(jìn)入中斷沿
    events_rdy     =  OS_FALSE;          //事件就緒標(biāo)志初始化為0
    events_rdy_nbr =  0u;                //就緒事件數(shù)初始化為0
    events_stat    =  OS_STAT_RDY;       //事件狀態(tài)初始化為就緒態(tài)
    pevents        =  pevents_pend;      //pevents指向掛起等待的事件組 pevent指向事件組中的事件
    pevent         = *pevents;
    while (pevent != (OS_EVENT *)0) {    //當(dāng)最后一個(gè)元素值為(OS_EVENT *)0時(shí)等待事件組都判斷完了
        switch (pevent->OSEventType) {   //對(duì)事件組中請(qǐng)求特定資源的事件做特定處理
#if (OS_SEM_EN > 0u)                       
            case OS_EVENT_TYPE_SEM:      //信號(hào)量事件,信號(hào)量大于0說明資源是可用的
                 if (pevent->OSEventCnt > 0u) {
                     pevent->OSEventCnt--;      
    //請(qǐng)求得到滿足,可用的信號(hào)量數(shù)就減少了所以要--
                    *pevents_rdy++ =  pevent;  
    //這個(gè)事件進(jìn)入就緒事件表
                      events_rdy   =  OS_TRUE;
    //標(biāo)志一下有事件就緒了
                    *pmsgs_rdy++   = (void *)0;
    //信號(hào)量沒有返回消息
                      events_rdy_nbr++;
    //就緒的事件數(shù)加1
                 } else {
                      events_stat |=  OS_STAT_SEM;
    //請(qǐng)求失敗則標(biāo)記為事件組等待信號(hào)量
                 }
                 break;
#endif
 
#if (OS_MBOX_EN > 0u)
            case OS_EVENT_TYPE_MBOX://是郵箱事件如果郵箱有東西則請(qǐng)求得到滿足
                 if (pevent->OSEventPtr != (void *)0) {                                      *pmsgs_rdy++=(void *)pevent->OSEventPtr;
     //把郵箱的消息地址保存在message_ready數(shù)組中
                     pevent->OSEventPtr  = (void *)0;
     //請(qǐng)求了一個(gè)郵箱郵箱就由非空狀態(tài)變空
                     *pevents_rdy++=pevent;
                     //這個(gè)事件進(jìn)入就緒態(tài)
                      events_rdy=OS_TRUE;        
                     //標(biāo)志一下有事件就緒了
                      events_rdy_nbr++;
                     //準(zhǔn)備好的事件數(shù)加1
                 } else {
                      events_stat |= OS_STAT_MBOX;
                     //請(qǐng)求郵箱失敗標(biāo)記事件組等待郵箱
                 }
                 break;
#endif
 
#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
            case OS_EVENT_TYPE_Q:                //如果是隊(duì)列事件
                 pq = (OS_Q *)pevent->OSEventPtr;//pq指向隊(duì)列事件指針
                 if (pq->OSQEntries > 0u) {      //如果隊(duì)列非空                          
                 *pmsgs_rdy++ = (void *)*pq->OSQOut++;
                         //把隊(duì)列的消息保存在pmsgs_rdy的數(shù)組中
                     if (pq->OSQOut == pq->OSQEnd) {
                         pq->OSQOut = pq->OSQStart;
                     }   //隊(duì)列的鏈表要把首尾連接起來
                     pq->OSQEntries--; 
                     //請(qǐng)求了一個(gè)隊(duì)列隊(duì)列中消息就減少了(隊(duì)列是鏈表,其中一塊少了即入口少了)
                    *pevents_rdy++ = pevent;      
                     //請(qǐng)求得到允許事件進(jìn)入就緒態(tài)                    
                     events_rdy   = OS_TRUE;          //標(biāo)志一下有事件就緒了  
                      events_rdy_nbr++;               //就緒事件數(shù)加1
                 } else {
                      events_stat |= OS_STAT_Q;    }
                     //請(qǐng)求隊(duì)列未得到允許則標(biāo)志事件組狀態(tài)為等待隊(duì)列                 
                 break;
#endif
 
            case OS_EVENT_TYPE_MUTEX:
            case OS_EVENT_TYPE_FLAG:
            //對(duì)互斥信號(hào)量事件和標(biāo)志事件則不做處理
            default:
            //如果都不是這些事件類型則退出中斷沿并返回事件類型錯(cuò)誤
                 OS_EXIT_CRITICAL();
                *pevents_rdy = (OS_EVENT *)0;//這里用這個(gè)(OS_EVENT *)0返回空的消息
            //因?yàn)槭窍缺4嬖偌铀猿霈F(xiàn)錯(cuò)誤不會(huì)有后續(xù)判斷這里就不用++
                *perr=  OS_ERR_EVENT_TYPE;
                 return (events_rdy_nbr);    //返回就緒的事件數(shù)
        }
        pevents++;
        pevent = *pevents;                              
        //對(duì)事件組中的每一個(gè)事件做判斷
    }
 
    if ( events_rdy == OS_TRUE) {    
       *pevents_rdy = (OS_EVENT *)0;  
       //所有的事件都判斷完了補(bǔ)上一個(gè) (OS_EVENT *)0的結(jié)束標(biāo)志
        OS_EXIT_CRITICAL();
       *perr  =  OS_ERR_NONE;
        return (events_rdy_nbr);    //返回事件的就緒數(shù)(調(diào)用這個(gè)函數(shù)的任務(wù)繼續(xù)運(yùn)行)
    }
       //如果沒有事件就緒即所有請(qǐng)求都失敗則掛起調(diào)用該函數(shù)的函數(shù)  
    OSTCBCur->OSTCBStat     |= events_stat  | OS_STAT_MULTI;
       //標(biāo)記當(dāng)前事件控制塊中的事件狀態(tài)為等待資源而且是等待多個(gè)資源
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
       //配置當(dāng)前事件控制塊中的事件狀態(tài)標(biāo)志為等待完成,因?yàn)檫@個(gè)事件即將被切換掉,進(jìn)入掛起態(tài)
    OSTCBCur->OSTCBDly       = timeout;        
       //設(shè)置該任務(wù)掛起等待的時(shí)間為timeout時(shí)間,超時(shí)任務(wù)就被切換掉。
    OS_EventTaskWaitMulti(pevents_pend);      
    //暫停任務(wù)直到出現(xiàn)新的事件呼叫或者掛起時(shí)間到
    OS_EXIT_CRITICAL();
    //退出中斷沿
    OS_Sched();                                
    //如果當(dāng)前任務(wù)不處于就緒態(tài)將進(jìn)行任務(wù)調(diào)度將優(yōu)先級(jí)最高的任務(wù)調(diào)入運(yùn)行態(tài)
    OS_ENTER_CRITICAL();
    //進(jìn)入中斷沿
    //對(duì)當(dāng)前最高優(yōu)先級(jí)的事件進(jìn)行狀態(tài)判斷(下一個(gè)任務(wù)或還是之前的任務(wù))
    switch (OSTCBCur->OSTCBStatPend) {        
        case OS_STAT_PEND_OK:                  //等待完成和等待終止都進(jìn)行相同處理
        case OS_STAT_PEND_ABORT:
             pevent = OSTCBCur->OSTCBEventPtr;
             if (pevent != (OS_EVENT *)0) {    
                //有任務(wù)就緒了
                *pevents_rdy++ =  pevent;      
                //把這個(gè)任務(wù)的地址存儲(chǔ)到pevents_rdy數(shù)組中
                *pevents_rdy   = (OS_EVENT *)0;
                //最后一個(gè)標(biāo)志為結(jié)束符
                  events_rdy_nbr++;
                //就緒事件數(shù)加1
             } else {                            
                 OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO;
                //如果沒有任務(wù)就緒標(biāo)志為超時(shí)處理,這里不明白########
                 OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);
                //解除暫停將任務(wù)從等待列表中刪除
             }
             break;
 
        case OS_STAT_PEND_TO:                  
        default:                              
             OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);//掛起時(shí)間到將任務(wù)從等待列表中刪除
             break;
    }
    //這個(gè)switch是用來消息傳遞的  
    switch (OSTCBCur->OSTCBStatPend) {
        case OS_STAT_PEND_OK:                   //掛起完成也標(biāo)志該事件又處在就緒態(tài)了
             switch (pevent->OSEventType) {    
#if (OS_SEM_EN > 0u)
                 case OS_EVENT_TYPE_SEM:
                     *pmsgs_rdy++ = (void *)0;  
                    //信號(hào)量沒有返回消息
                      break;
#endif
 
#if ((OS_MBOX_EN > 0u) ||((OS_Q_EN    > 0u) && (OS_MAX_QS > 0u)))
                 case OS_EVENT_TYPE_MBOX:
                 case OS_EVENT_TYPE_Q:
                     *pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg;
                      break;                   //把郵箱和隊(duì)列中的消息保存在pmsgs_rdy數(shù)組中
#endif
 
                 case OS_EVENT_TYPE_MUTEX:
                 case OS_EVENT_TYPE_FLAG:
                 default:
                      OS_EXIT_CRITICAL();
                     *pevents_rdy = (OS_EVENT *)0;
                     *perr        =  OS_ERR_EVENT_TYPE;
                      return (events_rdy_nbr);
             }
            *perr = OS_ERR_NONE;
             break;
 
        case OS_STAT_PEND_ABORT:              //等待終止返回空消息
            *pmsgs_rdy++ = (void *)0;        
            *perr        =  OS_ERR_PEND_ABORT;
             break;
 
        case OS_STAT_PEND_TO:                 //等待超時(shí)也返回空消息                  
        default:
            *pmsgs_rdy++ = (void *)0;          
            *perr        =  OS_ERR_TIMEOUT;    
             break;
    }
 
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY;
//事件標(biāo)記為就緒態(tài)
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;
//清除掛起標(biāo)志
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#if ((OS_MBOX_EN > 0u) ||((OS_Q_EN    > 0u) && (OS_MAX_QS > 0u)))
    OSTCBCur->OSTCBMsg      = (void      *)0;  
#endif
    OS_EXIT_CRITICAL();
 
    return (events_rdy_nbr);
}
#endif
關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 91精品久久久久久久久久入口 | 波多野结衣先锋影音 | 91精品一区二区 | 天天干天天爱天天爽 | 成人在线中文字幕 | 久久人人爽人人爽 | 黄网址在线观看 | 91免费看片 | 精品久久久久久红码专区 | 国产黄色小视频在线观看 | 久久久久久久久一区 | 久久51| 日韩视频 中文字幕 | 亚洲狠狠丁香婷婷综合久久久 | 色女人天堂| 欧美xxxx日本 | 91亚洲国产成人精品一区二三 | 妖精视频一区二区三区 | 国产精品一区在线观看你懂的 | 精品一区在线 | 日本一区二区三区四区 | 国产在线观 | 久久亚洲精品久久国产一区二区 | 成人免费黄色 | 日韩在线免费播放 | 国产精品久久国产精品 | 日韩一级 | 欧美一级欧美一级在线播放 | 中文字幕免费在线观看 | 欧美一区二区 | 精品久久久久久亚洲综合网站 | 日韩精品人成在线播放 | 国产精品九九九 | 日本三级精品 | 国产精品99精品久久免费 | 亚洲国产成人精品久久久国产成人一区 | 日皮视频免费 | 国产精品视频二区三区 | 欧美午夜精品久久久久久浪潮 | 视频在线一区二区 | 国产传媒毛片精品视频第一次 |