在實際任務(wù)間的通信中,一個或多個任務(wù)發(fā)送一個信號量或者消息給另一個任務(wù)是比常見的,而一個任務(wù)給多個任務(wù)發(fā)送信號量和消息相對比較少。前面所講的信號量和消息隊列均是單獨的內(nèi)核對象,是獨立于任務(wù)存在的。這兩章要講述的任務(wù)信號量和任務(wù)消息隊列是
任務(wù)特有的屬性,緊緊依賴于一個特定任務(wù)。
   任務(wù)信號量和任務(wù)消息隊列分別與多值信號量和消息隊列非常相似,不同之處是,前者僅發(fā)布給一個特定任務(wù),而后者可以發(fā)布給多個任務(wù)。因此,前者的操作相對比較簡單,而且省時。如果任務(wù)信號量和任務(wù)消息隊列可以滿足設(shè)計需求,那么盡量不要使用普通多值信號量和消息隊列 
   任務(wù)信號量伴隨任務(wù)存在,只要創(chuàng)建了任務(wù),其任務(wù)信號量就是該任務(wù)的一個數(shù)據(jù)成員,任務(wù)信號量的數(shù)據(jù)成員被包含在任務(wù)控制塊里。 
OSTaskSemPost () 
  OSTaskSemPost () 函數(shù)用于給一個任務(wù)發(fā)布任務(wù)信號量。OSTaskSemPost () 函數(shù)的信息如下表所示。 
   OSTaskSemPost () 函數(shù)的定義也位于“os_task.c”:
  S_SEM_CTR  OSTaskSemPost (OS_TCB  *p_tcb,   
//目標(biāo)任務(wù)OS_OPT   opt,     
//選項OS_ERR  *p_err)   
//返回錯誤類型
{OS_SEM_CTR  ctr;CPU_TS      ts;#ifdef OS_SAFETY_CRITICAL               //如果使能(默認(rèn)禁用)了安全檢測if (p_err == (OS_ERR *)
0) {         
//如果 p_err 為空OS_SAFETY_CRITICAL_EXCEPTION(); 
//執(zhí)行安全檢測異常函數(shù)return ((OS_SEM_CTR)
0);         
//返回0(有錯誤),停止執(zhí)行
    }
#endif#if OS_CFG_ARG_CHK_EN > 0u                  
//如果使能(默認(rèn)使能)了參數(shù)檢測功能switch (opt) {                          
//根據(jù)選項分類處理case OS_OPT_POST_NONE:              
//如果選項在預(yù)期之內(nèi)case OS_OPT_POST_NO_SCHED:break;                         
//跳出default:                            
//如果選項超出預(yù)期*p_err =  OS_ERR_OPT_INVALID;   
//錯誤類型為“選項非法”return ((OS_SEM_CTR)
0u);       
//返回0(有錯誤),停止執(zhí)行
    }
#endifts = OS_TS_GET();                                      
//獲取時間戳#if OS_CFG_ISR_POST_DEFERRED_EN > 0u                       
//如果使能了中斷延遲發(fā)布if (OSIntNestingCtr > (OS_NESTING_CTR)
0) {             
//如果該函數(shù)是在中斷中被調(diào)用OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SIGNAL,  
//將該信號量發(fā)布到中斷消息隊列(
void      *
)p_tcb,(void      *)
0,(OS_MSG_SIZE)0,(OS_FLAGS   )0,(OS_OPT     )0,(CPU_TS     )ts,(OS_ERR    *
)p_err);return ((OS_SEM_CTR)
0);                           
//返回0(尚未發(fā)布)   
    }
#endifctr = OS_TaskSemPost(p_tcb,                          
//將信號量按照普通方式處理
                         opt,ts,p_err);return (ctr);                                       
