參考文獻:https://www.rt-thread.org/document/site/programming-manual/basic/basic/
一般 MCU 包含的存儲空間有:片內 Flash 與片內 RAM,RAM 相當於內存,Flash 相當於硬盤。編譯器會將一個程序分類為好幾個部分,分別存儲在 MCU 不同的存儲區。
Keil 工程在編譯完之后,會有相應的程序所占用的空間提示信息,如下所示:
linking... Program Size: Code=48008 RO-data=5660 RW-data=604 ZI-data=2124 After Build - User command \#1: fromelf --bin.\\build\\rtthread-stm32.axf--output rtthread.bin ".\\build\\rtthread-stm32.axf" - 0 Error(s), 0 Warning(s). Build Time Elapsed: 00:00:07
上面提到的 Program Size 包含以下幾個部分:
1)Code: 代碼段,存放程序的代碼部分
2)RO-data:只讀數據段, 存放程序中定義的常量;
3)RW-data: 讀寫數據段,存放初始化為非0值的全局變量
4)ZI-data: 零數據段,存放未初始化的全局變量及初始化為0的變量;
編譯完工程會生成一個. map 的文件,該文件說明了各個函數占用的尺寸和地址,在文件的最后幾行也說明了上面幾個字段的關系:
Total RO Size (Code + RO Data) 53668 ( 52.41kB) Total RW Size (RW Data + ZI Data) 2728 ( 2.66kB) Total ROM Size (Code + RO Data + RW Data) 53780 ( 52.52kB)
1) RO Size 包含了 Code 及 RO-data,表示程序占用Flash空間的大小
2)RW Size 包含了RW-data及ZI-data,表示運行時占用的RAM的大小
3)ROM Size 包含了Code, RO Data以及RW Data, 表示燒寫程序所占用的Flash空間的大小
程序運行之前,需要有文件實體被燒錄到 STM32 的 Flash 中,一般是 bin 或者 hex 文件,該被燒錄文件稱為可執行映像文件。如圖 3-3 中左圖所示,是可執行映像文件燒錄到 STM32 后的內存分布,它包含 RO 段和 RW 段兩個部分:其中 RO 段中保存了 Code、RO-data 的數據,RW 段保存了 RW-data 的數據,由於 ZI-data 都是 0,所以未包含在映像文件中。
STM32 在上電啟動之后默認從 Flash 啟動,啟動之后會將 RW 段中的 RW-data(初始化的全局變量)搬運到 RAM 中,但不會搬運 RO 段,即 CPU 的執行代碼從 Flash 中讀取,另外根據編譯器給出的 ZI 地址和大小分配出 ZI 段,並將這塊 RAM 區域清零

其中動態內存堆為未使用的 RAM 空間,應用程序申請和釋放的內存塊都來自該空間。
如下面的例子:
rt_uint8_t* msg_ptr; msg_ptr = (rt_uint8_t*) rt_malloc (128); rt_memset(msg_ptr, 0, 128);
代碼中的 msg_ptr 指針指向的 128 字節內存空間位於動態內存堆空間中。
而一些全局變量則是存放於 RW 段和 ZI 段中,RW 段存放的是具有初始值的全局變量(而常量形式的全局變量則放置在 RO 段中,是只讀屬性的),ZI 段存放的系統未初始化的全局變量,如下面的例子:
#include <rtthread.h> const static rt_uint32_t sensor_enable = 0x000000FE; rt_uint32_t sensor_value; rt_bool_t sensor_inited = RT_FALSE; void sensor_init() { /* ... */ }
sensor_value 存放在 ZI 段中,系統啟動后會自動初始化成零(由用戶程序或編譯器提供的一些庫函數初始化成零)。sensor_inited 變量則存放在 RW 段中,而 sensor_enable 存放在 RO 段中。
