uC/OS-III-6.1-uC/OS-III任务堆栈空间

1.设置任务优先级
嵌入式系统中的重要的应用应该被设置为高优先级,一些显示操作就应该被设置为低优先级。 然而, 由于实时系统的复杂性, 在大多数情况下任务的优先级是不能被事先确定的。多数系统中,不是所有的任务都是重要的,不重要的任务应该被设置为低优先级。
2.堆栈空间大小的确定
堆栈的大小取决于该任务的需求。设定堆栈大小时,你就需要考虑: 所有可能被堆栈调用的函数及其函数的嵌套层数, 相关局部变量的大小, 中断服务程序所需要的空间。 另外, 堆栈还需存入CPU寄存器,如果处理器有浮点数单元FPU寄存器的话还需存入FPU寄存器。嵌入式系统的潜规则,避免写递归函数。
编译器/汇编器提供的的连接映像信息是很有用的。在每个函数中, 连接映像提供了函数在最坏情况下堆栈使用量。 这个功能能够比较精确地评估每个任务所需的堆栈空间。 当然, 还需添加一个CPU寄存器空间、再一个CPU寄存器空间(如果CPU没有独立的空间处理ISR的话)、再加上这些ISR需要的堆栈空间。最后,为了保证可靠还有再乘以一个1.5左右的值。
在产品的开发和测试阶段,通常在运行时用调试器测量堆栈的使用情况。
3.检测任务堆栈的溢出(使用MMU或MPU)
如果处理器有MMU或者MPU,检测堆栈是否溢出是非常简单的。MMU和MPU是CPU边上的特殊硬件设施, 可以检测非法访问, 如果任务企图访问未被允许的内存空间的话, 就会产生警告。
堆栈溢出检测寄存器:
(1).一些处理器中有一些堆栈溢出检测寄存器。当CPU的堆栈指针小于(或大于,取决于堆栈的生长方向)设置于这个寄存器的值时。异常产生时异常处理程序就要确保未允许空间代码的安全 ( 可能会发送警告给用户)。OS_TCB中的.StkLimitPtr就是为这种目的设置的如图5-3.堆栈必须被分配足够大的空间。 在大多数情况下, 该指针的值可以设置接近于&MYTaskStk[0]。
{假定堆栈是从高地址往低地址生长的}
这里写图片描述
在此提醒, StkLimitPtr 的值取决于 OSTaskCreate()的参数”stk_limit”如下所示:
这里写图片描述
通过首先改变堆栈溢出检测寄存器指向一个地址(通常设为NULL)从而让堆栈指针总是有效的。
基于软件的堆栈溢出检测:
当uC/OS-III从一个任务切换到另一个任务的时候,它会调用一个hook函数OSTaskSwHook(),它允许用户扩展上下文切换时的功能。所以,如果处理器没有硬件支持溢出检测功能,就可以在该 hook函数中添加代码软件模拟该功能。 特别的, 在切换到任务B前, 代码会检测将要被载入 CPU堆栈指针的值是否超出该任务 B的 TCB中StkLimitPtr限制。 因为软件不能在溢出时就迅速地做出反应, 所以应该设置StkLimitPtr的值尽可能远离&MyTaskStk[0], 保证有足够的溢出缓冲。如图5-4。软件检测不会像硬件检测那样有效,但也可以防止堆栈溢出。
这里写图片描述
计算空闲堆栈空间:
另一种防止堆栈溢出的方法是分配的空间远大于可能需要用到的。 然后, 调试器检测在运行时任务所用的最大堆栈空间。 这是易于实现的。 首先, 当任务创建时其堆栈被清零。 然后, 通过一个低优先级任务, 计算该任务整个堆栈中值为0的内存大小。 如果发现都不为0,那么就需要扩展堆栈的大小。然后,调整堆栈为的相应大小。这是一种非常有效的方法。 注意的是, 程序需用运行很长的时间以让堆栈达到其需要的最大值。详见图 5-5。 uC/OS-III提供了一个函数OSTaskStkChk()用于实现这个计算功能。事实上,这个函数被OS_StatTask()用于统计每个任务的堆栈使用情况。
这里写图片描述
4.任务管理服务
uC/OS-III 提供了很多与任务相关的函数。这些函数可以在OS_TASK.C中找到,它们都以以OSTask???()形式命名的。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/changjucha3459/article/details/81147303