//返回信號的當(dāng)前計數(shù)值
}  
OSTaskSemPost()   其實,不管是否使能了中斷延遲發(fā)布,最終都是調(diào)用 OS_TaskSemPost() 函數(shù)進(jìn)行發(fā)布信號量。只是使能了中斷延遲發(fā)布的發(fā)布過程會比較曲折,中間會有許多插曲,這是中斷管理范疇的內(nèi)容。
   OS_TaskSemPost() 函數(shù)的定義位于“os_task.c”:
  OS_SEM_CTR  OS_TaskSemPost (OS_TCB  *p_tcb,   
//目標(biāo)任務(wù)OS_OPT   opt,     
//選項CPU_TS   ts,      
//時間戳OS_ERR  *p_err)   
//返回錯誤類型
{OS_SEM_CTR  ctr;CPU_SR_ALLOC(); //使用到臨界段(在關(guān)/開中斷時)時必需該宏,該宏聲明和//定義一個局部變量,用于保存關(guān)中斷前的 CPU 狀態(tài)寄存器// SR(臨界段關(guān)中斷只需保存SR),開中斷時將該值還原。
OS_CRITICAL_ENTER();                               //進(jìn)入臨界段if (p_tcb == (OS_TCB *)
0) {                        
//如果 p_tcb 為空p_tcb = OSTCBCurPtr;                           
//將任務(wù)信號量發(fā)給自己(任務(wù))
    }p_tcb->TS = ts;                                    
//記錄信號量被發(fā)布的時間戳*p_err     = OS_ERR_NONE;                           
//錯誤類型為“無錯誤”switch (p_tcb->TaskState) {                        
//跟吳目標(biāo)任務(wù)的任務(wù)狀態(tài)分類處理case OS_TASK_STATE_RDY:                        
//如果目標(biāo)任務(wù)沒有等待狀態(tài)case OS_TASK_STATE_DLY:case OS_TASK_STATE_SUSPENDED:case OS_TASK_STATE_DLY_SUSPENDED:switch (
sizeof(OS_SEM_CTR)) {                        
//判斷是否將導(dǎo)致該信case 1u:                                         
//號量計數(shù)值溢出,如if (p_tcb->SemCtr == DEF_INT_08U_MAX_VAL) { 
//果溢出,則開中斷,OS_CRITICAL_EXIT();                     
//返回錯誤類型為“計*p_err = OS_ERR_SEM_OVF;                 
//數(shù)值溢出”,返回0return ((OS_SEM_CTR)
0);                 
//(有錯誤),不繼續(xù)}                                           
//執(zhí)行。break;                                      case 2u:if (p_tcb->SemCtr ==
 DEF_INT_16U_MAX_VAL) {OS_CRITICAL_EXIT();*p_err =
 OS_ERR_SEM_OVF;return ((OS_SEM_CTR)
0);}break;case 4u:if (p_tcb->SemCtr ==
 DEF_INT_32U_MAX_VAL) {OS_CRITICAL_EXIT();*p_err =
 OS_ERR_SEM_OVF;return ((OS_SEM_CTR)
0);}break;default:break;}p_tcb->SemCtr++;                              
//信號量計數(shù)值不溢出則加1ctr = p_tcb->SemCtr;                          
//獲取信號量的當(dāng)前計數(shù)值OS_CRITICAL_EXIT();                           
//退出臨界段break;                                        
//跳出case OS_TASK_STATE_PEND:                           
//如果任務(wù)有等待狀態(tài)case OS_TASK_STATE_PEND_TIMEOUT:case OS_TASK_STATE_PEND_SUSPENDED:case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:if (p_tcb->PendOn == OS_TASK_PEND_ON_TASK_SEM) { 
//如果正等待任務(wù)信號量OS_Post((OS_PEND_OBJ *)
0,                    
//發(fā)布信號量給目標(biāo)任務(wù)(OS_TCB      *
)p_tcb,(void        *)
0,(OS_MSG_SIZE  )0u,(CPU_TS       )ts);ctr = p_tcb->SemCtr;                         
//獲取信號量的當(dāng)前計數(shù)值OS_CRITICAL_EXIT_NO_SCHED();                 
//退出臨界段(無調(diào)度)if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)
0) { 
//如果選擇了調(diào)度任務(wù)OSSched();                               
//調(diào)度任務(wù)
                 }} else {                                         
//如果沒等待任務(wù)信號量switch (
sizeof(OS_SEM_CTR)) {                         
//判斷是否將導(dǎo)致case 1u:                                          
//該信號量計數(shù)值if (p_tcb->SemCtr == DEF_INT_08U_MAX_VAL) {  
//溢出,如果溢出,OS_CRITICAL_EXIT();                      
//則開中斷,返回*p_err = OS_ERR_SEM_OVF;                  
//錯誤類型為“計return ((OS_SEM_CTR)
0);                  
//數(shù)值溢出”,返}                                            
//回0(有錯誤),break;                                       
//不繼續(xù)執(zhí)行。case 2u:if (p_tcb->SemCtr ==
 DEF_INT_16U_MAX_VAL) {OS_CRITICAL_EXIT();*p_err =
 OS_ERR_SEM_OVF;return ((OS_SEM_CTR)
0);}break;case 4u:if (p_tcb->SemCtr ==
 DEF_INT_32U_MAX_VAL) {OS_CRITICAL_EXIT();*p_err =
 OS_ERR_SEM_OVF;return ((OS_SEM_CTR)
0);}break;default:break;}p_tcb->SemCtr++;                            
//信號量計數(shù)值不溢出則加1ctr = p_tcb->SemCtr;                        
//獲取信號量的當(dāng)前計數(shù)值OS_CRITICAL_EXIT();                         
//退出臨界段
             }break;                                          
