1. 前言
書接上文《ARM_Cortex-M0 DesignStart系列--3rtl仿真過(guò)程的詳細(xì)分析》,本文基于hello這個(gè)case,對(duì)Cortex M0的啟動(dòng)過(guò)程做一個(gè)詳細(xì)的分析,其實(shí)整個(gè)ARM Cortex M系列的啟動(dòng)的過(guò)程都是很相似的,這對(duì)我們理解SoC的啟動(dòng)過(guò)程會(huì)很有幫助。
2. Cortex-M0 啟動(dòng)流程
ARM Cortex-M架構(gòu)芯片一般帶有片上閃存(flash)。ARM Cortex-M手冊(cè)規(guī)定在片上閃存(flash)起始地址處需要有一個(gè)有效的中斷向量表。芯片上電或復(fù)位(會(huì)觸發(fā)reset_Handler中斷程序)后,cpu首先從中斷向量表中讀出棧指針(MSP)和入口函數(shù)地址(復(fù)位向量,即程序執(zhí)行的起始位置)。將棧指針和入口函數(shù)地址載入棧指針(cm0_msp)寄存器和尋址寄存器(cm0_pc)后,cpu會(huì)從復(fù)位向量 (一般是ROM/FLASH)開(kāi)始執(zhí)行程序。
2.1 復(fù)位序列:
根據(jù)上文的描述,復(fù)位順序大致如下圖(復(fù)位序列)所示:
2.2中斷向量表:
2.2.1 中斷向量表的定義:
上文中提到的中斷向量表(向量表在以后還可以轉(zhuǎn)移到其它位置),那么什么叫中斷向量表呢?把系統(tǒng)中所有的中斷類型碼(中斷號(hào))及其對(duì)應(yīng)的中斷處理函數(shù)按一定的規(guī)律存放在一個(gè)區(qū)域內(nèi),這個(gè)存儲(chǔ)區(qū)域就叫中斷向量表。
如下圖所示,在CM0中,在地址0提供的是MSP的初始值,然后緊跟著的是復(fù)位向量。向量表中的數(shù)值是32位的地址,不是跳轉(zhuǎn)指令。向量表的復(fù)位向量指向復(fù)位后應(yīng)執(zhí)行的第一條指令。
2.2.2中斷向量表格式
中斷向量表每一條目為一個(gè)32bit的地址。每一個(gè)地址對(duì)應(yīng)一個(gè)中斷函數(shù)的地址(第一個(gè)條目除外)。除了第一個(gè)條目以外,所有地址的目標(biāo)都為尋址寄存器(PC)。當(dāng)相應(yīng)中斷觸發(fā)時(shí),ARM Cortex-M硬件會(huì)自動(dòng)把中斷向量表中相應(yīng)的中斷函數(shù)地址裝載入尋址寄存器(PC)然后開(kāi)始執(zhí)行中斷函數(shù)。如上所述,前16位(從MSP初始值->SysTick向量)為ARM保留的系統(tǒng)中斷向量,建議大家熟記。之后的中斷為芯片自定義的外部中斷向量,可以在使用時(shí)查詢手冊(cè)或者廠商提供的驅(qū)動(dòng)程序。
2.2.3 本項(xiàng)目中的中斷向量表
下面的兩副截圖是我從cm0_designstart的啟動(dòng)文件startup_CMSDK_CM0.s中的截圖,跟上面的圖示解釋是一致的,只是增加了一些外部中斷向量。
通常中斷向量表會(huì)放在啟動(dòng)文件中,那么什么是啟動(dòng)文件呢?顧名思義,就是mcu上電啟動(dòng)后要開(kāi)始執(zhí)行其中的代碼(當(dāng)然是編譯后的代碼,或者機(jī)器碼指令)。要知道,我們對(duì)單片機(jī)燒錄程序后,程序是存在NOR FLASH(即NOR閃存,通常用于存儲(chǔ)程序,NAND 閃存通常用于存儲(chǔ)數(shù)據(jù))。啟動(dòng)文件是使用匯編語(yǔ)言編寫的,在堆棧建立之后才可以運(yùn)行C代碼,因?yàn)镃函數(shù)調(diào)用需要把參數(shù)函數(shù)返回地址入棧,堆棧沒(méi)有建立不能運(yùn)行C代碼。啟動(dòng)文件主要完成以下工作:1. 初始化堆棧指針MSP和程序指針PC;2.初始化中斷向量表;3.定義Reset_Handler子程序,4.初始化中斷服務(wù)程序;5. 初始化用戶堆棧。關(guān)于啟動(dòng)文件的更多細(xì)節(jié),可以參考下圖中的code。
2.3程序存儲(chǔ)器和Bootloader
Cortex-M0的程序存儲(chǔ)器,一般使用片上Flash,但是程序也可以存儲(chǔ)在外部或者使用其他類型的存儲(chǔ)器(如外部SPI Flash、EEPROM等)。我們一開(kāi)始就講了,當(dāng)CPU從復(fù)位中啟動(dòng)時(shí),會(huì)首先訪問(wèn)0地址的向量表,從而取得MSP的初始值和復(fù)位向量,然后從復(fù)位向量開(kāi)始執(zhí)行程序。但要保證系統(tǒng)正常工作,系統(tǒng)中需要有合法的向量表和合法的程序存儲(chǔ)器,這樣CPU才不會(huì)執(zhí)行惡意軟件代碼。
關(guān)于向量表我們前面已經(jīng)講過(guò)了,而程序存儲(chǔ)器(也就是Flash存儲(chǔ)器,因?yàn)槌绦蛞话愦娣旁贔lash中)一般是從地址0開(kāi)始的。但是,在用戶編程以前,市面上MCU產(chǎn)品的Flash存儲(chǔ)器中可能沒(méi)有任何程序。
為了保證CPU可以正確的啟動(dòng),有些基于Cortex-M的MCU含有一個(gè)bootloader,bootloader是位于MCU芯片上的一小段代碼(程序),bootloader會(huì)在CPU上電后執(zhí)行并跳轉(zhuǎn),并且如果Flash存儲(chǔ)器已經(jīng)編程的話,它會(huì)跳轉(zhuǎn)到Flash中的用戶程序執(zhí)行。Bootloader是由芯片供應(yīng)商預(yù)先編程,有時(shí)它位于片上Flash存儲(chǔ)器并且與用戶程序是分開(kāi)的(這樣用戶更新程序也不會(huì)影響到Bootloader),而更多的時(shí)候它是位于和可編程程序存儲(chǔ)器相互獨(dú)立的ROM中。
上電以后,CPU會(huì)執(zhí)行bootloader程序,bootloader 主要是給系統(tǒng)一個(gè)機(jī)會(huì),在上電后是從外部接收程序更新到系統(tǒng)內(nèi)的flash,然后再執(zhí)行,其實(shí)還是直接執(zhí)行系統(tǒng)內(nèi)Flash內(nèi)的程序。
當(dāng)然,即使沒(méi)有bootloader,即使Flash存儲(chǔ)器中缺少合法的程序映像,debugger也可以通過(guò)我們上文講解的SWD接口連接到CPU并重新編程Flash存儲(chǔ)器。
說(shuō)到這里,又是中斷向量表,又是啟動(dòng)文件,又是bootloader,是不是有點(diǎn)暈菜的感覺(jué)?不過(guò)你千萬(wàn)別犯迷糊,你再看看我們之前的一篇文章《ARM_Cortex-M0 DesignStart系列--3rtl仿真過(guò)程的詳細(xì)分析》中bootloader.o以及bootloader.lst是怎么產(chǎn)生的,你就明白怎么回事了。下面是反匯編bootloader.lst的截圖。結(jié)合下面的截圖以及我們上面的分析,就應(yīng)該就可以很清楚其中的過(guò)程了。
2.4啟動(dòng)過(guò)程的波形分析
2.4.1 AHB協(xié)議簡(jiǎn)單介紹
由于后面啟動(dòng)過(guò)程的波形分析是基于AHB總線的,多少需要一些AHB協(xié)議的基礎(chǔ),當(dāng)然了這并不復(fù)雜。我從協(xié)議里面截了幾張圖,大家看一下就很清楚了。
2.4.2 啟動(dòng)波形分析
下面是,基于hello這個(gè)case的仿真波形,我們這里重點(diǎn)關(guān)注復(fù)位以后啟動(dòng)部分的波形。有了上面大量的分析和鋪墊,到這里感覺(jué)反而輕松了。大家將下圖中的波形跟bootloader.lst文件做一下對(duì)照就很容易理解了。下圖中值得一提的是,從地址4讀出的復(fù)位向量是’h199,而程序執(zhí)行的起始位置是’h198。原因是,程序執(zhí)行的真正起始位置是’h198,但是在將這個(gè)地址放到復(fù)位向量處時(shí),將最低位置1,以表示Thumb代碼,即CM0是在Thumb狀態(tài)下執(zhí)行的,僅此而已。
今天暫時(shí)先寫到這里了,我們后續(xù)不見(jiàn)不散。
-
ARM
+關(guān)注
關(guān)注
134文章
9027瀏覽量
366475 -
Cortex-M
+關(guān)注
關(guān)注
2文章
227瀏覽量
29707 -
DesignStart
+關(guān)注
關(guān)注
1文章
7瀏覽量
6024
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論