uC/OS-III任务创建函数OSTaskCreate()

uC/OS-III任务创建函数OSTaskCreate()

欢迎进入linuxweiyh的博客

1.OSTaskCreate()函数原型

void TaskCreate(OS_TCB *p_tcb,  // 任务控制OS_TCB的地址
    CPU_CHAR *p_name,           // 任务的名字
    OS_TASK_PTR p_task,         // 任务代码的起始地址
    void *p_arg,                // 任务第一次运行时接收到的参数
    OS_PRIO prio,               // 任务优先级
    CPU_STK *p_stk_base,        // 任务栈的基地址,基地址总是栈空间的最低地址
    CPU_STK_SIZE stk_limit,     // 任务栈的深度标记
    CPU_STK_SIZE stk_size,      // 任务栈的大小
    OS_MSG_QTY q_size,          // 任务内部消息队列的大小
    OS_TICK time_quanta,        // 时间片轮转的长度
    void *p_ext,                // 用户补充的存储区
    OS_OPT opt,                 // 任务特定选项
    OS_ERR *p_err)              // 错误码

注1:这里最需要注意的参数是任务栈的基地址,这里的基地址指的是栈空间的最低地址,即???Stk[0]的地址。
注2:在uC/OS-II:的OSTaskCreate()函数中,描述有关栈的参数是栈顶地址,不是栈的基地址。
注3:深度标记stk_limit表示的是栈剩余空间,不需要管栈的增长方向,是多少就是多少,uC/OS-III内部会自己转换。当栈的剩余空间小于栈的深度标记时会报警。
2.OSTaskCreate()函数代码解析

void  OSTaskCreate (OS_TCB        *p_tcb,
                    CPU_CHAR      *p_name,
                    OS_TASK_PTR    p_task,
                    void          *p_arg,
                    OS_PRIO        prio,
                    CPU_STK       *p_stk_base,
                    CPU_STK_SIZE   stk_limit,
                    CPU_STK_SIZE   stk_size,
                    OS_MSG_QTY     q_size,
                    OS_TICK        time_quanta,
                    void          *p_ext,
                    OS_OPT         opt,
                    OS_ERR        *p_err)
{
    CPU_STK_SIZE   i;
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OS_OBJ_QTY     reg_nbr;
#endif
    CPU_STK       *p_sp;
    CPU_STK       *p_stk_limit;
    CPU_SR_ALLOC();

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == DEF_TRUE) {
       *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
        return;
    }
#endif

    // 不允许在ISR中创建任务
#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u  
    if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              
        *p_err = OS_ERR_TASK_CREATE_ISR;
        return;
    }
#endif

    // 形参检测
#if OS_CFG_ARG_CHK_EN > 0u  
    if (p_tcb == (OS_TCB *)0) {              // 任务控制块
        *p_err = OS_ERR_TCB_INVALID;
        return;
    }
    if (p_task == (OS_TASK_PTR)0) {          // 任务起始地址
        *p_err = OS_ERR_TASK_INVALID;
        return;
    }
    if (p_stk_base == (CPU_STK *)0) {        // 栈的基地址                     
        *p_err = OS_ERR_STK_INVALID;
        return;
    }
    if (stk_size < OSCfg_StkSizeMin) {      // 栈的大小                      
        *p_err = OS_ERR_STK_SIZE_INVALID;
        return;
    }
    if (stk_limit >= stk_size) {             // 栈的深度标记                    
        *p_err = OS_ERR_STK_LIMIT_INVALID;
        return;
    }
    if (prio >= OS_CFG_PRIO_MAX) {           // 任务优先级                        
        *p_err = OS_ERR_PRIO_INVALID;
        return;
    }
#endif

    // 任务的优先级检测
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
    if (prio == (OS_PRIO)0) {
        if (p_tcb != &OSIntQTaskTCB) {
            *p_err = OS_ERR_PRIO_INVALID;              // 不允许任务的优先级为0
            return;
        }
    }
