1. 程式人生 > >stm32內存到底是如何分配的,基於.map文件分析

stm32內存到底是如何分配的,基於.map文件分析

多少 mdk 變量 inf ilo 分享 圖片 嵌入式操作系統 程序編寫

  一直以來本人對MCU的FLASH和SRAM(RAM存儲器一種)是如何分配的只是知道個大概,而不盡祥。不是非常了解內存分配大多數時候對我們進行裸機程序編寫是沒有太大影響的。

但一旦上升到使用嵌入式操作系統,這個問題就難以回避,因為操作系統沒有任何應用編譯之後都要占用至少10幾KB,這對RAM緊張的MCU來說是致命的,

我們要想盡辦法來省RAM,而辦法是基於你知道內存是怎麽分配的。

ps:有些只有10KB RAM的單片機就不要打OS的主意了,還是老老實實的用時間片輪詢吧,效率也是不錯的。

以下偏重RAM的分析

一、已經了解的

如圖是MDK編譯之後的消息

技術分享圖片

從中知道

占用的FLASH = Code + RO-data + RW-data

stm32 FLASH的起始地址是0x08000000,當然也可以自定義起始地址,不過記得在main函數中定義變量後加一句SCB->VTOR=FLASH_BASE | OFFSET;OFFSET是想要偏移的量,可宏定義或直接0xXX。

當然也可以調用庫函數 NVIC_SetVectorTable()進行偏移,效果一樣。IAP升級這樣用的多。

占用的SRAM = RW-data + ZI-data

stm32 SRAM的起始地址是0x20000000。看MDK的魔法棒設置target選項也是可以設置RAM起始地址和大小的,不過一般我不動RAM。

我一般是這樣記憶的,前面3個是給FLASH,後面2個是給SRAM。

含義:

Code :代碼

RO-data :只讀數據,字符串常量(const修飾的)

RW-data:可讀可寫數據,已經初始化的全局變量 或者 static修飾的變量(不管局部變量還是全局變量,沒有顯示地初始化的話會初始化為0)

ZI-data :沒有進行初始化的全局變量

二、基於.map文件的分析,我逐個試出來的結果如下,右邊是.map文件的內容。

技術分享圖片技術分享圖片

PAD是墊子、衛生巾的意思,占用兩個字節,姑且理解為隔開各個段吧。

宏定義、結構體、聯合體、枚舉類型等都屬於代碼。RAM只存放變量。但FLASH不只是存放代碼,還有變量。就是和RAM都有的交集。MDK生成的 RW-data (全局變量、static變量)

這麽多的變量,他們是怎麽排列在RAM中的呢,看上面.map文件中的地址就知道了。就是已初始化的變量在前面,然後跟著是未初始化的全局變量,然後是堆,最後是棧

也就是說棧和堆的起始地址是不可控的,是根據我們程序的全局變量多少計算出來的,一句話,吃剩下的。

三、裁剪棧和堆的大小

1.當我們程序運行到一個函數中莫名其妙的就崩了,進入HardFault_Handler,數組也沒有越界啊。

其中可能的一個原因就是局部變量過多,棧溢出,不夠用了,需要我們Tailor(裁剪)一下RAM。ps:數組越界也屬於棧溢出。在啟動文件中進行裁剪。HardFault_Handler網上也有很多分析方法。

2.例如,如下啟動文件我們可以吧Stack_Size從0x400(1KB)改到0x800(2KB)一般就不會出現崩潰了,如果還崩,那要找找其他原因(是不是函數使用了非法的指針(即非法地址,0xE0000000之類的MCU不認,不能訪問的地址))等等。

3.當然有時候棧加上其他的,大小超過了RAM總大小,編譯器就會提示不夠,就要一點一點加著試。

這時大小超過了RAM總大小,也能從一定程度說明程序設計存在不合理,幾乎用光了RAM。比如全局變量設置的過大,實際沒用這麽多,也設置這麽多,一般多實際最大使用量加2個字節都沒問題。大型的全局變量(即結構體全局變量、聯合體全局變量)過多,重復繁雜,共用率不高。就要逐個文件刪繁就簡,砍掉能砍的全局變量,縮小能縮的結構體,字節對齊,各種看家本領使出來。砍到不能再砍只能考慮砍功能或者換芯片了。

技術分享圖片

四、以後再增加對FREERTOS的內存管理分析

。。。

stm32內存到底是如何分配的,基於.map文件分析