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