任务堆栈
每个任务都有自己的堆栈空间。堆栈必须声明为OS_STK类型,并且由连续的内存空间组成。用户可以静态分配堆栈空间(在编译的时候分配)也可以动态地分配堆栈空间(在运行的时候分配)。静态堆栈声明如程序,这两种声明应放置在函数的外面。
静态堆栈
static OS_STK MyTaskStack[stack_size];
用户可以用C编译器提供的malloc()函数来动态地分配堆栈空间,如程序清单所示。在动态分配中,用户要时刻注意内存碎片问题。特别是当用户反复地建立和删除任务时,内存堆中可能会出现大量的内存碎片,导致没有足够大的一块连续内存区域可用作任务堆栈,这时malloc()便无法成功地为任务分配堆栈空间。
用malloc()为任务分配堆栈空间 |
OS_STK *pstk; |
|
|
pstk = (OS_STK *)malloc(stack_size); |
if (pstk != (OS_STK *)0) { /* 确认malloc()能得到足够地内存空间 */ |
Create the task; |
} |
图表示了一块能被malloc()动态分配的3K字节的内存堆[(1)]。假定建立三个任务(任务A,B和C),每个任务需要1K字节的空间。设第一个1K字节给任务A,第二个1K字节给任务B, 第三个1K字节给任务C[(2)]。然后,用户的应用程序删除任务A和任务C,用free()函数释放内存到内存堆中[(3)]。现在,用户的内存堆虽有2K字节的自由内存空间,但它是不连续的,所以用户不能建立另一个需要2K字节内存的任务(即任务D)。如果用户并不会去删除任务,使用malloc()是非常可行的。
图 F4.1 内存碎片
µC/OS-Ⅱ支持的处理器的堆栈既可以从上(高地址)往下(低地址)长也可以从下往上长。用户在调用OSTaskCreate()或OSTaskCreateExt()的时候必须知道堆栈是怎样长的,因为用户必须得把堆栈的栈顶传递给以上两个函数,当OS_CPU.H文件中的OS_STK_GROWTH置为0时,用户需要将堆栈的最低内存地址传递给任务创建函数。
堆栈从下往上递增 |
OS_STK TaskStack[TASK_STACK_SIZE]; |
|
OSTaskCreate(task, pdata, &TaskStack[0], prio); |
当OS_CPU.H文件中的OS_STK_GROWTH置为1时,用户需要将堆栈的最高内存地址传递给任务创建函数,如程序清单4.8所示。
程序清单 L4.8 堆栈从上往下递减 |
OS_STK TaskStack[TASK_STACK_SIZE]; |
|
OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio); |
这个问题会影响代码的可移植性。如果用户想将代码从支持往下递减堆栈的处理器中移植到支持往上递增堆栈的处理器中的话,用户得使代码同时适应以上两种情况。在这种特殊情况下,重新写成如程序所示的形式。
对两个方向增长的堆栈都提供支持 |
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 |
任务所需的堆栈的容量是由应用程序指定的。用户在指定堆栈大小的时候必须考虑用户的任务所调用的所有函数的嵌套情况,任务所调用的所有函数会分配的局部变量的数目,以及所有可能的中断服务例程嵌套的堆栈需求。另外,用户的堆栈必须能储存所有的CPU寄存器。
UCOS_II基础入门:
扫一扫关注微信公众号,获取更多实时的嵌入式资讯,嵌入式学习指导方法,汽车电子最新资讯等。