//跳出default:                                             
//如果任務(wù)狀態(tài)超出預(yù)期OS_CRITICAL_EXIT();                             
//退出臨界段*p_err = OS_ERR_STATE_INVALID;                   
//錯誤類型為“狀態(tài)非法”ctr   = (OS_SEM_CTR)
0;                          
//清零 ctrbreak;                                          
//跳出
    }return (ctr);                                            
//返回信號量的當(dāng)前計數(shù)值
}  
OS_TaskSemPost()   在 OS_SemPost() 函數(shù)中,又會調(diào)用 OS_Post() 函數(shù)發(fā)布內(nèi)核對象。OS_Post() 函數(shù)是一個底層的發(fā)布函數(shù),它不僅僅用來發(fā)布任務(wù)信號量,還可以發(fā)布多值信號量、互斥信號量、消息隊列、事件標(biāo)志組或任務(wù)消息隊列。注意,在這里,OS_Post() 函數(shù)將任務(wù)信號量直接發(fā)布給目標(biāo)任務(wù)。
   OS_Post() 函數(shù)的定義位于“os_core.c”。:
  void  OS_Post (OS_PEND_OBJ  *p_obj,     
//內(nèi)核對象類型指針OS_TCB       *p_tcb,     
//任務(wù)控制塊void         *p_void,    
//消息OS_MSG_SIZE   msg_size,  
//消息大小CPU_TS        ts)        
//時間戳
{switch (p_tcb->TaskState) {                               
//根據(jù)任務(wù)狀態(tài)分類處理case OS_TASK_STATE_RDY:                               
//如果任務(wù)處于就緒狀態(tài)case OS_TASK_STATE_DLY:                               
//如果任務(wù)處于延時狀態(tài)case OS_TASK_STATE_SUSPENDED:                         
//如果任務(wù)處于掛起狀態(tài)case OS_TASK_STATE_DLY_SUSPENDED:                     
//如果任務(wù)處于延時中被掛起狀態(tài)break;                                           
//不用處理,直接跳出case OS_TASK_STATE_PEND:                              
//如果任務(wù)處于無期限等待狀態(tài)case OS_TASK_STATE_PEND_TIMEOUT:                      
//如果任務(wù)處于有期限等待狀態(tài)if (p_tcb->PendOn == OS_TASK_PEND_ON_MULTI) {    
//如果任務(wù)在等待多個信號量或消息隊列OS_Post1(p_obj,                              
//標(biāo)記哪個內(nèi)核對象被發(fā)布
                          p_tcb,p_void,msg_size,ts);} else {                                         
//如果任務(wù)不是在等待多個信號量或消息隊列
#if (OS_MSG_EN > 0u)                                          
//如果使能了任務(wù)隊列或消息隊列p_tcb->MsgPtr  = p_void;                     
//保存消息到等待任務(wù)p_tcb->MsgSize =
 msg_size;                   
#endifp_tcb->TS      = ts;                         
//保存時間戳到等待任務(wù)
             }if (p_obj != (OS_PEND_OBJ *)
0) {                 
//如果內(nèi)核對象為空OS_PendListRemove(p_tcb);                    
//從等待列表移除該等待任務(wù)
#if OS_CFG_DBG_EN > 0u                                        
//如果使能了調(diào)試代碼和變量 OS_PendDbgNameRemove(p_obj,                  //移除內(nèi)核對象的調(diào)試名
                                      p_tcb);
#endif}OS_TaskRdy(p_tcb);                               //讓該等待任務(wù)準(zhǔn)備運行p_tcb->TaskState  = OS_TASK_STATE_RDY;           
//任務(wù)狀態(tài)改為就緒狀態(tài)p_tcb->PendStatus = OS_STATUS_PEND_OK;           
//清除等待狀態(tài)p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;     
//標(biāo)記不再等待break;case OS_TASK_STATE_PEND_SUSPENDED:                    
//如果任務(wù)在無期限等待中被掛起case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:            
//如果任務(wù)在有期限等待中被掛起if (p_tcb->PendOn == OS_TASK_PEND_ON_MULTI) {    
//如果任務(wù)在等待多個信號量或消息隊列OS_Post1(p_obj,                              
//標(biāo)記哪個內(nèi)核對象被發(fā)布
                          p_tcb,p_void,msg_size,ts);} else {                                         
//如果任務(wù)不在等待多個信號量或消息隊列
#if (OS_MSG_EN > 0u)                                          
//如果使能了調(diào)試代碼和變量p_tcb->MsgPtr  = p_void;                     
//保存消息到等待任務(wù)p_tcb->MsgSize =
 msg_size;                     
#endifp_tcb->TS      = ts;                         
//保存時間戳到等待任務(wù)
             }OS_TickListRemove(p_tcb);                        //從節(jié)拍列表移除該等待任務(wù)if (p_obj != (OS_PEND_OBJ *)
