原子的开发板,原子的例程序“ALIENTEK MINISTM32 实验1 跑马灯”
是用SWD调试时发现R13也就是SP的值为 0x20000208,觉得奇怪不?stack的定位一般应该是RAM空间的最高位,因为STM32使用的是向下生长的满栈,所以根据RAM = 20KB SP可以定在0x20005000上。这样做的好处先不提,先看看MDK是怎样算出0x20000208的。
在启动程序里跟SP有关的当然就是__initial_sp这个标号了,也不知道内容是什么?反正进到__main里面就自动将SP改成0x20000208了,查找了下MDK的帮助文档,隐约有提到initial_sp的值是根据ZI的地址算出来的,ZI是什么我就不解释了,(RO,RW,ZI嘛),再来通过看编译后的程序确定下好了,详细信息都在.map文件里,这里面有IMAGE文件的详细说明。
XXX.map 文件里的一部分如下,XXX.map文件在工程文件夹里有的。 因为是复制粘贴过来的 所以要上下对齐了看。
====================================================================
Image component sizes
Code (inc. data) RO Data RW Data ZI Data Debug Object Name
160 8 0 4 0 0 delay.o
128 18 0 0 0 0 led.o
28 4 240 0 512 0 stm32f10x.o
778 72 0 0 0 0 sys.o
88 10 0 0 0 0 test.o
----------------------------------------------------------------------
1184 112 272 4 516 0 Object Totals
0 0 32 0 0 0 (incl. Generated)
2 0 0 0 4 0 (incl. Padding)
----------------------------------------------------------------------
Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name
0 0 0 0 0 0 entry.o
8 4 0 0 0 0 entry2.o
4 0 0 0 0 0 entry5.o
8 4 0 0 0 0 entry7.o
30 0 0 0 0 0 handlers.o
36 8 0 0 0 0 init.o
----------------------------------------------------------------------
88 16 0 0 0 0 Library Totals
2 0 0 0 0 0 (incl. Padding)
----------------------------------------------------------------------
Code (inc. data) RO Data RW Data ZI Data Debug Library Name
86 16 0 0 0 68 mc_w.l
----------------------------------------------------------------------
88 16 0 0 0 0 Library Totals
----------------------------------------------------------------------
================================================================
Code (inc. data) RO Data RW Data ZI Data Debug
1272 128 272 4 516 7504 Grand Totals
1272 128 272 4 516 7504 ELF Image Totals
1272 128 272 4 0 0 ROM Totals
===============================================================
Total RO Size (Code + RO Data) 1544 ( 1.51kB)
Total RW Size (RW Data + ZI Data) 520 ( 0.51kB)
Total ROM Size (Code + RO Data + RW Data) 1548 ( 1.51kB)
================================================================
注意到红线的地方,可以看到程序用到多少RW 和 ZI,启动stm32f10x.s里竟然有512个字节的ZI,这个不奇怪,就是因为
Stack_Size EQU 0x00000200 的设定
所以再加上Padding的4个字节,ZI区共516个字节,看黄线部分,padding是干啥的我也不清楚,貌似是为了对齐用了添加的多余字节。
那么再加上RW区的4个字节,总共RW + ZI = 520个字节,所以SP就定在了 0x20000208 (0x208 = 520),那么现在真相看到了吧。
结论&吐槽:MDK能不用这么坑爹的设定么?把stack放到RW+ZI区的结束位置?并且Stack_Size EQU 0x00000200 这个空间也算ZI?stack需要ZI?费力不讨好吧,你定个Stack_Size EQU 0x00000200 有什么用呢?能防止程序深度调用时stack溢出?还要在创建ZI时多初始化512个字节,把stack定到RAM最高地址不好么?把RW+ZI区结束位置留给heap不好么?看着不爽吧,还不让人改,一个__main都搞完了,还直接跳到我的main,我只能干瞪眼。试过保留向量表,其他部分自己用汇编写吧,各种报错,各种库函数什么的找不到,我不用你的初始化库还不行吗?还真不行,不知道该哪的设置,搞了一晚上头都大了。
好吧我屈服了
在向量表的末尾加上红线部分
.......
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
SP_ADDR DCD 0X20005000
EXPORT SP_ADDR
AREA |.text|, CODE, READONLY
.......
然后在主程序里 加上红线部分 嵌入一个汇编函数来修改SP
__asm void set_sp(void)
{
IMPORT SP_ADDR
LDR R13, SP_ADDR
BX LR // 返回主程序(不可省略)
ALIGN
}
int main(void)
{
set_sp(); //终于我的SP是自己定义的了
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
LED0=0;
LED1=1;
delay_ms(300);
LED0=1;
LED1=0;
delay_ms(300);
}
}
记得最后改 Stack_Size EQU 0x00000000
这样就没了那512个字节的冤大头。
哎,这就是跟编译器卯了一晚上,得到的结果。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>