RT-Thread 程序內(nèi)存分布
一般 MCU 包含的存儲(chǔ)空間有:片內(nèi) Flash 與片內(nèi) RAM,RAM 相當(dāng)于內(nèi)存,F(xiàn)lash 相當(dāng)于硬盤。編譯器會(huì)將一個(gè)程序分類為好幾個(gè)部分,分別存儲(chǔ)在 MCU 不同的存儲(chǔ)區(qū)。
Keil 工程在編譯完之后,會(huì)有相應(yīng)的程序所占用的空間提示信息,如下所示:
linking...
Program Size: Code=47364 RO-data=5348 RW-data=608 ZI-data=2112
FromELF: creating hex file...
After Build - User command #1: fromelf --bin .\build\rtthread-stm32.axf --output rtthread.bin
".\build\rtthread-stm32.axf" - 0 Error(s), 1 Warning(s).
Build Time Elapsed: 00:01:15
上面提到的 Program Size 包含以下幾個(gè)部分:
1)Code:代碼段,存放程序的代碼部分;
2)RO-data:只讀數(shù)據(jù)段,存放程序中定義的常量;
3)RW-data:讀寫數(shù)據(jù)段,存放初始化為非 0 值的全局變量;
4)ZI-data:0 數(shù)據(jù)段,存放未初始化的全局變量及初始化為 0 的變量;
編譯完工程會(huì)生成一個(gè). map 的文件,該文件說(shuō)明了各個(gè)函數(shù)占用的大小和地址,在文件的最后幾行也說(shuō)明了上面幾個(gè)字段的關(guān)系:
Code (inc. data) RO Data RW Data ZI Data Debug
47364 6182 5348 608 2112 708864 Grand Totals
47364 6182 5348 108 2112 708864 ELF Image Totals (compressed)
47364 6182 5348 108 0 0 ROM Totals
==============================================================================
Total RO Size (Code + RO Data) 52712 ( 51.48kB)
Total RW Size (RW Data + ZI Data) 2720 ( 2.66kB)
Total ROM Size (Code + RO Data + RW Data) 52820 ( 51.58kB)
1)RO Size 包含了 Code 及 RO-data,表示程序占用 Flash 空間的大??;
2)RW Size 包含了 RW-data 及 ZI-data,表示運(yùn)行時(shí)占用的 RAM 的大?。?/p>
3)ROM Size 包含了 Code、RO Data 以及 RW Data,表示燒寫程序所占用的 Flash 空間的大?。?/p>
程序運(yùn)行之前,需要有文件實(shí)體被燒錄到 STM32 的 Flash 中,一般是 bin 或者 hex 文件,該被燒錄文件稱為可執(zhí)行映像文件。如下圖所示,是可執(zhí)行映像文件燒錄到 STM32 后的內(nèi)存分布,它包含 RO 段和 RW 段兩個(gè)部分:其中 RO 段中保存了 Code、RO-data 的數(shù)據(jù),RW 段保存了 RW-data 的數(shù)據(jù),由于 ZI-data 都是 0,所以未包含在映像文件中。
STM32 在上電啟動(dòng)之后默認(rèn)從 Flash 啟動(dòng),啟動(dòng)之后會(huì)將 RW 段中的 RW-data(初始化的全局變量)搬運(yùn)到 RAM 中,但不會(huì)搬運(yùn) RO 段,即 CPU 的執(zhí)行代碼從 Flash 中讀取,另外根據(jù)編譯器給出的 ZI 地址和大小分配出 ZI 段,并將這塊 RAM 區(qū)域清零。

其中動(dòng)態(tài)內(nèi)存堆為未使用的 RAM 空間,應(yīng)用程序申請(qǐng)和釋放的內(nèi)存塊都來(lái)自該空間。
如下面的例子:
rt_uint8_t* msg_ptr;
msg_ptr = (rt_uint8_t*) rt_malloc (128);
rt_memset(msg_ptr, 0, 128);
代碼中的 msg_ptr 指針指向的 128 字節(jié)內(nèi)存空間位于動(dòng)態(tài)內(nèi)存堆空間中。
而一些全局變量則是存放于 RW 段和 ZI 段中,RW 段存放的是具有初始值的全局變量(而常量形式的全局變量則放置在 RO 段中,是只讀屬性的),ZI 段存放的系統(tǒng)未初始化的全局變量,如下面的例子:
#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 段中,系統(tǒng)啟動(dòng)后會(huì)自動(dòng)初始化成零(由用戶程序或編譯器提供的一些庫(kù)函數(shù)初始化成零)。
sensor_inited 變量則存放在 RW 段中
sensor_enable 存放在 RO 段中。