0) {                 
//如果內(nèi)核對象為空OS_PendListRemove(p_tcb);                    
//從等待列表移除該等待任務(wù)
#if OS_CFG_DBG_EN > 0u                                        
//如果使能了調(diào)試代碼和變量 OS_PendDbgNameRemove(p_obj,                  //移除內(nèi)核對象的調(diào)試名
                                      p_tcb);
#endif}p_tcb->TaskState  = OS_TASK_STATE_SUSPENDED;     
//任務(wù)狀態(tài)改為被掛起狀態(tài)p_tcb->PendStatus = OS_STATUS_PEND_OK;           
//清除等待狀態(tài)p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;     
//標(biāo)記不再等待break;default:                                              
//如果任務(wù)狀態(tài)超出預(yù)期break;                                           
//直接跳出
    }
}  OS_Post() OSTaskSemPend ()?
   與 OSSemPost () 多值信號量發(fā)布函數(shù)相對應(yīng),OSTaskSemPend () 函數(shù)用于等待任務(wù)信號量。 
 
   OSTaskSemPend () 函數(shù)的定義也位于“os_task.c:
  OS_SEM_CTR  OSTaskSemPend (OS_TICK   timeout,  
//等待超時時間OS_OPT    opt,      
//選項CPU_TS   *p_ts,     
//返回時間戳OS_ERR   *p_err)    
//返回錯誤類型
{OS_SEM_CTR    ctr;CPU_SR_ALLOC(); //使用到臨界段(在關(guān)/開中斷時)時必需該宏,該宏聲明和//定義一個局部變量,用于保存關(guān)中斷前的 CPU 狀態(tài)寄存器// SR(臨界段關(guān)中斷只需保存SR),開中斷時將該值還原。
#ifdef OS_SAFETY_CRITICAL                //如果使能了安全檢測if (p_err == (OS_ERR *)
0) {          
//如果錯誤類型實參為空OS_SAFETY_CRITICAL_EXCEPTION();  
//執(zhí)行安全檢測異常函數(shù)return ((OS_SEM_CTR)
0);          
//返回0(有錯誤),停止執(zhí)行
    }
#endif#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u          
//如果使能了中斷中非法調(diào)用檢測if (OSIntNestingCtr > (OS_NESTING_CTR)
0) {  
//如果該函數(shù)在中斷中被調(diào)用*p_err = OS_ERR_PEND_ISR;                
//返回錯誤類型為“在中斷中等待”return ((OS_SEM_CTR)
0);                 
//返回0(有錯誤),停止執(zhí)行
    }
#endif#if OS_CFG_ARG_CHK_EN > 0u                  
//如果使能了參數(shù)檢測switch (opt) {                          
//根據(jù)選項分類處理case OS_OPT_PEND_BLOCKING:          
//如果選項在預(yù)期內(nèi)case OS_OPT_PEND_NON_BLOCKING:break;                         
//直接跳出default:                            
//如果選項超出預(yù)期*p_err = OS_ERR_OPT_INVALID;    
//錯誤類型為“選項非法”return ((OS_SEM_CTR)
0);        
//返回0(有錯誤),停止執(zhí)行
    }
