Cortex-M軟件結(jié)構(gòu)
暑期成長計劃?。?!
信盈達(dá)十大編程——訓(xùn)練營?開營啦~~
點擊下方鏈接,加入學(xué)習(xí)團(tuán)隊,這個暑期成為一個不一樣的自己????
https://t.bilibili.com/682665552784654372?spm_id_from=444.41.0.0
一? 程序映像
程序映像指的是程序存儲器,對于大多數(shù)芯片來講,一般為flash,flash中不僅存儲了用戶的程序代碼還有其它多種軟件部分:
向量表
復(fù)位處理/啟動代碼
C啟動代碼
應(yīng)用代碼
C運行時庫函數(shù)
其它數(shù)據(jù)
1 向量表
ARM Cortex-M處理器的向量表中包含每個異常和中斷的起始地址,而對于Cortex-M0和Cortex-M0+處理器復(fù)位后,向量表定義在存儲器空間的起始位置(地址為0x00000000),向量表的第一個字節(jié)還定義了主棧指針的初始值,向量表是和設(shè)備相關(guān)的(取決于所支持的異常),向量表一般是定義在啟動代碼中。
2 復(fù)位處理/啟動代碼
復(fù)位處理是可選的,若沒有復(fù)位處理,則會直接執(zhí)行C啟動代碼。復(fù)位處理中的代碼在處理器從復(fù)位中退出時會立刻執(zhí)行,有些情況下其中還會存在一些硬件初始化代碼。對于使用CMSIS-CORE(Cortex-M處理器用的軟件架構(gòu))的工程,復(fù)位處理執(zhí)行SystemInit()函數(shù),其會在跳轉(zhuǎn)到C啟動代碼前設(shè)置時鐘和PLL。
啟動代碼一般由微控制器廠商提供,有時還會在工具鏈軟件中,其可能是C代碼或匯編代碼。
3 C啟動代碼
若使用C/C++或其他高級語言編程,處理器需要執(zhí)行一些程序代碼以設(shè)置程序執(zhí)行環(huán)境(如設(shè)置全局變量以及SRAM中的初始值),對于加載時未初始化的數(shù)據(jù)存儲器中的變量,需要將他們初始化為0.若應(yīng)用需要使用malloc()等C函數(shù),C啟動代碼還需要初始化堆存儲的數(shù)據(jù)變量,初始化后,C啟動代碼會跳轉(zhuǎn)到main程序開頭。
C啟動代碼會被工具鏈自動生成,因此是和工具鏈相關(guān)的,如果是完全用匯編編寫的程序,則可能會不存在啟動代碼。對于ARM編譯器,C啟動代碼的標(biāo)號為__main,而GNU C編譯器生成的啟動代碼標(biāo)號一般為_start.
4 應(yīng)用代碼
應(yīng)用代碼一般是從main()開始的,其中包括用以執(zhí)行所需任務(wù)的應(yīng)用程序代碼生成的指令,除了指令序列外,還有其它類型的數(shù)據(jù):
變量初始值:函數(shù)或子例程中的局部變量需要被初始化,在程序執(zhí)行期間會設(shè)置這些初始值。
程序代碼中的常量,應(yīng)用代碼中的常量數(shù)據(jù)有多種:數(shù)據(jù)值、地址或外設(shè)寄存器以及常量字符 串等。這些數(shù)據(jù)一般被稱為文本數(shù)據(jù),且在程序映像中會以多個名為文本池的形式分組出現(xiàn)。
有些應(yīng)用可能還包含查找表、圖形映像數(shù)據(jù)(如位圖)等其他常量數(shù)據(jù)。
5 C庫代碼
在使用某些C/C++函數(shù)時,C庫代碼會被連接器插入程序映像中。另外,在進(jìn)行浮點運算和除法等數(shù)據(jù)處理任務(wù)時可能也會包含C庫代碼。Cortex-M0和Cortex-M0+處理器不支持除法指令,除法運算一般由C庫中的除法函數(shù)執(zhí)行。
為了應(yīng)對不同用途,有些開發(fā)工具會提供各種版本的C庫。例如,對于Keil MDK或ARM Development Studio 5(DS-5),可以選擇使用名為Microlib的特殊版本的C庫。Microlib面向微控制器應(yīng)用,并且體積非常小,但是無法提供標(biāo)準(zhǔn)C庫的所有特性。對于不需要很高的數(shù)據(jù)處理能力且存儲器需求非常緊張的應(yīng)用,Microlib是降低代碼大小的好方法。
對于不同的應(yīng)用,C庫代碼可能不會出現(xiàn)在簡單的C應(yīng)用(無C庫函數(shù)調(diào)用)或純匯編語言工程中。
向量表必須放在存儲器映像的開頭處,程序映像的其他部分就有沒有什么限制了。有些情況下,若程序存儲器中各部分的布局有特殊的要求,則可以利用連接器腳本控制程序映像的生成。
6 其他數(shù)據(jù)
程序映像中還包含其它數(shù)據(jù),例如全局變量和靜態(tài)變量的初始值。
二? SRAM中的數(shù)據(jù)
處理器中的SRAM包含:
數(shù)據(jù)空間
??臻g
堆空間
1 數(shù)據(jù)空間
存儲在RAM的末端,通常包含全局和靜態(tài)變量。局部變量可以存儲在處理器的寄存器中,或者放在棧中以減少RAM的使用,未使用函數(shù)中的局部變量不會占空存儲器空間。
2 ??臻g
??臻g,包括臨時數(shù)據(jù)存儲空間(一般的棧PUSH和POP操作)、局部變量的存儲空間、函數(shù)調(diào)用時的參數(shù)傳遞、以及異常流程中的寄存器保存等。
Thumb指令集在處理器數(shù)據(jù)訪問時非常高效,其使用棧指針(SP)相關(guān)的尋址模式,并且在很小的指令開銷下就可以訪問棧存儲中的這些數(shù)據(jù)。
3 堆空間
堆存儲是可選的,用于C函數(shù)中存儲器空間的動態(tài)分配,如 alloc()或malloc()和其他使用這個功能的函數(shù)。為了保證這些函數(shù)能夠正確分配存儲空間,C啟動代碼需要初始化堆存儲及其控制變量。
4 RAM空間分布
對于RAM處理器,還可以將程序代碼賦值到內(nèi)存中并從這里開始執(zhí)行,但是對于多數(shù)微控制器應(yīng)用,程序一般從Flash等非易失性存儲器中開始執(zhí)行。
將這些數(shù)據(jù)放到SRAM中的方法有很多種,一般是和工具鏈相關(guān)的。對于不具備OS的簡單應(yīng)用SRAM中存儲器分布情況如下圖。

