摘要:物聯網嵌入式芯片,存儲是數據核心之一,這個對於編程和設計的人來說又比較陌生,今天來說說MCU中的內存結構。
本文分享自華為雲社區《漫談嵌入式系統的內存》,作者:o0龍龍0o 。
前言
物聯網嵌入式芯片,存儲是數據核心之一,這個對於編程和設計的人來說又比較陌生,今天來說說MCU中的內存結構
1、存儲器形式
MCU的存儲器從存儲特性上分為:易失性存儲器、非易失性存儲器,即常說的Volatile memory和Non-volatile memory
隨機存取存儲器 :1、DRAM(動態隨機存儲器)、2、SRAM(靜態隨機存儲器)一般MCU的內存多采用SRAM構成,主要原因是速度快、結構簡單。
非易失性存儲器(Non-volatile memory)是指即使電源供應中斷,存儲器所存儲的資料並不會消失,重新供電后,就能夠讀取存儲器中的資料。 主要種類如下:
- 只讀存儲器(ROM)
- 可編程式只讀存儲器(PROM)
- 可擦除可規划式只讀存儲器(EPROM)
- 電子抹除式可復寫只讀存儲器(EEPROM)
- Flash ROM
- 磁存儲、硬盤、軟盤、磁帶、3D XPoint、固態硬盤、光存儲、光盤
其中 PROM、Flash一般作為MCU數據程序存儲器,不過現在也有很多MCU內掛EEPROM,方便用戶寫入臨時數據。
可擦除可編程式只讀存儲器
是一種斷電后仍能保留數據的計算機存儲芯片、它是一組浮柵晶體管,被一個提供比電子電路中常用電壓更高電壓的電子器件分別編程。一旦資料寫入完成后,EPROM只能用強紫外線照射來擦除。我們常說的24C芯片就是這類的存儲器芯片,他可以按照Byte去擦鞋數據,比按照扇區擦寫的Flash效果高很多。
2、數據存儲
內存的數據一般可以分為堆、棧、程序代碼、數據代碼、全局變量代碼
一般如下分布:
堆內存(也稱內存池)的起始地址及堆區域總大小是LiteOS對程序堆的解釋,就是一段AP程序所占用的內存大小,這些大小由鏈表或是二叉樹組成,用於該程序段內存的占用。
棧——堆棧(:stack)又稱為棧或堆疊,是計算機科學中的一種抽象資料類型,只允許在有序的線性資料集合的一端(稱為堆棧頂端,:top)進行加入數據(:push)和移除數據(:pop)的運算。因而按照后進先出(LIFO, Last In First Out)的原理運作。在MCU由系統LiteOS對剩余內存進行分配用於程序的局部變量的使用和數據malloc產生新分配的內存。
bss段:(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。bss是英文Block Started by Symbol的簡稱。bss段屬於靜態內存分配。
data段:數據段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬於靜態內存分配。
text段:代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域,一般存放在ROM中。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀(某些架構也允許代碼段為可寫,即允許修改程序)。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。
我么編程時很少會設計到這些的設計,往往是由系統LiteOS自動完成或是由編譯器完成。
3、如何利用程序設計內存呢?
宏命令:
#pragma alloc_text( "textsection", function1, ... )
命名特別定義的函數駐留的代碼段。該編譯指示必須出現在函數說明符和函數定義之間。
#pragma code_seg( ["section-name"[,"section-class"] ] )
指定分配函數的代碼段。code_seg編譯指示為函數指定默認的段。你也能夠像段名一樣指定一個可選的類名。使用沒有段名字符串的#pragma code_seg將恢復分配到編譯開始時候的狀態。
#pragma const_seg( "MY_DATA" )
導致在#pragma語句后面的常量數據分配在一個叫做MY_DATA的段中。
#pragma const_seg( ["section-name"[, "section-class"] ] )
指定用於常量數據的默認段。data_seg編譯指示除了可以工作於所有數據以外具有一樣的效果。你能夠使用該編譯指示將你的常量數據保存在一個只讀的段中。