把一个大型任务分解成多个小任务,然后在计算机中通过运行这些小任务,最终达到完成大任务的目的。在μC/OS-II中,与上述那些小任务对应的程序实体就叫做“任务”(实质上是一个线程–有私有空间的任务叫做进程,没有私有空间的任务叫做线程),μC/OS-II就是一个能对这些小任务的运行进行管理和调度的多任务操作系统。
从应用程序设计的角度来看,μC/OS-II的任务就是一个用户编写的C函数和与之相关联的一些数据结构而构成的一个实体。在内存中应该存有任务的代码和与该任务配套的堆栈。
一个完整的任务应该有如下三部分:
1. 任务代码(程序)
2. 任务的私有堆栈(用以保护运行环境)
3. 任务控制块(提供私有堆栈也是虚拟处理器的位置)
μC/OS-Ⅱ的任务管理函数共有9个:
- 2个建立任务函数
- 1个堆栈检验函数
- 1个优先级变更函数
- 1个任务挂起函数
- 1个任务恢复函数
- 1个删除任务函数
- 1个请求删除任务函数
- 1个任务信息的获取函数
这些任务管理函数后面再详细分析,这里重点讲一下任务堆栈。
任务栈是用于保存任务函数中所用寄存器、变量和数据结构的堆栈。µC/OS-Ⅱ的任务栈必须声明为OS_STK
类型,它有如下特点:(1) 每个任务都可以有自己不同的堆栈空间;(2) 堆栈声明应放置在函数的外面;(3) 堆栈由连续的内存空间组成。
每个任务在创建的时候都要调用OSTaskStkInit()
初始化任务堆栈。初始化任务堆栈需要清楚处理器平台堆栈的生长方向,Corex-M3的堆栈是向下生长的。
如下定义的任务堆栈,则栈顶指针应STARTUP_TASK_STK_SIZE-1]
static OS_STK startup_task_stk[STARTUP_TASK_STK_SIZE]; //define stack
堆栈初始化在不同的处理器平台有差异,以下为在STM32上移植系统的堆栈初始化函数源码,其实任务堆栈的初始化就是对该任务的虚拟处理器的初始化(复位)。
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;
(void)opt; /* 'opt' is not used, prevent warning */
stk = ptos; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception */
*(stk) = (INT32U)0x01000000L; /* xPSR */
*(--stk) = (INT32U)task; /* Entry Point */
*(--stk) = (INT32U)0xFFFFFFFEL; /* R14 (LR) (init value will cause fault if ever used)*/
*(--stk) = (INT32U)0x12121212L; /* R12 */
*(--stk) = (INT32U)0x03030303L; /* R3 */
*(--stk) = (INT32U)0x02020202L; /* R2 */
*(--stk) = (INT32U)0x01010101L; /* R1 */
*(--stk) = (INT32U)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--stk) = (INT32U)0x11111111L; /* R11 */
*(--stk) = (INT32U)0x10101010L; /* R10 */
*(--stk) = (INT32U)0x09090909L; /* R9 */
*(--stk) = (INT32U)0x08080808L; /* R8 */
*(--stk) = (INT32U)0x07070707L; /* R7 */
*(--stk) = (INT32U)0x06060606L; /* R6 */
*(--stk) = (INT32U)0x05050505L; /* R5 */
*(--stk) = (INT32U)0x04040404L; /* R4 */
return (stk);
}
OSTaskStkInit()
在Cortex-M3中主要功能为初始化任务的栈的桔构,使任务的栈看起来就好像刚发生了一个中断一样。Cortex-M3中断时,xPSR、PC、LR、R12、R3--R0
自动入栈,R11--R4
需手动保存。这里的值R1--R12
没有实际意义,相应的数值只为调试方便。
初始化后各寄存器的值如下
xPSR=0x0100000
,xPSR
T
位置1,否则第一次执行任务是Fault。
PC=task
,指向任务入口。
R14=0xFFFFFFFE
,是一个非法值,主要目的是不让使用R14
,任务不能返回。
R0=p_arg
,用于传递任务的参数。