#endifif (p_ts != (CPU_TS *)
0) {      
//如果 p_ts 非空*p_ts  = (CPU_TS  )
0;        
//清零(初始化)p_ts
    }CPU_CRITICAL_ENTER();                        //關(guān)中斷  if (OSTCBCurPtr->SemCtr > (OS_SEM_CTR)
0) {   
//如果任務(wù)信號量當(dāng)前可用OSTCBCurPtr->SemCtr--;                   
//信號量計數(shù)器減1ctr    = OSTCBCurPtr->SemCtr;            
//獲取信號量的當(dāng)前計數(shù)值if (p_ts != (CPU_TS *)
0) {               
//如果 p_ts 非空*p_ts  = OSTCBCurPtr->TS;             
//返回信號量被發(fā)布的時間戳
        }
#if OS_CFG_TASK_PROFILE_EN > 0u                  
//如果使能了任務(wù)控制塊的簡況變量OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->TS;     
//更新任務(wù)等待if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->SemPendTime) { 
//任務(wù)信號量的OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->SemPendTime;   
//最長時間記錄。
        }
#endifCPU_CRITICAL_EXIT();                     //開中斷            *p_err = OS_ERR_NONE;                     
//錯誤類型為“無錯誤”return (ctr);                            
//返回信號量的當(dāng)前計數(shù)值
    }/* 如果任務(wù)信號量當(dāng)前不可用 */if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)
0) {  
//如果選擇了不阻塞任務(wù)CPU_CRITICAL_EXIT();                              
//開中斷*p_err = OS_ERR_PEND_WOULD_BLOCK;                  
//錯誤類型為“缺乏阻塞”return ((OS_SEM_CTR)
0);                           
//返回0(有錯誤),停止執(zhí)行} 
else {                                              
//如果選擇了阻塞任務(wù)if (OSSchedLockNestingCtr > (OS_NESTING_CTR)
0) {  
//如果調(diào)度器被鎖CPU_CRITICAL_EXIT();                          
//開中斷*p_err = OS_ERR_SCHED_LOCKED;                  
//錯誤類型為“調(diào)度器被鎖”return ((OS_SEM_CTR)
0);                       
//返回0(有錯誤),停止執(zhí)行
        }}/* 如果調(diào)度器未被鎖 */OS_CRITICAL_ENTER_CPU_EXIT();                         //鎖調(diào)度器,重開中斷                      OS_Pend((OS_PEND_DATA *)
0,                            
//阻塞任務(wù),等待信號量。(OS_PEND_OBJ  *)
0,                            
//不需插入等待列表。
            (OS_STATE      )OS_TASK_PEND_ON_TASK_SEM,(OS_TICK       )timeout);OS_CRITICAL_EXIT_NO_SCHED();                          //開調(diào)度器(無調(diào)度)
OSSched();                                            //調(diào)度任務(wù)/* 任務(wù)獲得信號量后得以繼續(xù)運行 */CPU_CRITICAL_ENTER();                                 //關(guān)中斷switch (OSTCBCurPtr->PendStatus) {                    
//根據(jù)任務(wù)的等待狀態(tài)分類處理case OS_STATUS_PEND_OK:                           
//如果任務(wù)成功獲得信號量if (p_ts != (CPU_TS *)
0) {                   
//返回信號量被發(fā)布的時間戳*p_ts                    =  OSTCBCurPtr->
TS;
#if OS_CFG_TASK_PROFILE_EN > 0u                           
//更新最長等待時間記錄OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->
TS;if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->
SemPendTime) {OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->
SemPendTime;}
#endif}*p_err = OS_ERR_NONE;                         
//錯誤類型為“無錯誤”break;                                       
//跳出case OS_STATUS_PEND_ABORT:                        
//如果等待被中止if (p_ts != (CPU_TS *)
0) {                   
//返回被終止時的時間戳*p_ts  =  OSTCBCurPtr->
TS;}*p_err = OS_ERR_PEND_ABORT;                   
//錯誤類型為“等待被中止”break;                                       
//跳出case OS_STATUS_PEND_TIMEOUT:                      
//如果等待超時if (p_ts != (CPU_TS *)
0) {                   
//返回時間戳為0*p_ts  = (CPU_TS  )
0;}*p_err = OS_ERR_TIMEOUT;                      
//錯誤類型為“等待超時”break;                                       
//跳出default:                                          
//如果等待狀態(tài)超出預(yù)期*p_err = OS_ERR_STATUS_INVALID;               
//錯誤類型為“狀態(tài)非法”break;                                       
//跳出
    }                                                     ctr = OSTCBCurPtr->SemCtr;                            
