zoukankan      html  css  js  c++  java
  • 【LiteOS】LiteOS任务篇源码分析创建任务函数


    前言

    • 20201009
    • LiteOS 2018
    • 需要会通用链表

    链接

    参考

    • 上面链接

    笔录草稿

    部分源码分析

    源码分析

    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;
    
  • 相关阅读:
    HDU 1016 Prime Ring Problem
    POJ 1724 ROADS(bfs最短路)
    HDU 1033 Edge
    IE 兼容模式
    HDU 1263 水果
    数据结构之图详解
    继续过中等难度.0309
    排序的稳定性
    Java+7入门经典
    哈希链表及其变种
  • 原文地址:https://www.cnblogs.com/lizhuming/p/13787459.html
Copyright © 2011-2022 走看看