ucosii中堆栈增长方式与栈顶指针的困惑
一、ucosii堆栈例子:
OS_STK TaskStk;
二、数组地址
对于数组,其元素地址是递增的,即: &TaskStk < &TaskStk < &TaskStk < ... < &TaskStk
三、增长方式与栈顶栈底
堆栈是“后进先出”模式,第一个进栈的数据,其地址为栈底地址,最后一个进栈的为栈顶,那么关于向上、向下增长方式的栈顶如图:
四、疑问:
按照上面的逻辑:
向上增长模式,栈顶地址为:&TaskStk
向下增长模式,栈顶地址为:&TaskStk
但是
按照《嵌入式实时操作系统μCOS-II原理及应用 任哲编著》这本书中说法:
向上增长模式,栈顶地址为:&TaskStk
向下增长模式,栈顶地址为:&TaskStk
和我分析的是相反的。
请问我有哪一步理解错误了吗? 如果堆栈从内存高地址向低地址方向增长, 常量 OS_STK_GROWTH 应设为 1
51单片机的堆栈是 向上增长的,不应该设为1。
但是 由于 51 内部的RAM 太小, ucos51 使用外部 xdata 模拟 stack。采用向下方式处理任务栈。
所以, OS_STK_GROWTH 为 1 本帖最后由 Thireven 于 2015-11-19 08:38 编辑
leirui001 发表于 2015-11-19 08:06
如果堆栈从内存高地址向低地址方向增长, 常量 OS_STK_GROWTH 应设为 1
51单片机的堆栈是 向上增长的,不应 ...
这个我明白,我不明白的地方是我分析出来的栈顶和那本书里面给出来的相反......另外,我的硬件平台是stm32的 你对栈顶理解有误 Thireven 发表于 2015-11-19 08:37
这个我明白,我不明白的地方是我分析出来的栈顶和那本书里面给出来的相反......另外,我的硬件平台是stm3 ...
注意,STM32的栈方式是向下生长的满栈,也就是从高地址即任务栈的末地址开始给变量,寄存器等需要入栈的分配栈空间。
首次使用堆栈指针是指向任务栈的末地址,也就是高地址。举个例子,比如某任务的栈空间是CPU_STK stack,创建
任务后的栈初始化效果就是这样的:
* 说 明:第一次任务切换前,16个寄存器的存储
* |-----------------| stack
* | .... |
* |-----------------|
* | .... |
* |-----------------|
* 低地址 | .... |
* |-----------------|
* ^ | R4 |
* ^ |-----------------|
* ^ | R5 |
* | |-----------------|
* | | R6 |
* | |-----------------|
* | | R7 |
* | |-----------------|
* | | R8 |
* | |-----------------|
* | | R9 |
* | |-----------------|
* | | R10 |
* | |-----------------|
* | | R11 |
* | |-----------------|
* | | R0 = p_arg |
* | |-----------------|
* | | R1 |
* | |-----------------|
* | | R2 |
* | |-----------------|
* | | R3 |
* | |-----------------|
* | | R12 |
* | |-----------------|
* | | LR |
* | |-----------------|
* | | PC = task |
* | |-----------------|
* | | xPSR |
* 高地址 |-----------------|stack cht-rtos 发表于 2015-11-19 09:00
你对栈顶理解有误
是第一个进栈的为栈顶? Eric2013 发表于 2015-11-19 09:08
注意,STM32的栈方式是向下生长的满栈,也就是从高地址即任务栈的末地址开始给变量,寄存器等需要入栈的 ...
我懂了,创建任务的时候,任务堆栈还是空的,没有存放数据,这个时候栈顶和栈底是重合的。
所以向下增长模式,应该是向栈中压入数据时,栈顶指针时向下偏移的。也就是“向下增长”指的是栈顶指针是“向下偏移”的意思。
是否这样理解?
Thireven 发表于 2015-11-19 21:50
我懂了,创建任务的时候,任务堆栈还是空的,没有存放数据,这个时候栈顶和栈底是重合的。
所以向下增长 ...
对 {
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);
}
这个函数中,可以看出地址是递减的;但是不明白右边参数赋值有什么要求? OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) Eric2013 发表于 2015-11-19 09:08
注意,STM32的栈方式是向下生长的满栈,也就是从高地址即任务栈的末地址开始给变量,寄存器等需要入栈的 ...
你好:
我最近在看ucos,也遇到和LZ一样的疑问。
在你的回答中:从高地址即任务栈的末地址开始给变量,寄存器等需要入栈的分配栈空间
意思是刚开始分配的时候,栈顶和栈底都指向stack的位置,
随着变量和既存器压栈,栈底始终在stack,而栈顶则stack,stack,.....,stack
是这样吗?
谢谢! dadian 发表于 2020-6-15 17:07
你好:
我最近在看ucos,也遇到和LZ一样的疑问。
在你的回答中:从高地址即任务栈的末地址开始给变量,寄 ...
栈顶,指向的是栈的起始单元,换个角度,要是依次从栈里弹出元素的话,栈顶元素那个是垫底出栈。
栈指针,根据栈的生长方向,递增或递减。也就可以确定栈顶的位置。
页:
[1]