#endif
    if (prio == (OS_CFG_PRIO_MAX - 1u)) {
        if (p_tcb != &OSIdleTaskTCB) {                 // 不允许与空闲任务的优先级相同
            *p_err = OS_ERR_PRIO_INVALID;       
            return;
        }
    }

    // 初始化任务控制块(OS_TCB)
    OS_TaskInitTCB(p_tcb);

    *p_err = OS_ERR_NONE;

    // 清空任务栈
    if ((opt & OS_OPT_TASK_STK_CHK) != (OS_OPT)0) {      // 是否使能任务栈检测
        if ((opt & OS_OPT_TASK_STK_CLR) != (OS_OPT)0) {  // 任务栈是否必须清空   
            p_sp = p_stk_base;
            for (i = 0u; i < stk_size; i++) {            // 栈的增长方向是从高到低
                *p_sp = (CPU_STK)0;                      // 从低到高清空栈
                p_sp++;
            }
        }
    }

   // 初始化栈的深度标记
#if (CPU_CFG_STK_GROWTH == CPU_STK_GROWTH_HI_TO_LO)
    p_stk_limit = p_stk_base + stk_limit;
#else
    p_stk_limit = p_stk_base + (stk_size - 1u) - stk_limit;
#endif

    // 初始化栈
    p_sp = OSTaskStkInit(p_task,
                         p_arg,
                         p_stk_base,
                         p_stk_limit,
                         stk_size,
                         opt);

    // 初始化OS_TCB
    p_tcb->TaskEntryAddr = p_task;       // 保存任务入口地址
    p_tcb->TaskEntryArg  = p_arg;        // 保存任务参数
    p_tcb->NamePtr       = p_name;       // 保存任务名称
    p_tcb->Prio          = prio;         // 保存任务优先级
    p_tcb->StkPtr        = p_sp;         // 保存栈顶地址
    p_tcb->StkLimitPtr   = p_stk_limit;  // 保存栈深度标记
    p_tcb->TimeQuanta    = time_quanta;  // 保存任务时间片
#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    if (time_quanta == (OS_TICK)0) {
        p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta;
    } else {
        p_tcb->TimeQuantaCtr = time_quanta;
    }
#endif
    p_tcb->ExtPtr        = p_ext;        // 保存额外的TCB结构
    p_tcb->StkBasePtr    = p_stk_base;   // 保存栈的基地址 
    p_tcb->StkSize       = stk_size;     // 保存栈的大小
    p_tcb->Opt           = opt;          // 保存任务可选项

#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    for (reg_nbr = 0u; reg_nbr < OS_CFG_TASK_REG_TBL_SIZE; reg_nbr++) {
        p_tcb->RegTbl[reg_nbr] = (OS_REG)0;
    }
#endif

#if OS_CFG_TASK_Q_EN > 0u
    OS_MsgQInit(&p_tcb->MsgQ,                               /* Initialize the task's message queue                    */
                q_size);
#endif

    OSTaskCreateHook(p_tcb);              // 调用用户定义的介入函数

    // 把任务添加到任务就绪表中
    OS_CRITICAL_ENTER();                  // 进入临界区
    OS_PrioInsert(p_tcb->Prio);           // 向任务表中添加任务优先级
    OS_RdyListInsertTail(p_tcb);

#if OS_CFG_DBG_EN > 0u
    OS_TaskDbgListAdd(p_tcb);
#endif

    OSTaskQty++;  // Increment the #tasks counter

    if (OSRunning != OS_STATE_OS_RUNNING) {  // Return if multitasking has not started
        OS_CRITICAL_EXIT();               // 退出临界区
        return;
    }

    OS_CRITICAL_EXIT_NO_SCHED();          // 退出临界区

    OSSched();                            // 调度
}

总结:OSTaskCreate()函数主要的工作是初始化任务控制块、初始化栈、添加任务到任务任务就绪表。
注:由于目前对uC/OS-III的理解不是很透彻,所以只能做部分注释,以后会逐步增加。

你可能感兴趣的:(uC/OS-III)