大家好,又见面了,我是你们的朋友全栈君。
uC/OS-III任务创建函数OSTaskCreate()
欢迎进入linuxweiyh的博客
1.OSTaskCreate()函数原型
代码语言:javascript复制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()函数代码解析
代码语言:javascript复制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的理解不是很透彻,所以只能做部分注释,以后会逐步增加。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。