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

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

三 微控制器啟動(dòng)流程

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

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


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