//獲取信號量的當(dāng)前計數(shù)值CPU_CRITICAL_EXIT();                                  
//開中斷return (ctr);                                         
//返回信號量的當(dāng)前計數(shù)值
}  
OSTaskSemPend()   當(dāng)需要阻塞任務(wù),等待任務(wù)信號量時,OSTaskSemPend () 函數(shù)會調(diào)用一個更加底層的等待函數(shù)來執(zhí)行當(dāng)前任務(wù)對多值信號量的等待,該函數(shù)就是 OS_Pend()。與 OS_Post() 函數(shù)一樣,OS_Pend() 函數(shù)不僅僅用來等待任務(wù)信號量,還可以等待多值信號量、互斥信號量、消息隊列、事件標(biāo)志組或任務(wù)消息隊列。注意,在這里,OS_Pend()函數(shù)并沒有把當(dāng)前任務(wù)插入到等待列表。
   OS_Pend() 函數(shù)的定義位于“os_core.c”:
  void  OS_Pend (OS_PEND_DATA  *p_pend_data,  
//待插入等待列表的元素OS_PEND_OBJ   *p_obj,        
//等待的內(nèi)核對象OS_STATE       pending_on,   
//等待哪種對象內(nèi)核OS_TICK        timeout)      
//等待期限
{OS_PEND_LIST  *
p_pend_list;OSTCBCurPtr->PendOn     = pending_on;                    
//資源不可用,開始等待OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;             
//正常等待中
OS_TaskBlock(OSTCBCurPtr,                                //阻塞當(dāng)前運行任務(wù),timeout);                                   
//如果 timeout 非0,把任務(wù)插入的節(jié)拍列表if (p_obj != (OS_PEND_OBJ *)
0) {                         
//如果等待對象非空p_pend_list             = &p_obj->PendList;          
//獲取對象的等待列表到 p_pend_listp_pend_data->PendObjPtr = p_obj;                     
//保存要等待的對象OS_PendDataInit((OS_TCB       *)OSTCBCurPtr,         
//初始化 p_pend_data(待插入等待列表)(OS_PEND_DATA *
)p_pend_data,(OS_OBJ_QTY    )1);OS_PendListInsertPrio(p_pend_list,                   //按優(yōu)先級將 p_pend_data 插入到等待列表
                              p_pend_data);} else {                                                 
//如果等待對象為空OSTCBCurPtr->PendDataTblEntries = (OS_OBJ_QTY    )
0; 
//清零當(dāng)前任務(wù)的等待域數(shù)據(jù)OSTCBCurPtr->PendDataTblPtr     = (OS_PEND_DATA *)
0; }
#if OS_CFG_DBG_EN > 0u                                       
//如果使能了調(diào)試代碼和變量 OS_PendDbgNameAdd(p_obj,                                 //更新信號量的 DbgNamePtr 元素為其等待OSTCBCurPtr);                          
//列表中優(yōu)先級最高的任務(wù)的名稱。
#endif
}  OS_Pend() OSTaskSemPendAbort ()?
   OSTaskSemPendAbort() 函數(shù)用于中止一個任務(wù)對其任務(wù)信號量的等待。要使用OSTaskSemPendAbort() 函數(shù),還得事先使能 OS_CFG_TASK_SEM_PEND_ABORT_EN(位于“os_cfg.h”) 
  #define OS_CFG_TASK_SEM_PEND_ABORT_EN   1u   
//使能/禁用函數(shù) OSTaskSemPendAbort()    OSTaskSemPendAbort() 函數(shù)的信息如下表所示。 
 
    OSTaskSemPendAbort() 函數(shù)的定義位于“os_task.c”:
  #if OS_CFG_TASK_SEM_PEND_ABORT_EN > 0u  
