編排 | strongerHuang ? 看到有小伙伴在討論關(guān)于單片機內(nèi)存的話題,今天就結(jié)合STM32給大家描述一下常見的劃分區(qū)域。 ?
在一個STM32程序代碼中,從內(nèi)存高地址到內(nèi)存低地址,依次分布著棧區(qū)、堆區(qū)、全局區(qū)(靜態(tài)區(qū))、常量區(qū)、代碼區(qū),其中全局區(qū)中高地址分布著.bss段,低地址分布著.data段。 ?
總的分布如下所示:
內(nèi)存高地址 | 棧區(qū) |
? | 堆區(qū) |
.bss段 | |
.data段 | |
常量區(qū) | |
內(nèi)存低地址 | 代碼區(qū) |
? 一、棧區(qū)(stack)
臨時創(chuàng)建的局部變量存放在棧區(qū)。
函數(shù)調(diào)用時,其入口參數(shù)存放在棧區(qū)。
函數(shù)返回時,其返回值存放在棧區(qū)。
const定義的局部變量存放在棧區(qū)。
2、堆區(qū)(heap)
堆區(qū)用于存放程序運行中被動態(tài)分布的內(nèi)存段,可增可減。
可以有malloc等函數(shù)實現(xiàn)動態(tài)分布內(nèi)存。
有malloc函數(shù)分布的內(nèi)存,必須用free進行內(nèi)存釋放,否則會造成內(nèi)存泄漏。 ?
3、全局區(qū)(靜態(tài)區(qū))
全局區(qū)有.bss段和.data段組成,可讀可寫。 ?
4、.bss段
未初始化的全局變量存放在.bss段。
初始化為0的全局變量和初始化為0的靜態(tài)變量存放在.bss段。
.bss段不占用可執(zhí)行文件空間,其內(nèi)容有操作系統(tǒng)初始化。 ?
5、.data段
已經(jīng)初始化的全局變量存放在.data段。
靜態(tài)變量存放在.data段。
.data段占用可執(zhí)行文件空間,其內(nèi)容有程序初始化。
const定義的全局變量存放在.rodata段。 ?
6、常量區(qū)
字符串存放在常量區(qū)。 常量區(qū)的內(nèi)容不可以被修改。 ?
7、代碼區(qū)
程序執(zhí)行代碼存放在代碼區(qū)。 字符串常量也有可能存放在代碼區(qū)。 ?
通過上面的介紹,可能你對各個數(shù)據(jù)的存儲位置還是很模糊,下面通過一個簡單的程序,再來體會理解一下。 ?
通過上面的介紹,可能你對各個數(shù)據(jù)的存儲位置還是很模糊,下面通過一個簡單的程序,再來體會理解一下
【多余一段】
?
#include上面我們已經(jīng)對堆、棧、全局區(qū)、常量區(qū)、代碼區(qū)進行了全面的分析,也舉例進行了說明。static unsigned int val1 = 1; //val1存放在.data段 unsigned int val2 = 1; //初始化的全局變量存放在.data段 unsigned int val3 ; //未初始化的全局變量存放在.bss段 const unsigned int val4 = 1; //val4存放在.rodata(只讀數(shù)據(jù)段) unsigned char Demo(unsigned int num) //num 存放在棧區(qū) { ??char?var?=?"123456";???????????????//var存放在棧區(qū),"123456"存放在常量區(qū) ??unsigned?int?num1?=?1?;????????????//num1存放在棧區(qū) ??static?unsigned?int?num2?=?0;??????//num2存放在.data段 ??const?unsigned?int?num3?=?7;???????//num3存放在棧區(qū) ??void?*p; ??p?=?malloc(8);?????????????????????//p存放在堆區(qū) ??free(p); return 1; } void main() { unsigned int num = 0 ; num = Demo(num); //Demo()函數(shù)的返回值存放在棧區(qū)。 }
下面我們在對這些區(qū)存放在哪種介質(zhì)上進行討論。 ?
8、RAM和ROM、Flash Memory的物理特性
首先,我們需要明白RAM和ROM、Flash Memory的物理特性。 ?
9、RAM
RAM又稱隨機存取存儲器,存儲的內(nèi)容可通過指令隨機讀寫訪問。
RAM中的存儲的數(shù)據(jù)在掉電是會丟失,因而只能在開機運行時存儲數(shù)據(jù)。
其中RAM又可以分為兩種,一種是Dynamic RAM(DRAM動態(tài)隨機存儲器),另一種是Static RAM(SRAM,靜態(tài)隨機存儲器)。 ?
10、ROM
ROM又稱只讀存儲器,只能從里面讀出數(shù)據(jù)而不能任意寫入數(shù)據(jù)。ROM與RAM相比,具有讀寫速度慢的缺點。但由于其具有掉電后數(shù)據(jù)可保持不變的優(yōu)點,因此常用也存放一次性寫入的程序和數(shù)據(jù),比如主版的BIOS程序的芯片就是ROM存儲器。 ?
11、Flash Memory
由于ROM具有不易更改的特性,后面就發(fā)展了Flash Memory。Flash Memory不僅具有ROM掉電不丟失數(shù)據(jù)的特點,又可以在需要的時候?qū)?shù)據(jù)進行更改,不過價格比ROM要高。 ?
12、不同數(shù)據(jù)的存放位置
由前面的分析我們知道,代碼區(qū)和常量區(qū)的內(nèi)容是不允許被修改的,ROM(STM32就是Flash Memory)也是不允許被修改的,所以代碼區(qū)和常量區(qū)的內(nèi)容編譯后存儲在ROM中。 ?
而棧、堆、全局區(qū)(.bss段、.data段)都是存放在RAM中。 ?
至此,關(guān)于不同數(shù)據(jù)存放哪個區(qū)域已經(jīng)全部介紹完了。
下面還將介紹一下Keil 的Build Output窗口。 ?
13、Keil 的Build Output窗口

如上圖,存在Code、RO-data、RW-data、ZI-data四個代碼段大小。 ?
其中Code就是代碼占用大小,RO-data是只讀常量、RW-data是已初始化的可讀可寫變量,ZI-data是未初始化的可讀可寫變量。 ?
有些時候,我們需要知道RAM和ROM的使用情況如何,那么我們就可以使用下面的公式計算。 ?
RAM? = RW-data + ZI-data ROM = Code + RO-data + RW-data?
?
審核編輯:劉清
評論