开启辅助访问 切换到窄版

打印 上一主题 下一主题

任务创建的实现

[复制链接]
楼主
跳转到指定楼层
| 只看该作者 回帖奖励 |倒序浏览 |阅读模式

0x01

摘要
任务建立是ucos的重要内容,为了实现多任务,系统在建立初期就需要建立任务,任务建立涉及到TCB表、任务就绪表等内容,这些都是建立任务的重要方面,本文主要对ucos任务的建立过程进行讲解。

0x02

引言

任务创建是用户使用ucos最重要的一部分,在每次系统正式启动前都需要对任务进行专门的初始化,使用ucos的任务创建函数建立需要调用的函数,这样ucos就可以按照优先级的先后对任务进行调度,实现多任务同时运行的效果(实际上是多任务轮流运行)。为了让大家对ucos的任务创建过程有一个清楚的了解,并对ucos的任务创建所需的参数不在迷惑,本文对ucos的任务创建函数OSTaskCreate进行分析。
0x03

原理

首先列出OSTaskCreate的源码(放在后面吧),开始是#if...#endif条件编译,大家应该都了解,不多做解释。然后就是对OSTaskCreate的详细编程,也就是c语言的函数创建,函数名加上传递参数OSTaskCreate(参数),这里面的参数可能大家有点不太好了解,先做一下介绍:

void (*task)(void *p_arg)分为两部分一个是函数名指针void (*task),一个是函数参数(void *p_arg)c语言中(void *p)()p为指向函数名的指针,void *p_arg则表示参数p_arg为不定类型指针。这个参数的意思就是传递一个函数名,且这个函数带有一个不定类型的参数,具体参数由实际函数决定。
void *p_arg,和上面解释的一样,这个位置放传递给函数的参数,上面那个只是定义函数的形式,而不传递具体的参数,只是来表明这个函数参数类型。
OS_STK *ptos,用来表示任务用到的堆栈地址,这个需要用户事先定义好具体的堆栈,也就是一个数组,将数组的地址也就是数组的名传过来就行。
INT8U prio,表示任务的优先级,这个要求每个任务的优先级必须不同,在ucos的最新版本中取消这个限制了,主要是通过采用时间转轮的方式,达到一个优先级容纳多个任务的功能。
那么这些参数具体怎么用,还需要对OSTaskCreate进行具体分析,为了大家便于阅读,采用在代码中间插入讲解方式。
源码:
#if OS_TASK_CREATE_EN > 0
条件编译,与后面的#endif配对使用。
INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio)
这就是函数的具体名称,各个参数的意思已经在上面进行了介绍。
{
OS_STK *psp;
INT8U err;
这里定义了两个变量,一个用户接受堆栈初始化的返回值,一个用于接收TCB初始化的返回值。
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr = 0;
#endif
这里也是条件编译,主要用于确定进入临界段的方法,因为方法3需要一个cup_sr的变量。
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO) {
return (OS_ERR_PRIO_INVALID);
}
#endif
这是是条件编译,如果允许参数检查,则会检查任务的优先级是否在允许的范围内,如果超界了则会返回OS_ERR_PRIO_INVALID的错误值。
OS_ENTER_CRITICAL();
if (OSIntNesting > 0) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
这里主要是判断任务是否是在中断中进行的任务建立,如果是,则返回错误。
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {
当以上所有情况都满足时,如果对应优先级的OSTCBPrioTbl数组值为0,则表明这个优先级没有被占用,否则被占用。被占用则不进行任何操作,返回优先级被占用的错误OS_ERR_PRIO_EXIST
OSTCBPrioTbl[prio] = OS_TCB_RESERVED;
如果优先级没有被占用,则现将这个优先级弄上占用标记,避免因为中断等原因二次操作。

OS_EXIT_CRITICAL();
psp = OSTaskStkInit(task, p_arg, ptos, 0);
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
这里则对任务的堆栈、任务的TCB表进行了初始化,具体在下一讲中进行讲解。
if (err == OS_ERR_NONE) {
到这里表示任务的初始化完成,先判断是否出错,如果没有出错则进行下面的操作。
if (OSRunning == OS_TRUE) {
OS_Sched();
}
这里表示如果系统已经在运行了,则进行一次任务切换,这里只要是为了满足任务是由其他运行的任务创建的,这样可以及时的按照优先级进行任务运行。
} else {
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;
OS_EXIT_CRITICAL();
}
这个else里面表示任务初始化中出现了错误,任务创建失败,则这里对优先级对应的OSTCBPrioTbl数组重新赋值为0,取消对其的占用,以便其他任务使用。
return (err);
这里就返回任务初始化TCB时的返回值,出错与否可以在任务创建中进行判读。
}
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);
}
#endif
0x04

小结

本文主要讲解了ucos任务创建的过程,其实任务创建主要是对堆栈和TCB进行初始化,如果初始化没有错误则任务创建成功。初始化主要做了哪些事情,在下一篇中在进行讲解。

Change

你的努力
我的付出
大家的支持
终将化作生命辉煌
如有任何疑问请后台回复

或添加作者Waiting_B_H



知识传播是一种美德

让更多人少走弯路
才能有更多人与你携手前进

欢迎扫码一起分享经验


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表