//如果使能了 OSTaskSemPendAbort()
CPU_BOOLEAN  OSTaskSemPendAbort (OS_TCB  *p_tcb, 
//目標(biāo)任務(wù)OS_OPT   opt,   
//選項OS_ERR  *p_err) 
//返回錯誤類型
{CPU_TS         ts;CPU_SR_ALLOC(); //使用到臨界段(在關(guān)/開中斷時)時必需該宏,該宏聲明和//定義一個局部變量,用于保存關(guān)中斷前的 CPU 狀態(tài)寄存器// SR(臨界段關(guān)中斷只需保存SR),開中斷時將該值還原。
#ifdef OS_SAFETY_CRITICAL               //如果使能了安全檢測if (p_err == (OS_ERR *)
0) {         
//如果錯誤類型實參為空OS_SAFETY_CRITICAL_EXCEPTION(); 
//執(zhí)行安全檢測異常函數(shù)return (DEF_FALSE);             
//返回(失敗),停止執(zhí)行
    }
#endif#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u           
//如果使能了中斷中非法調(diào)用檢測if (OSIntNestingCtr > (OS_NESTING_CTR)
0) {   
//如果該函數(shù)是在中斷中被調(diào)用*p_err = OS_ERR_PEND_ABORT_ISR;           
//錯誤類型為“在中斷中創(chuàng)建對象”return (DEF_FALSE);                      
//返回(失敗),停止執(zhí)行
    }
#endif#if OS_CFG_ARG_CHK_EN > 0u                  
//如果使能了參數(shù)檢測switch (opt) {                          
//根據(jù)選項匪類處理case OS_OPT_POST_NONE:              
//如果選項在預(yù)期內(nèi)case OS_OPT_POST_NO_SCHED:break;                         
//直接跳出default:                            
//如果選項超出預(yù)期*p_err =  OS_ERR_OPT_INVALID;   
//錯誤類型為“選項非法”return (DEF_FALSE);            
//返回(失敗),停止執(zhí)行
    }
#endifCPU_CRITICAL_ENTER();                 //關(guān)中斷if ((p_tcb == (OS_TCB *)
0) ||         
//如果 p_tcb 為空,或者(p_tcb == OSTCBCurPtr)) {         
//p_tcb 指向當(dāng)前運行任務(wù)。CPU_CRITICAL_EXIT();              
//開中斷*p_err = OS_ERR_PEND_ABORT_SELF;   
//錯誤類型為“中止自身”return (DEF_FALSE);               
//返回(失敗),停止執(zhí)行
    }/* 如果 p_tcb (目標(biāo)任務(wù)) 不是當(dāng)前運行任務(wù)(自身) */if (p_tcb->PendOn != OS_TASK_PEND_ON_TASK_SEM) { 
//如果目標(biāo)任務(wù)沒在等待任務(wù)信號量CPU_CRITICAL_EXIT();                         
//開中斷*p_err = OS_ERR_PEND_ABORT_NONE;              
//錯誤類型為“沒在等待任務(wù)信號量”return (DEF_FALSE);                          
//返回(失敗),停止執(zhí)行
    }CPU_CRITICAL_EXIT();                             //開中斷
OS_CRITICAL_ENTER();                             //進(jìn)入臨界段ts = OS_TS_GET();                                
//獲取時間戳OS_PendAbort((OS_PEND_OBJ *)
0,                   
//中止目標(biāo)任務(wù)對信號量的等待
                 p_tcb, ts);OS_CRITICAL_EXIT_NO_SCHED();                     //退出臨界段(無調(diào)度)if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)
0) { 
//如果選擇了任務(wù)調(diào)度OSSched();                                   
//調(diào)度任務(wù)
    }*p_err = OS_ERR_NONE;                             
