LiteOS-任務篇-原始碼分析-建立任務函式
阿新 • • 發佈:2020-10-09
目錄
巨集
任務控制塊
前言
- 20201009
- LiteOS 2018
- 需要會通用連結串列
連結
- LiteOS原始碼連結
- 常見問題
- 華為開發者社群
- 華為LiteOS官方教程
- 我的原始碼
- 包含 裸機原始碼
- LiteOS 工程模板
- 其它關於 LiteOS 的 demo 及 note
參考
- 上面連結
筆錄草稿
部分原始碼分析
原始碼分析
LOS_TaskCreate
函式
- 需要一個 任務初始化引數結構體
TSK_INIT_PARAM_S
和 一個任務控制代碼。 - TSK_INIT_PARAM_S 原始碼
/** * @ingroup los_task * Define the structure of the parameters used for task creation. * * Information of specified parameters passed in during task creation. */ typedef struct tagTskInitParam { TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */ UINT16 usTaskPrio; /**< Task priority */ UINT32 uwArg; /**< Task parameters */ UINT32 uwStackSize; /**< Task stack size */ CHAR *pcName; /**< Task name */ UINT32 uwResved; /**< Reserved */ } TSK_INIT_PARAM_S;
- LOS_TaskCreate 函式原始碼
- 內含解讀
/***************************************************************************** Function : LOS_TaskCreate Description : Create a task Input : pstInitParam --- Task init parameters Output : puwTaskID --- Save task ID Return : LOS_OK on success or error code on failure *****************************************************************************/ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *puwTaskID, TSK_INIT_PARAM_S *pstInitParam) { UINT32 uwRet = LOS_OK; UINTPTR uvIntSave; LOS_TASK_CB *pstTaskCB; // 定義一個任務控制塊 uwRet = LOS_TaskCreateOnly(puwTaskID, pstInitParam); // 以掛起的方式建立一個新的任務(即是阻塞態) if (LOS_OK != uwRet) { return uwRet; } pstTaskCB = OS_TCB_FROM_TID(*puwTaskID); // 通過任務 ID 獲取 TCB 控制代碼 uvIntSave = LOS_IntLock(); // 鎖任務 pstTaskCB->usTaskStatus &= (~OS_TASK_STATUS_SUSPEND); pstTaskCB->usTaskStatus |= OS_TASK_STATUS_READY; // 解除阻塞-->進入就緒 #if (LOSCFG_BASE_CORE_CPUP == YES) // CPU 利用率模組程式碼段 g_pstCpup[pstTaskCB->uwTaskID].uwID = pstTaskCB->uwTaskID; g_pstCpup[pstTaskCB->uwTaskID].usStatus = pstTaskCB->usTaskStatus; #endif osPriqueueEnqueue(&pstTaskCB->stPendList, pstTaskCB->usPriority); // 將該任務插入 優先順序佇列 ,即是 就緒列表 g_stLosTask.pstNewTask = LOS_DL_LIST_ENTRY(osPriqueueTop(), LOS_TASK_CB, stPendList); /*lint !e413*/ /* 找出已經建立的任務中最高優先順序、最先插入的 TCB */ /* 以下只是判斷是否需要排程而已 */ /* 如果系統開啟了排程,且,鎖任務關閉,則,進入二次判斷 */ if ((g_bTaskScheduled) && (g_usLosTaskLock == 0)) { /* 如果最高優先順序、最先插入的任務不在執行態,則進行排程 */ if (g_stLosTask.pstRunTask != g_stLosTask.pstNewTask) { if (LOS_CHECK_SCHEDULE) { (VOID)LOS_IntRestore(uvIntSave); osSchedule(); return LOS_OK; } } } /* 解鎖任務排程 */ (VOID)LOS_IntRestore(uvIntSave); return LOS_OK; }
LOS_TaskCreateOnly
函式
- g_stTskRecyleList
- 任務可回收連結串列
- g_stLosFreeTask
- 任務可用連結串列
/*****************************************************************************
Function : LOS_TaskCreateOnly
Description : Create a task and suspend
Input : pstInitParam --- Task init parameters
Output : puwTaskID --- Save task ID
Return : LOS_OK on success or error code on failure
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *puwTaskID, TSK_INIT_PARAM_S *pstInitParam)
{
UINT32 uwTaskID = 0;
UINTPTR uvIntSave;
VOID *pTopStack;
VOID *pStackPtr;
LOS_TASK_CB *pstTaskCB;
UINT32 uwErrRet = OS_ERROR;
/* 元素合法檢查 [start][A] */
if (NULL == puwTaskID)
{
return LOS_ERRNO_TSK_ID_INVALID;
}
if (NULL == pstInitParam)
{
return LOS_ERRNO_TSK_PTR_NULL;
}
if (NULL == pstInitParam->pcName)
{
return LOS_ERRNO_TSK_NAME_EMPTY;
}
if (NULL == pstInitParam->pfnTaskEntry)
{
return LOS_ERRNO_TSK_ENTRY_NULL;
}
if ((pstInitParam->usTaskPrio) > OS_TASK_PRIORITY_LOWEST)
{
return LOS_ERRNO_TSK_PRIOR_ERROR;
}
if (((pstInitParam->usTaskPrio) == OS_TASK_PRIORITY_LOWEST)
&& (pstInitParam->pfnTaskEntry != OS_IDLE_TASK_ENTRY))
{
return LOS_ERRNO_TSK_PRIOR_ERROR;
}
if (pstInitParam->uwStackSize > OS_SYS_MEM_SIZE)
{
return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
}
if (0 == pstInitParam->uwStackSize)
{
pstInitParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
}
pstInitParam->uwStackSize = ALIGN(pstInitParam->uwStackSize , 8);
if (pstInitParam->uwStackSize < LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE)
{
return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
}
/* 元素合法檢查 [end][A] */
uvIntSave = LOS_IntLock(); // 鎖任務
/* 處理任務可回收連結串列,釋放出可用任務空間 */
while (!LOS_ListEmpty(&g_stTskRecyleList))
{
pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); /*lint !e413*/ /* 獲取任務 可回收連結串列 中的 第一個 TCB。 *後面有原始碼分析* */
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); // 從該連結串列中刪除該節點
LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList); // 把該任塊放到 可用連結串列 中
(VOID)LOS_MemFree(m_aucSysMem0, (VOID *)pstTaskCB->uwTopOfStack); // 釋放該任務申請的任務棧空間
pstTaskCB->uwTopOfStack = (UINT32)NULL;// 初始化該任務塊棧頂指標
}
/* 判斷是否還有可用任務塊使用,若沒有,則,退出 */
if (LOS_ListEmpty(&g_stLosFreeTask))
{
uwErrRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
OS_GOTO_ERREND();
}
pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stLosFreeTask)); /*lint !e413*/ /* 獲取 可用連結串列 中第一個節點對應的 TCB。*後面有原始碼分析* */
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stLosFreeTask)); // 上面獲取後,便從 可用連結串列 中刪除該節點。
(VOID)LOS_IntRestore(uvIntSave); // 解鎖任務
uwTaskID = pstTaskCB->uwTaskID; // 獲取 ID
pTopStack = (VOID *)LOS_MemAllocAlign(m_aucSysMem0, pstInitParam->uwStackSize, 8); // 申請動態記憶體,8 位元組對齊
if (NULL == pTopStack) // 申請失敗
{
uvIntSave = LOS_IntLock();
LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList);
uwErrRet = LOS_ERRNO_TSK_NO_MEMORY;
OS_GOTO_ERREND();
}
/* 申請成功 */
/* 初始化 TCB */
pStackPtr = osTskStackInit(uwTaskID, pstInitParam->uwStackSize, pTopStack);
pstTaskCB->pStackPointer = pStackPtr;
pstTaskCB->uwArg = pstInitParam->uwArg;
pstTaskCB->uwTopOfStack = (UINT32)pTopStack;
pstTaskCB->uwStackSize = pstInitParam->uwStackSize;
pstTaskCB->pTaskSem = NULL;
pstTaskCB->pTaskMux = NULL;
pstTaskCB->usTaskStatus = OS_TASK_STATUS_SUSPEND;
pstTaskCB->usPriority = pstInitParam->usTaskPrio;
pstTaskCB->pfnTaskEntry = pstInitParam->pfnTaskEntry;
pstTaskCB->uwEvent.uwEventID = 0xFFFFFFFF;
pstTaskCB->uwEventMask = 0;
pstTaskCB->pcTaskName = pstInitParam->pcName;
pstTaskCB->puwMsg = NULL;
*puwTaskID = uwTaskID; /* 更新 ID,返回給上層 */
return LOS_OK; /* 建立成功 */
LOS_ERREND:
(VOID)LOS_IntRestore(uvIntSave);
return uwErrRet;
}
巨集 OS_TCB_FROM_PENDLIST
和 巨集 LOS_DL_LIST_FIRST
- OS_TCB_FROM_PENDLIST
- 獲取 連結因子 ptr 中所在的任務控制塊的首地址
- 意思就是:獲取某條 stPendList 連結串列 中 ptr 節點的 TCB控制代碼
/**
* @ingroup los_task
* @brief Obtain the pointer to a task control block.
* @par Description:
* This API is used to obtain the pointer to a task control block using a corresponding parameter.
* @param ptr [IN] Parameter used for obtaining the task control block.
* @retval Pointer to the task control block.
*/
#define OS_TCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY(ptr, LOS_TASK_CB, stPendList)
- LOS_DL_LIST_ENTRY
- 通用連結串列的演算法
- 獲取連結因子 item 所在的資料塊的首地址
/**
*@ingroup los_list
*@brief Obtain the pointer to a structure that contains a doubly linked list.
*@par Description:
*This API is used to obtain the pointer to a structure that contains a doubly linked list.
*@param item [IN] Current node's pointer to the next node.
*@param type [IN] Structure name.
*@param member [IN] Member name of the doubly linked list in the structure.
*@retval Pointer to the structure that contains the doubly linked list.
*/
#define LOS_DL_LIST_ENTRY(item, type, member) \
((type *)((char *)item - LOS_OFF_SET_OF(type, member))) \
- LOS_OFF_SET_OF
- 通用連結串列的演算法
- 算出 結構體首地址 到 成員 之間的便宜。
/**
*@ingroup los_list
*@brief Obtain the pointer to a doubly linked list in a structure.
*@par Description:
*This API is used to obtain the pointer to a doubly linked list in a structure.
*@param type [IN] Structure name.
*@param member [IN] Member name of the doubly linked list in the structure.
*@retval Pointer to the doubly linked list in the structure.
*/
#define LOS_OFF_SET_OF(type, member) ((long)&((type *)0)->member) /*lint -e(413) */
任務控制塊 LOS_TASK_CB
/**
* @ingroup los_task
* Define the task control block structure.
*/
typedef struct tagTaskCB
{
VOID *pStackPointer; /**< Task stack pointer */
UINT16 usTaskStatus;
UINT16 usPriority;
UINT32 uwStackSize; /**< Task stack size */
UINT32 uwTopOfStack; /**< Task stack top */
UINT32 uwTaskID; /**< Task ID */
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
VOID *pTaskSem; /**< Task-held semaphore */
VOID *pTaskMux; /**< Task-held mutex */
UINT32 uwArg; /**< Parameter */
CHAR *pcTaskName; /**< Task name */
LOS_DL_LIST stPendList;
LOS_DL_LIST stTimerList;
UINT32 uwIdxRollNum;
EVENT_CB_S uwEvent;
UINT32 uwEventMask; /**< Event mask */
UINT32 uwEventMode; /**< Event mode */
VOID *puwMsg; /**< Memory allocated to queues */
} LOS_TASK_CB;