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