硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6232|回复: 14
收起左侧

[有问必答] stm32的内部存储,rom,ram,变量保存的位置。

[复制链接]

32

主题

103

回帖

199

积分

高级会员

积分
199
发表于 2018-11-9 14:41:02 | 显示全部楼层 |阅读模式
我了解到C语言的变量,自动变量,静态变量,寄存器变量,全局变量。C语言的存储空间常量区,堆区,栈区。
我用的芯片是stm32f103系列,128KB的flash,20KB的SRAM
我看内存图,flash memory分配的地址是从0x0800 0000~0x0801 FFFF,应该是对应128KB的flash吧,都是2的17次方,需要17个二进制位表示
看启动文件
Stack_Size      EQU     0x00000400
Heap_Size       EQU     0x00000200
这里有个疑问:
它的意思是堆是2的10次方个字节,1KB?栈是2的11次方个字节,是10KB?


第二个疑问,这个堆和栈是在flash里还是在SRAM里?
第三个疑问,自动变量、静态变量、寄存器变量、全局变量是保存在什么位置,是这个flash吗?
第四个疑问,20KB的SRAM用来保存什么内容,代码保存在哪里地方?
对这些基础概念不懂,谢谢




回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2018-11-9 15:43:55 | 显示全部楼层
1、0x200 = 512字节,  0x400 = 1024字节
2、SRAM
3、在SRAM里面
4、保证变量,代码保存在flash。

有时间可以学习下我们的入门视频教程:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=15408

堆栈章节和map文件章节,非常清晰的讲解了这些问题
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-9 16:03:24 | 显示全部楼层
eric2013 发表于 2018-11-9 15:43
1、0x200 = 512字节,  0x400 = 1024字节
2、SRAM
3、在SRAM里面

谢谢,我研究研究
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-9 16:12:17 | 显示全部楼层
eric2013 发表于 2018-11-9 15:43
1、0x200 = 512字节,  0x400 = 1024字节
2、SRAM
3、在SRAM里面

我发现我程序里定义一个3000个字节的数组,还是外部数组
uint8_t Sendbuff[3000]={0};//定义外部变量数组
它的数量已经超过了0x200 0x400了,为啥没有崩溃呢
回复

使用道具 举报

36

主题

2040

回帖

2148

积分

至尊会员

积分
2148
发表于 2018-11-9 17:04:49 | 显示全部楼层
伊森亨特 发表于 2018-11-9 16:12
我发现我程序里定义一个3000个字节的数组,还是外部数组
uint8_t Sendbuff[3000]={0};//定义外部变量数 ...

学习老大楼上给你发的堆栈章节,这个使用的不是堆栈空间。
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-15 09:17:49 | 显示全部楼层
byccc 发表于 2018-11-9 17:04
学习老大楼上给你发的堆栈章节,这个使用的不是堆栈空间。

外部变量使用的rom,也就是flash啊。我在定义内部数组试试
回复

使用道具 举报

0

主题

105

回帖

105

积分

初级会员

积分
105
发表于 2018-11-15 09:42:13 | 显示全部楼层
伊森亨特 发表于 2018-11-15 09:17
外部变量使用的rom,也就是flash啊。我在定义内部数组试试

你走歪了。可变的变量使用的都是ram。
你应该了解一下堆、栈、以及静态空间的分布及什么时候被使用。
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-15 11:16:51 | 显示全部楼层
本帖最后由 伊森亨特 于 2018-11-15 11:28 编辑

测试了一下,外部变量使用的是SRAM,起始地址0x2000 0000,但是应该不是堆栈中吧,应该是静态存储区,而且栈是0x400,堆是0x200,一共才1536个字节,放不下这好几千。当外部数组5000的时候会提示错误信息,4500的时候还不会提示错误信息。
u32 array[4500]={50000};
这时候5000*4=20000个字节,SRAM是20KB,20480个字节,还剩480个字节估计当作别用了。
错误信息如下:
.\output\template.axf: Error: L6406E: No space in execution regions with .ANY selector matching startup_stm32f10x_md.o(STACK).
.\output\template.axf: Error: L6406E: No space in execution regions with .ANY selector matching startup_stm32f10x_md.o(HEAP).
.\output\template.axf: Error: L6406E: No space in execution regions with .ANY selector matching libspace.o(.bss).
.\output\template.axf: Error: L6406E: No space in execution regions with .ANY selector matching system_stm32f10x.o(.data).
.\output\template.axf: Error: L6406E: No space in execution regions with .ANY selector matching stm32f10x_rcc.o(.data).
.\output\template.axf: Error: L6407E: Sections of aggregate size 0x688 bytes could not fit into .ANY selector(s).

放在函数内部,定义局部数组的时候,通过call+stack窗口发现array的地址是0x1FFF FEB8,查看手册,这个地址也不知道干什么,system memory
大数组溢出.png
内存地址.png
发现函数内数组定义到410个元素的时候,会进入硬件失效,地址0x1FFF FFF8,整个数组需要空间是410*4=1640个字节,栈空间是1024个字节,为什么超出这么多才出现问题呢?见下图 内部变量溢出.png
@eric2013
自动变量溢出.png
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-15 11:27:14 | 显示全部楼层
barryxiao 发表于 2018-11-15 09:42
你走歪了。可变的变量使用的都是ram。
你应该了解一下堆、栈、以及静态空间的分布及什么时候被使用。

