1.stm32内存空间分配图
Stm32的keil编译连接如上图所示。
编译信息包含以下几个部分:
1)Code: 代码段,存放程序的代码部分
2)RO-data:只读数据段, 存放程序中定义的常量;
3)RW-data: 读写数据段,存放初始化为非0值的全局变量
4)ZI-data: 零数据段,存放未初始化的全局变量及初始化为0的变量;
编译完工程会生成一个. map 的文件,该文件说明了各个函数占用的尺寸和地址,在文件的最后几行也说明了上面几个字段的关系:
Total RO Size (Code + RO Data) 46052 ( 44.97kB)
Total RW Size (RW Data + ZI Data) 36552 ( 35.70kB)
Total ROM Size (Code + RO Data + RW Data) 46212 ( 45.13kB)
1)RO Size 包含了 Code 及 RO-data,表示程序占用Flash空间的大小
2)RW Size 包含了RW-data及ZI-data,表示运行时占用的RAM的大小
3)ROM Size 包含了Code, RO Data以及RW Data, 表示烧写程序所占用的Flash空间的大小
//变量放在在指定地址无初始值 这个地址值一要比较已初始变量的地址大,不然编译不通过(比RW-data 数据大),因为ZI-data(未初始化区)是连接空间
INT32U ramIapFlag1__attribute__((at(0x2000007c)));//( 因为内存地址是从0x2000000开始偏移的,所以定义的地址不小于0x2000007c)
//变量放在在指定地址有初始值,这个要在Rw-data之内,所以定义范围在0x20000000~0x20000078之间
INT32U ramIapFlag2__attribute__((at(0x20000078))) = 8;
因为STM32程序编译完的二进制文件的头4字节是栈指针,如上图所示,其值会为0x20000568 ,若其芯片是64K内存,那么其高地址0x20003f99~0x2010000则是空闲区域
堆和栈空间分配
栈:向低地址扩展
堆:向高地址扩展
原始编译信息
Program Size: Code=44052 RO-data=1992 RW-data=448 ZI-data=35336
int mem_test = 1;//增加一个全局变量并已初始化后的编译信息
Program Size: Code=44060 RO-data=1992 RW-data=452 ZI-data=35332
说明增加一个全局已初始化变量,是定义在RW-data区域
int mem_test;//增加一个全局未初始化变量后的编译信息
Program Size: Code=44060 RO-data=1992 RW-data=452 ZI-data=35332
const int mem_test=232;//增加一个全局const变量后的编译信息
Program Size: Code=44060 RO-data=1992 RW-data=448 ZI-data=35336
Stack_Size由0x400改成0x600后的编译信息,栈的增加影响的是ZI-data段内存,即栈的空间在ZI-data段内
Stack_Size EQU 0x00000600
Program Size: Code=44060 RO-data=1992 RW-data=448 ZI-data=35848
Heap_Size 由0x200改成0x500后的编译信息,堆的增加影响的是ZI-data段内存,即堆的空间也是在ZI-data段内
Heap_Size EQU 0x00000500
Program Size: Code=44060 RO-data=1992 RW-data=448 ZI-data=36104
2在应用程序中检测栈使用多少的方法2.1在引导startup_stm32f10x_*.s文件导出Stack_Mem,__initial_sp两个变量如以下代码
EXPORT Stack_Mem ;导出栈底.
EXPORT __initial_sp ;导出栈顶.
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE,
Stack_Mem SPACE Stack_Size
__initial_sp
2.2在应用程序中添加以下检测函数
void DebugCheckStackFun(void)
{
extern INT32U Stack_Mem[]; //主堆栈栈底.在启动文件中定义.
extern INT32U __initial_sp[]; //主堆栈栈顶.在启动文件中定义.
static INT32U s_uMStackMaxUse =0; //主堆栈最大使用量.字节数.
INT32U * puMStack; //用它指向主堆栈.进行检查.
INT32U uMStackSize; //主堆栈尺寸.
INT32U uMStackUse; //主堆栈当前使用量.字节数.
uMStackSize = (INT32U)__initial_sp - (INT32U)Stack_Mem; //主堆栈尺寸.
puMStack = Stack_Mem; //从栈底开始检查.
while (*puMStack++ == 0); //找到第一个不为0的数.退出时,puMStack指向该数的下一位置.
puMStack--; //退回到第一个不为0的数位置.
uMStackUse = (INT32U)__initial_sp - (INT32U)puMStack; //堆栈使用量.
if (uMStackUse > s_uMStackMaxUse) //记录最大使用量.
{
s_uMStackMaxUse = uMStackUse;
Uartprintf("s_uMStackMaxUse= %d \n",s_uMStackMaxUse);
}
if (uMStackUse > (uMStackSize- 0X0080)) //堆栈快用完了.
{
}
}
3.stm32实现软件复位的函数
__set_FAULTMASK(1);//关闭所有中端
NVIC_SystemReset();//复位
4.往指定位置读/写内容
//*(int *)addr = 0x55aa55bb;
//__STREXW(0x235a,(int *)&addr);
*(int *)addr = 0x55aa55bb;
var = __LDREXW((int *)addr);
参考网址:
http://www.cppblog.com/prayer/archive/2009/08/17/93594.html
http://blog.163.com/yangqinghua_lw/blog/static/169081872007101325210429/
http://wenku.baidu.com/view/d63ffc0a4a7302768e9939ca.html
http://blog.csdn.net/ha123123/article/details/8900775
https://www.cnblogs.com/linux-37ge/p/11964434.html