首页 > 代码库 > ucos如何保存局部变量到任务堆栈中

ucos如何保存局部变量到任务堆栈中

学习ucos好长一段时间,一直没明白在os中任务是怎么保存局部变量在自己的栈中。今天终于弄明白了。

1.没有OS时,任务如何保存局部变量

在我的知识体系里,我一直以为单片机中就只有一个栈,以stm32为例,在启动文件中有怎么一段:

; Amount of memory (in bytes) allocated for Stack

; Tailor this value to your application needs

; <h> Stack Configuration

; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>

; </h>

Stack_Size      EQU     0x00000400

                      AREA    STACK, NOINIT, READWRITE, ALIGN=3

 Stack_Mem    SPACE   Stack_Size

__initial_sp

假设stm32的内存有16Kb,起始地址为,栈向下生长,从启动文件中可以看到,栈的大小为0x400,我称之为系统栈,系统栈的范围为0x0x20000000~0x20000400 。在没有OS的应用中(裸奔),cpu其实有两个任务,一个是中断任务,一个是main函数中的后台任务。当函数调用或者发生中断时,就使用系统栈保存局部变量和寄存器状态,也就是SP指向0x0x20000000~0x20000400。

2.ucos中如何保存局部变量

 其实有没有操作系统都一样,都把任务中的局部变量和当前的寄存器状态保存在栈中,在UCOS中一个任务就分配一个栈,假设有两个任务,申请分配对应的任务栈如下:

   static  OS_STK Task1Stk[128];  //假设任务1的堆栈地址为0x20000500,那么任务1中的局部变量和寄存器状态将保存在0x20000500~0x20000580

   static  OS_STK Task2Stk[256]; //假设任务1的堆栈地址为0x20000600,那么任务2中的局部变量和寄存器状态将保存在0x20000600~0x20000700

当任务1运行时,系统使用的栈不再是0x0x20000000~0x20000400,而是0x20000500~0x20000580,任务2运行时,系统中的栈指向0x20000600~0x20000700。那么如何切换SP呢?假设切换到任务1SP:
;保存任务1SP

    LDR     R1, =Task1Stk                                   ; 把SP存在R1中,在任务1中R1等于0x20000500~0x20000580
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

;切换到任务1的SP

    MSR     PSP, R0                                             ; Load PSP with new process SP

就这样,在UCOS中的模拟系统栈,生成任务栈,局部变量在任务栈中的分配,而非在系统栈中。而我之前的困惑是以为任务中的局部变量是分配到系统栈中,待任务切换中把系统栈中的内容负责到任务栈中。

 

ucos如何保存局部变量到任务堆栈中