玖叶教程网

前端编程开发入门

LiteOS内核源码分析系列六-任务调度LOS_Task-3

任务模块初始化

在系统启动时,在kernel\init\los_init.c中调用OsTaskInit()进行任务模块初始化,还会调用OsIdleTaskCreate()创建空闲任务。

2.1 任务模块初始化

函数OsTaskInit()定义在kernel\base\los_task.c,我们分析下这个函数的执行过程。

⑴处代码获取开发板配置的最大任务数g_taskMaxNum,计算需要申请的内存大小size,为任务控制块TCB数组(也叫作任务池)g_taskCBArray申请内存。为什么比最大任务数多申请一个呢?在删除任务时会使用。下文分析删除任务的源码时再详细讲解其用意。⑵处代码初始化双向链表g_losFreeTask用作空闲的任务链表、g_taskRecycleList可以回收的任务链表。⑶处循环初始化每一个任务,任务状态未使用OS_TASK_STATUS_UNUSED,初始化任务Id,并把任务挂在空闲任务链表上。⑷处初始化优先级队列,详细的代码实现剖析,参见之前的源码剖析文章。⑸处互斥锁死锁检测的调测特性的,后续系列文章专题进行讲解。⑹处代码初始化排序链表,详细的代码实现剖析,参见之前的源码剖析文章。⑺处如果开启了惰性栈,计算TCB的成员变量stackFrame在其结构体中的偏移量g_stackFrameOffLenInTcb

LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
{
    UINT32 index;
    UINT32 ret;
    UINT32 size;

⑴  g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;
    size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
    g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
    if (g_taskCBArray == NULL) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }
    (VOID)memset_s(g_taskCBArray, size, 0, size);

⑵  LOS_ListInit(&g_losFreeTask);
    LOS_ListInit(&g_taskRecycleList);
⑶  for (index = 0; index < g_taskMaxNum; index++) {
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
        g_taskCBArray[index].taskId = index;
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);
    }

⑷  ret = OsPriQueueInit();
    if (ret != LOS_OK) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }

⑸  ret = OsMuxDlockCheckInitHook();
    if (ret != LOS_OK) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }
⑹  for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
        ret = OsSortLinkInit(&g_percpu[index].taskSortLink);
        if (ret != LOS_OK) {
            return LOS_ERRNO_TSK_NO_MEMORY;
        }
    }

#ifdef LOSCFG_LAZY_STACK
⑺  g_stackFrameOffLenInTcb = (UINT16)LOS_OFF_SET_OF(LosTaskCB, stackFrame);
#endif

    return LOS_OK;
}

2.2 创建空闲任务IdleCore000

除了初始化任务池,在系统启动阶段还会创建idle空闲任务。⑴处设置任务初始化参数时,空闲任务的入口执行函数为OsIdleTask()。⑵处可以看出空闲任务标记为了系统级别的任务OS_TASK_FLAG_SYSTEM

LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
{
    UINT32 ret;
    TSK_INIT_PARAM_S taskInitParam;
    Percpu *perCpu = OsPercpuGet();
    UINT32 *idleTaskId = &perCpu->idleTaskId;

    (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
⑴  taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;
    taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;
    taskInitParam.pcName = "IdleCore000";
    taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
#ifdef LOSCFG_KERNEL_SMP
    taskInitParam.usCpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());
#endif
    ret = LOS_TaskCreate(idleTaskId, &taskInitParam);
    if (ret == LOS_OK) {
⑵      OS_TCB_FROM_TID(*idleTaskId)->taskFlags |= OS_TASK_FLAG_SYSTEM;
    }

    return ret;
}

我们看下空闲任务的入口执行函数为OsIdleTask(),它调用LOS_TaskResRecycle()回收任务栈资源,后文会分析如何回收任务指引。

LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
{
    while (1) {
        LOS_TaskResRecycle();

#ifdef LOSCFG_KERNEL_LOWPOWER
        if (g_lowPowerHook != NULL) {
            g_lowPowerHook();
        }
#else
        wfi();
#endif
    }
}



发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言