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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章