首先說一下 MCU 的存儲器組織。
蒙圈,MCU 中常使用的存儲器類型有:FLASH、RAM、ROM(包括EEPROM)
在軟件角度來看,程序和數據的存儲分為以下幾個部分:
注:
1.代碼段和常量段都可以用于保存常量數據,其主要區別是,如果常量可以作為匯編指令的一個操作數,則該常量被編譯進代碼段。如果不能用一個匯編操作數表示,則存于常量段。如 "uchar a=0x05;" 中的 "0x05" 將被編譯成代碼 "mov #0x05, a";如果是 "uchar a[]={0x05, 0x06}" 則 "0x05,0x06" 被放置于常量段, 在初始化 a[] 的時候會有一段匯編指令用于將常量段中的內容拷貝到 a[] 中。
軟件存儲區與硬件存儲器類型是怎么對應的呢?
一般來講如下:
注:
1.MCU 中的 ROM 通常用于存儲制造商信息、控制器型號等信息;
2.對于 x86 體系結構的系統,因為沒有 Flash 類型的存儲器,所以,所有的軟件存儲區最終都加載到內存中,但是其內存是分段的,用戶對不同內存段的訪問權限不同,其代碼段和常量段不可以被用戶修改,如果意外修改則拋出段錯誤異常。
知道了存儲器類型和各存儲區的劃分之后,讓我們來看以下三組程序:
1.
staticvoidProcStr(void)
{
ucharStr[]={"12345"};
}
這段程序中,Str[] 是一個局部數組,其大小為 6,占用的堆棧空間是 2 個字符;"12345" 是常量,被存儲在常量段;Str[] 的初始化過程,相當于從常量區拷貝 6 個字符的數據到棧中,這 6 個字符是"12345\0"。
2.
staticvoidProcStr(void)
{
ucharStr[]="12345";
}
這段程序中,Str[] 是一個局部數組,其大小為 6,占用的堆棧空間是 2 個字符;"12345" 是常量,被存儲在常量段;Str[] 的初始化過程,相當于從常量區拷貝 6 個字符的數據到棧中,這 6 個字符是 "12345\0"。
3.
staticvoidProcStr(void)
{
constuchar*Str="12345";
}
這段程序中沒有數組,唯一的Str 是一個局部指針,其大小為 4(在 32 位系統中),因此這段程序只占用 4(在 32 位系統中)個字符的堆棧空間;"12345"是常量,被存儲在常量段;Str 的初始化過程,是將指針Str 初始化為常量"12345"的地址,后續程序通過指針Str直接訪問常量段,無需內存拷貝過程。
從以上分析可以看出,前兩種方法是一樣的,都需要為局部數據分配存儲空間,并將靜態存儲區的數據拷貝過來,而最后一種方法是通過指針直接訪問靜態數據而無需拷貝。如果字符串長度大于系統中指針的長度,第三種方法將在時間和空間上大大優于前兩種方法(第三種方法極大的節省了堆棧空間,并減少了拷貝數據所用的時間)。
但是,對于 MCU 來說,并不總是第三種方法好,原因在于第三種方法是直接訪問常量段,由上面的表可知,對于將常量存儲于 Flash 的 MCU 來說,訪問常量段要比訪問 RAM 慢得多。因此,如果接下來要頻繁訪問這個字符串,那么,采用前兩種方法在速度上將會更優一些,理由是前兩種方法只需要訪問一次 Flash,而第三種方法則每次都需要訪問 Flash。
當然,如果在接下來的程序中,需要修改字符串Str 中的內容,那就只能采用前兩種方法,第三種方法將會提示錯誤。
特殊說明:今天講的一些內容跟編譯器的特性相關,不同編譯器,甚至相同編譯器的不同版本間存在一定差異。
-
mcu
+關注
關注
146文章
17917瀏覽量
362715 -
存儲器
+關注
關注
38文章
7643瀏覽量
166839 -
編譯器
+關注
關注
1文章
1659瀏覽量
50053
原文標題:嵌入式程序開發需要知道的存儲器知識
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄

存儲器是如何組織的?是如何與處理器總線連接的?
集成鐵電存儲器的MCU有何作用
存儲器與通用寄存器的相關資料下載
相變存儲器(PCM)技術基礎知識
MCU的存儲器介紹

評論