(1条消息) stm32内存空间分配

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

(0)

相关推荐