看我新的楼层,我在函数内部定义410个元素的数组,u32位,这就是410*4=1640个字节,这应该是在栈中,栈是0x400,1024个字节,已经超了好多个字节。这是什么情况
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-15 11:31:57 | 显示全部楼层
eric2013 发表于 2018-11-9 15:43
1、0x200 = 512字节,  0x400 = 1024字节
2、SRAM
3、在SRAM里面

我看过了,然后试验一下,
我在函数内部定义410个元素的数组,u32位,这就是410*4=1640个字节,这应该是在栈中,栈是0x400,1024个字节,已经超了好多个字节,还可以正常调试;
内部定义420个元素的数组,u32位,这就是420*4=1680个字节,这时进入硬件失效
这是什么原因呢,为啥超过了栈的空间还是可以调试,他是用了堆的空间吗?谢谢
回复

使用道具 举报

0

主题

105

回帖

105

积分

初级会员

积分
105
发表于 2018-11-15 17:48:10 | 显示全部楼层
本帖最后由 barryxiao 于 2018-11-15 17:51 编辑
伊森亨特 发表于 2018-11-15 11:31
我看过了,然后试验一下,
我在函数内部定义410个元素的数组,u32位,这就是410*4=1640个字节,这应该是 ...

stm32的栈空间是向下生长的,MDK在链接的时候把栈空间起始放在了你使用的RAM的末尾(注意,不是总RAM)。
例如你stack size=0x200,你其他的使用数据量是0x1000字节,那么最开始的时候sp指针就在0x20001200,然后你函数运行的时候,每定义了一个变量,sp就往前(0x20000000的方向)走一截。如果走到超过了stack空间长度(到了0x20001000),再定义就极有可能覆盖掉前面的数据,但硬件并不会出错,因为从CPU的角度来看你要访问的地方是正确的,还处在CPU可访问的范围内
C语言本身对栈空间是不做检查的,编译器也没检查。所以不会出错。如果你用了操作系统,可以用操作系统来检查栈空间使用。就是在使用到的栈末尾写入一个特殊的数字,定期检查这个数字被推到了哪个位置

我一个程序的使用示例,“使用内存”指的是除stack外的所有变量,包括静态变量、全局变量、heap等

我的一个程序示例

我的一个程序示例


回复

使用道具 举报

0

主题

105

回帖

105

积分

初级会员

积分
105
发表于 2018-11-15 18:03:57 | 显示全部楼层
伊森亨特 发表于 2018-11-15 11:31
我看过了,然后试验一下,
我在函数内部定义410个元素的数组,u32位,这就是410*4=1640个字节,这应该是 ...

如果你定义的时候sp指针顶到了0x20000000更往下,这在CM3和CM4的内存划分里是属于code区,属于启动映射需要考虑的范围,不同的启动方式实际对应的区域不一样。
可能会触发总线错误,具体的中断是hard_fault还是bus_fault我不确定了
Snipaste_2018-11-15_17-57-42.png
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-16 11:57:42 | 显示全部楼层
barryxiao 发表于 2018-11-15 17:48
stm32的栈空间是向下生长的,MDK在链接的时候把栈空间起始放在了你使用的RAM的末尾(注意,不是总RAM)。 ...

谢谢。我想我明白你的意思了。虽然超过0x200,但是因为之前用了一部分SRAM内容,所以栈不是从0x2000 0000开始,可以占用别的地方的SRAM,所以不会报错,可以正常;但是用的太多,超过了0x2000 0000,就跑到了别的区域,就报错了。
第二个就是SP是堆栈指针,它指向栈顶,就是说用了多少栈空间呗,628+122836=123464,RW是初始化为0的全局变量,ZI是未初始化的全局变量和初始化为0的全局变量。为啥是除了栈以外的所有变量呢,把heap算上了,没算stack。
ZI是编译之后才存在的吗?感觉抽象不好理解
回复

使用道具 举报

0

主题

105

回帖

105

积分

初级会员

积分
105
发表于 2018-11-16 13:34:15 | 显示全部楼层
伊森亨特 发表于 2018-11-16 11:57
谢谢。我想我明白你的意思了。虽然超过0x200,但是因为之前用了一部分SRAM内容,所以栈不是从0x2000 0000 ...

你忽略了我说的栈生长方向。
无论在stack之前有没有定义SRAM,SP都不是从0x20000000开始,而是从你用到的SRAM尾部开始
MDK编译的结果sp指针是一个向下生长的,意思是sp从0x20001200是栈底,栈顶在0x20001000位置,生长方向是地址数字减小的方向。大于0x20001200以后的SRAM没有被使用。0x20000000+0x1200数字是你使用的SRAM总量。
ZI/RW都是编译完成后在链接阶段安排的。ZI和RW的区别只在于是否进行了默认初始化,属于操作流程上的区别,在内存中的本质是一样的,不用区别对待
建议你画一下内存分段的图,分析一下mdk编译出来的**.map文件。弄一个小工程,只分析SRAM的安排还是不难的
回复

使用道具 举报

32

主题

103

回帖

199

积分

高级会员

积分
199
 楼主| 发表于 2018-11-18 21:31:31 | 显示全部楼层
barryxiao 发表于 2018-11-16 13:34
你忽略了我说的栈生长方向。
无论在stack之前有没有定义SRAM,SP都不是从0x20000000开始,而是从你用到 ...

zi rw 计算的都是全局变量吧,map文件里可以看到
局部变量在stack里,在map文件里还看不到,需要在调试时候能看到,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-13 04:24 , Processed in 0.212414 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表