chap04-任务管理
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
INT8U OSTaskCreateExt (void (*task)(void *pd),
INT16U id,
OS_STK *pbos, INT32U stk_size,
void *pext,
INT16U opt)
12
{
#if OS_CRITICAL_METHOD == 3 register */ OS_CPU_SR cpu_sr; #endif OS_STK INT8U *psp; err;
page
23
这个问题会影响代码的可移植性。如果用户想将 代码从支持往下递减堆栈的处理器中移植到支持 往上递增堆栈的处理器中的话,用户得使代码同 时适应以上两种情况。
程序清单
对两个方向增长的堆栈都提供支持
OS_STK TaskStack[TASK_STACK_SIZE]; #if OS_STK_GROWTH == 0 OSTaskCreate(task, pdata, &TaskStack[0], prio); #else OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio); #endif
page
22
当OS_CPU.H 文件中的OS_STK_GROWTH 置 为1 时,用户需要将堆栈的最高内存地址传递给 任务创建函数。
程序清单
堆栈从上往下递减
OS_STK TaskStack[TASK_STACK_SIZE];
OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio);
page
21
当OS_CPU.H 文件中的OS_STK_GROWTH 置 为0 时,用户需要将堆栈的最低内存地址传递给 任务创建函数。
程序清单 堆栈从下往上递增
OS_STK TaskStack[TASK_STACK_SIZE]; OSTaskCreate(task, pdata, &TaskStack[0], prio);
page
6
4.0 建立任务,OSTaskCreate()
任务的创建 --- 创建该任务的TCB;在TCB中将该 任务的Code、Stack关联起来和TCB共同构成 Task。 uC/OS-II提供两个系统函数创建Task :
OSTaskCreate( )
OSTaskCreateExt( )
10
4.01 建立任务,OSTaskCreateExt()
用OSTaskCreateExt()函数来建立任务会更 加灵活,但会增加一些额外的开销。
page
11
程序清单
OSTaskCreateExt()
void *pdata, OS_STK *ptos, INT8U prio,
为要建立的任务 创建一个特殊的 标识符 指向任务的堆栈 栈底的指针,用 指定堆栈成员数 于堆栈的检验。 目的容量 指向用户附加的 数据域的指针 用于设定 OSTaskCreateExt()的 选项,指定是否允许 堆栈检验,是否将堆 栈清零,任务是否要 进行浮点操作等等。
page
/*****************************主函数**********************************/ void main(void) { ……
OSInit(); …… OSTaskCreate(TaskStart,……); OSStart(); // 对uC/OS-II初始化 // 创建起始任务 // 开始多任务调度
15
创建任务的一般方法
可在调用函数OSStart()启动任务调度之前来创建。 在任务中来创建。 uC/OS-II的规定:在OSStart()启动任务调度之前必须创建至少一个 任务。 这样,在OSStart()之前先创建一个任务,并赋予它最高的优先级, 从而使它成为起始任务,然后在这个起始任务中,再创建其它各任务。 如果要使用系统提供的统计任务,则统计任务的初始化函数必须在 这个起始任务中来调用。 uC/OS-II不允许在中断服务程序中创建任务
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK 分配给任务 *ptos, INT8U prio) {
# if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; # endif
void *psp;
page
24
4.03 堆栈检验,OSTaskStkChk()
决定任务实际所需的堆栈空间大小是很有必要的--减少应用程序代码所需的RAM(内存)数量。 μC/OS-Ⅱ提供的OSTaskStkChk()函数可以为用 户提供这种有价值的信息。
器加1
9
} else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0; OS_EXIT_CRITICAL(); }
return (err);
} OS_EXIT_CRITICAL();
returnБайду номын сангаас(OS_PRIO_EXIST);
}
page
page
4.02 任务堆栈
每个任务都有自己的堆栈空间。堆栈必须声明为 OS_STK 类型,并且由连续的内存空间组成。用 户可以静态分配堆栈空间(在编译的时候分配)也 可以动态地分配堆栈空间(在运行的时候分配)。
程序清单
或
静态堆栈
static OS_STK MyTaskStack[stack_size];
INT8U err;
# if OS_ARG_CHK_EN > 0
先检测分配给任务 的优先级是否有效
if (prio > OS_LOWEST_PRIO) {
return (OS_PRIO_INVALID); } # endif
8
OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {
/* Allocate storage for CPU status
#if OS_ARG_CHK_EN > 0 if (prio > OS_LOWEST_PRIO) { within allowable range */ return (OS_PRIO_INVALID); } /* Make sure priority is
} /*****************************起始任务*********************************/ void TaskStart(void *pdata) { …… // 在这个位置安装并启动uC/OSII时钟 OSStatInit(); // 初始化统计任务 …… // 在这个位置创建其它任务 For(;;) { 起始任务的代码 } }
任务可以在多任务调度开始前建立,也可以在其它 任务的执行过程中被建立。在开始多任务调度(即调用 OSStart())前,用户必须建立至少一个任务。任务不能 由中断服务程序(ISR)来建立。
page
7
程序清单 OSTaskCreate()
的优先级
任务代码的 指针
当任务开始执行时传 分配给任务的堆 栈的栈顶指针 递给任务的参数的指 针
page
4
任务也可以是在一次执行完毕后被删除掉。
void YourTask (void *pdata) { /* 用户代码 */ OSTaskDel(OS_PRIO_SELF); }
page
5
μC/OS-Ⅱ任务管理
最多管理任务数:64个;
保留任务:四个最高优先级和四个最低优先级的 任务;
用户任务:最多56个。
err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0);
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL(); 任务计数 OSTaskCtr++; OS_EXIT_CRITICAL(); if (OSRunning == TRUE) { OSSched(); }
确保在规定的优 先级上还没有建 立任务
放置一个非空指针在 建立任务的堆 OSTCBPrioTbl[prio] = (OS_TCB *)1; 栈, 返回新的堆 OSTCBPrioTbl[]中来保 留该优先级 栈栈顶(psp) 从空闲的 OS_EXIT_CRITICAL(); OS_TCB 池中 psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); 获得并初始化 一个OS_TCB
14
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt); err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); if (err == OS_NO_ERR) { OS_ENTER_CRITICAL(); OSTaskCtr++; OS_EXIT_CRITICAL(); if (OSRunning == TRUE) { OS_Sched(); } } else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0; OS_EXIT_CRITICAL(); } return (err); } OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); }
程序清单 静态堆栈
OS_STK MyTaskStack[stack_size];
page
18
malloc()函数来动态地分配堆栈空间
程序清单 用malloc()为任务分配堆栈空间
OS_STK *pstk;
pstk = (OS_STK *)malloc(stack_size); if (pstk != (OS_STK *)0) { /* 确认malloc()能得到足够 地内存空间 */ Create the task; }
嵌入式实时操作系统 μC/OS-II
2012-12-14
page
1
第4章 任务管理
2012-12-14
page
2
本章所讲的内容:
建立任务;删除任务;
改变任务的优先级;
挂起和恢复任务;
获得有关任务的信息。
2012-12-14
page
3
任务可以是一个无限的循环
void YourTask (void *pdata) { for (;;) { /* 用户代码 */ 调用μC/OS-Ⅱ的服务例程之一: OSMboxPend(); OSQPend(); OSSemPend(); OSTaskDel(OS_PRIO_SELF); OSTaskSuspend(OS_PRIO_SELF); OSTimeDly(); OSTimeDlyHMSM(); /* 用户代码 */ } }
page
19
在动态分配中,用户要时刻注意内存碎片 问题。
page
20
μC/OS-Ⅱ支持的处理器的堆栈既可以从上(高地 址)往下(低地址)长也可以从下往上长。
用户在调用OSTaskCreate()或 OSTaskCreateExt()的时候必须知道堆栈是怎样 长的,因为用户必须得把堆栈的栈顶传递给以上 两个函数。
#endif
13
OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { OSTCBPrioTbl[prio] = (OS_TCB *)1; OS_EXIT_CRITICAL(); if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) || /* See if stack checking has been enabled */ ((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) { /* See if stack needs to be cleared */ #if OS_STK_GROWTH == 1 (void)memset(pbos, 0, stk_size * sizeof(OS_STK)); #else (void)memset(ptos, 0, stk_size * sizeof(OS_STK)); #endif }