KEIL编译程序后报下边错误:
原因是因为代码的全局变量太多或全局的数组太大导致程序编译后RAM溢出,建议先查看有没有比较大的全局数组
BootLoader\BootLoader.axf: Error: L6406E: No space in execution
regions with .ANY selector matching startup_stm32f103xb.o(STACK). …
BootLoader\BootLoader.axf: Error: L6407E: Sections of aggregate size
0x768 bytes could not fit into .ANY selector(s). Not enough
information to list image symbols. Not enough information to list load
addresses in the image map. Finished: 2 information, 0 warning and 17
error messages.
程序编译没错 运行时报错:
最常见的两个问题:
1:指针越界或者空指针
》数组指针越界死机一般存在两种情况 :直接死机或者添加其他代码时死机,原因是开始程序比较简单时数组越界访问的地址是有效可访问的地址此时越界是不会死机的,但添加其他代码运行后代码突然死机就是访问到了不可访问的地址就死机,一般此类问题原因比较难查:只能一层层的代码过滤找到死机的函数,最终确认越界的数组指针。2:栈溢出:函数中存在比较打的 局部数组 ,像读flash一般定义4k数组
3:ram(堆)要是不够用,可以把一些常量数组值前+const
(有些单片机会把常量放进flash而不是ram)
常用的stm32单片机:
stm32f103ret6:大片 Flash:512k ram:64k rom:512k
stm32f103c8t6 :小片 Flash:128k ram:20k rom:64k
keil编写后程序占ram rom (https://blog.youkuaiyun.com/WIP56/article/details/118936794?spm=1001.2014.3001.5502)
Program Size: Code=13004 RO-data=292 RW-data=64 ZI-data=18976
其中:rom=Code+ RO-data + RW-data
ram=RW-data+ ZI-data
我用的是stm32f103c8t6 小片,ram= 20k,程序中有两个比较大的全局数组arr[4096],调用使用这个数组的函数,编译直接报上边这些错误。
原因是: RW-data+ ZI-data>20k
修改办法:
1:换用大片
2:减少全局变量与数组的大小
附加:
1.stm32数据手册
STM32小容量,中等容量和大容量的型号区别
因为STM32F103xx是一个完整的系列,其成员之间是完全地脚对脚兼容,软件和功能上也兼容。在参考手册中,STM32F013x4和STM32F103x6被归为小容量产品,STM32F103x8和STM32F103xB被归为中等容量产品,STM32F103xC,STM32103xD和STM32F103xE被归为大容量产品
2. 单片机内存区域划分
链接
3.编译参数的意义:
Program Size: Code=13004 RO-data=292 RW-data=64 ZI-data=18976
1、Code 是代码占用的内存。
2、RO-data是 Read Only 只读常量的大小,如const型。
3、RW-data是(Read Write) RW是可读可写变量,就是初始化时候就已经赋值了的,RW + ZI就是你的程序总共使用的RAM字节数。
4、ZI-data是(Zero Initialize) 没有初始化的可读写变量的大小,就是程序中用到的变量并且被系统初始化为0的变量的字节数,keil编译器默认是把你没有初始化的变量都赋值一个0,这些变量在程序运行时是保存在RAM中的。
程序编译后:.lcf、.adx、.map文件中字段解释 .data,.sdata,.rodata,.sbss ,.text
ELF文件说明 汇编伪操作指令
.data 是指初始化段 表示已经初始化的全局变量和静态变量,需要占用内存空间以保存初始值
.sdata是指smll data初始化段(小于多少可以算small data,可以在codewarrior中设置)
.rodata表示只读数据,如程序中用到的字符串常量,printf中的格式串,switch语句中的跳转表等
.sbss 是指small data未初始化段。
.text是代码段,如函数指针指向的就是这个区域
写代码时注意事项
Flash用来存储机器代码,常量,初始化值不为0的全局变量,而且程序运行是在Flash中;
RAM:用来存储初始化值为0的全局变量,以及静态变量(模块内部或者函数内部),堆和栈。
STM32微控制器包含的存储单元如下所示:
Main memory block:Flash,地址为0x8000000,RAM,地址为0x20000000
System storage block:this area is used to store the code about bootloader which is used to upgrade firmware,地址为0x1FFF0000。
OTP area:One Time Programmable area
Optional bytes:
如何选择系统从哪个区域运行代码?
系统开机上电或者硬件复位后会根据BOOT pin进行判断,如果BOOT pin为低电平,则系统从Flash中运行代码(地址为:0x8000000),如果BOOT pin为高电平,则系统从System storage block运行代码(地址为:0x1FFF0000)。
系统启动文件?
系统的启动文件为Startup_stm32L011XX.s,该文件是汇编语言,用于初始化芯片关键模块,主要包括异常向量表和PC、SP指针。
系统编译之后包含的数据类型?
'
数据类型:
> Ro code:机器代码,存放在Flash中 Ro data:常量,用const修饰的变量,存放在flash中 RW
> data:全局变量,初始化值不为0,存放在flash中,运行时会拷贝到RAM中,RAM运行速度快,节省修改数据时间 ZI
> data:全局变量,初始化值为0,存放在RAM中 ZI stack:栈空间数据,函数内部的局部变量,存放在RAM中 ZI
> heap:堆空间,使用malloc分配,存放在RAM中
'