//錯誤類型為“無錯誤”return (DEF_TRUE);                               
//返回(中止成功)
}
#endif  OSTaskSemPendAbort()   OSTaskSemPendAbort() 函數(shù)會調(diào)用一個更加底層的中止等待函數(shù)來執(zhí)行當(dāng)前任務(wù)對多值信號量的等待,該函數(shù)就是 OS_PendAbort()。OS_PendAbort() 函數(shù)不僅僅用來中止對任務(wù)信號量的等待,還可以中止對多值信號量、互斥信號量、消息隊列、事件標(biāo)志組或任務(wù)消息隊列的等待。
   OS_PendAbort() 函數(shù)的定義位于“os_core.c”:
  void  OS_PendAbort (OS_PEND_OBJ  *p_obj,   
//被等待對象的類型OS_TCB       *p_tcb,   
//任務(wù)控制塊指針CPU_TS        ts)      
//等待被中止時的時間戳
{switch (p_tcb->TaskState) {                             
//根據(jù)任務(wù)狀態(tài)分類處理                    case OS_TASK_STATE_RDY:                             
//如果任務(wù)是就緒狀態(tài)case OS_TASK_STATE_DLY:                             
//如果任務(wù)是延時狀態(tài)case OS_TASK_STATE_SUSPENDED:                       
//如果任務(wù)是掛起狀態(tài)case OS_TASK_STATE_DLY_SUSPENDED:                   
//如果任務(wù)是在延時中被掛起break;                                         
//這些情況均與等待無關(guān),直接跳出case OS_TASK_STATE_PEND:                            
//如果任務(wù)是無期限等待狀態(tài)case OS_TASK_STATE_PEND_TIMEOUT:                    
//如果任務(wù)是有期限等待狀態(tài)if (p_tcb->PendOn == OS_TASK_PEND_ON_MULTI) {  
//如果任務(wù)在等待多個信號量或消息隊列OS_PendAbort1(p_obj,                       
//強制解除任務(wù)對某一對象的等待
                               p_tcb,ts);}
#if (OS_MSG_EN > 0u)                                
//如果使能了任務(wù)隊列或消息隊列p_tcb->MsgPtr     = (
void      *)
0;    
//清除(復(fù)位)任務(wù)的消息域p_tcb->MsgSize    = (OS_MSG_SIZE)
0u;
#endifp_tcb->TS         = ts;                        
//保存等待被中止時的時間戳到任務(wù)控制塊if (p_obj != (OS_PEND_OBJ *)
0) {               
//如果等待對象非空OS_PendListRemove(p_tcb);                  
//將任務(wù)從所有等待列表中移除
             }OS_TaskRdy(p_tcb);                             //讓任務(wù)進(jìn)準(zhǔn)備運行p_tcb->TaskState  = OS_TASK_STATE_RDY;         
//修改任務(wù)狀態(tài)為就緒狀態(tài)p_tcb->PendStatus = OS_STATUS_PEND_ABORT;      
//標(biāo)記任務(wù)的等待被中止p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;   
//標(biāo)記任務(wù)目前沒有等待任何對象break;                                         
//跳出case OS_TASK_STATE_PEND_SUSPENDED:                  
//如果任務(wù)在無期限等待中被掛起case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:          
//如果任務(wù)在有期限等待中被掛起if (p_tcb->PendOn == OS_TASK_PEND_ON_MULTI) {  
//如果任務(wù)在等待多個信號量或消息隊列OS_PendAbort1(p_obj,                       
//強制解除任務(wù)對某一對象的等待
                               p_tcb,ts);}
#if (OS_MSG_EN > 0u)                              
//如果使能了任務(wù)隊列或消息隊列p_tcb->MsgPtr     = (
void      *)
0;  
//清除(復(fù)位)任務(wù)的消息域p_tcb->MsgSize    = (OS_MSG_SIZE)
0u;
#endifp_tcb->TS         = ts;                        
//保存等待被中止時的時間戳到任務(wù)控制塊if (p_obj != (OS_PEND_OBJ *)
0) {               
//如果等待對象非空OS_PendListRemove(p_tcb);                  
//將任務(wù)從所有等待列表中移除
             }OS_TickListRemove(p_tcb);                      //讓任務(wù)脫離節(jié)拍列表p_tcb->TaskState  = OS_TASK_STATE_SUSPENDED;   
//修改任務(wù)狀態(tài)為掛起狀態(tài)p_tcb->PendStatus = OS_STATUS_PEND_ABORT;      
//標(biāo)記任務(wù)的等待被中止p_tcb->PendOn     = OS_TASK_PEND_ON_NOTHING;   
//標(biāo)記任務(wù)目前沒有等待任何對象break;                                         
//跳出default:                                            
//如果任務(wù)狀態(tài)超出預(yù)期break;                                         
//不需處理,直接跳出
    }
}  OS_PendAbort() ?
 ?
 
轉(zhuǎn)載于:https://www.cnblogs.com/tianxxl/p/10385933.html
                            總結(jié)
                            
                                以上是生活随笔為你收集整理的任务信号量的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。