對于有嵌入式OS的微控制器系統(tǒng),每個任務(wù)的棧都是獨立的。許多OS都允許軟件開發(fā)人員定義每個任務(wù)/線程所需的棧大小,有些OS可能會將RAM分分割成多個部分,并將每個部分分配給一個任務(wù),其中都包含各自的數(shù)據(jù)、棧和堆。
具有RTOS的多數(shù)系統(tǒng)都會使用下圖左側(cè)的數(shù)據(jù)布局,這里的全局和靜態(tài)變量以及堆存儲都是共用的。

三 微控制器啟動流程

有些微控制器會包含一個獨立的ROM,其中存儲一段BootLoader程序,該程序會在微控制器執(zhí)行Flash存儲器中的用戶程序前啟動。這個過程是可選的,如果沒有這段代碼那么硬件復(fù)位之后,微控制器從向量表的首地址處取出一個字大小的數(shù)據(jù),該數(shù)據(jù)就是棧指針。然后開始執(zhí)行復(fù)位向量。

當(dāng)處理器被復(fù)位之后,首先從0x0000 0000地址處讀取兩個字,第一個字為棧頂指針,第二個字為復(fù)位向量,決定程序執(zhí)行的起始地址(復(fù)位處理)。


版權(quán)聲明:本文為CSDN博主「黑刀夜」的原創(chuàng)文章,版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除。
原文鏈接:https://blog.csdn.net/chengbaojin/article/details/110263105