1.3初始化存儲(chǔ)設(shè)備初始化存儲(chǔ)器系統(tǒng)主要是對(duì)系統(tǒng)存儲(chǔ)器控制器的初始化,如果系統(tǒng)具有存儲(chǔ)器管理單元,也必須對(duì)其進(jìn)行初始化。 ARM微處理器架構(gòu)的理論尋址能力為4GB,但是對(duì)于一個(gè)特定的系統(tǒng)來(lái)說(shuō),所配備的實(shí)際物理存儲(chǔ)器遠(yuǎn)沒(méi)有那么多。出于對(duì)芯片的面積、成本、使用靈活性等方面的考慮,這么大容量的存儲(chǔ)器如果設(shè)計(jì)在芯片內(nèi)部是不能被接受的。因此,基于ARM微處理器的系統(tǒng)一般都需要外擴(kuò)大容量的存儲(chǔ)器,這些存儲(chǔ)器是由專門(mén)的存儲(chǔ)器控制器控制的。 因?yàn)榇鎯?chǔ)器控制器并非標(biāo)準(zhǔn)ARM微處理器架構(gòu)的一部分,所以不同的ARM微處理器,設(shè)計(jì)也會(huì)各不相同,初始化代碼自然也會(huì)有一些差異,但一般包含如下兩個(gè)方面: 1. 存儲(chǔ)器類型和時(shí)序的配置 ARM微處理器一般都設(shè)計(jì)有多種類型的存儲(chǔ)器接口,需要根據(jù)具體的系統(tǒng)設(shè)計(jì)加以正確配置,且對(duì)于同在一種類型的存儲(chǔ)器,也會(huì)因?yàn)樵L問(wèn)速度的差異進(jìn)行不同的時(shí)序設(shè)置。 存儲(chǔ)器接口時(shí)序優(yōu)化是非常重要的,這會(huì)影響到整個(gè)系統(tǒng)的性能。因?yàn)橐话阆到y(tǒng)運(yùn)行的速度瓶頸都存在于存儲(chǔ)器訪問(wèn),所以存儲(chǔ)器訪問(wèn)時(shí)序應(yīng)盡可能的快;而同時(shí)又要考慮到由此帶來(lái)的穩(wěn)定性問(wèn)題,應(yīng)根據(jù)不同的情況來(lái)配置。一般一個(gè)特定的系統(tǒng),需要進(jìn)行多次測(cè)試,才能確定最佳的時(shí)序配置。 2. 存儲(chǔ)器的地址分配與地址重映射 ARM微處理器架構(gòu)的理論尋址能力為4GB,但是對(duì)于一個(gè)特定的系統(tǒng)來(lái)說(shuō),所配備的實(shí)際物理存儲(chǔ)器遠(yuǎn)沒(méi)有那么多。因此,存儲(chǔ)器的地址分配也就是將物理存儲(chǔ)器定位在4GB地址空間的哪個(gè)具體位置。 ARM微處理器通常采用兩種方式來(lái)完成地址分配:一種方式采用固定的存儲(chǔ)器地址分配,即物理存儲(chǔ)器的起始地址是固定的;另一種方式采用存儲(chǔ)器重映射的手段,使物理存儲(chǔ)器的起始地址可以在有效的地址空間內(nèi)任意改變,即物理存儲(chǔ)器的地址是不固定的。 基于固定存儲(chǔ)器地址分配的ARM微處理器系統(tǒng),當(dāng)系統(tǒng)的硬件設(shè)計(jì)完成以后,物理存儲(chǔ)器地址也就確定了,在軟件設(shè)計(jì)的程序流程中考慮就簡(jiǎn)單一些。而對(duì)于具有存儲(chǔ)器地址重映射功能的系統(tǒng),這個(gè)過(guò)程就復(fù)雜的多。 一種典型的存儲(chǔ)器地址重映射過(guò)程描述如下:當(dāng)系統(tǒng)上電或復(fù)位以后,PC指針指向0x0,程序從0x0地址開(kāi)始執(zhí)行,因此,為了能正確讀取代碼,要求此時(shí)Flash(或其它類型的ROM)的起始地址為0x0。但Flash(或其它類型的ROM)的訪問(wèn)速度大大低于RAM,每次產(chǎn)生異常后,都要從Flash(或其它類型的ROM)的異常向量表調(diào)轉(zhuǎn)到相應(yīng)的處理程序,會(huì)影響異常的響應(yīng)速度,因此,系統(tǒng)便提供一種靈活的地址重映射方法,在系統(tǒng)完成必要地初始化以后,將RAM安排到0x0地址處,而將原來(lái)位于0x0處的Flash(或其它類型的ROM)安排到其他的地方上去,加快異常的響應(yīng)速度。 這個(gè)過(guò)程中最容易出錯(cuò)的地方是如何保證程序執(zhí)行流程的連續(xù)性。因?yàn)?span>PC指針最初在Flash里取指令執(zhí)行,在進(jìn)行地址重映射以后,Flash(或其它類型的ROM)被安排到其他地址上去了,而當(dāng)前地址被安排為RAM,如果事先沒(méi)有對(duì)RAM的內(nèi)容進(jìn)行正確地設(shè)置,在往下取指令執(zhí)行就會(huì)出錯(cuò),即程序的連續(xù)性被存儲(chǔ)器地址重映射這種變化所打斷。 常用的處理方法是:先將Flash(或其它類型的ROM)的內(nèi)容全部復(fù)制到RAM中,然后再進(jìn)行地址重映射。此時(shí)盡管Flash(或其它類型的ROM)和RAM的物理地址發(fā)生了變化,但由于RAM中的內(nèi)容與原來(lái)的Flash(或其它類型的ROM)是一樣的,PC指針就可以繼續(xù)取得正確地指令執(zhí)行,從而保證了程序流程的連續(xù)性。 1.4 初始化堆棧因?yàn)?span>ARM有7種執(zhí)行狀態(tài),每一種狀態(tài)的堆棧指針寄存器(SP)都是獨(dú)立的(注意System和User模式使用同一個(gè)SP)。所以,對(duì)程序中需要用到的每一種模式都要給SP定義一個(gè)堆棧地址。方法是改變狀態(tài)寄存器內(nèi)的狀態(tài)位,使處理器切換到不同的狀態(tài),然后給SP賦值。注意:不要切換到User模式進(jìn)行User模式的堆棧設(shè)置,因?yàn)檫M(jìn)入User模式后就不能再操作CPSR回到別的模式了,可能會(huì)對(duì)接下去的程序執(zhí)行造成影響。 1.5 初始化用戶執(zhí)行環(huán)境主要包括初始化臨界I/O設(shè)備,初始化應(yīng)用程序執(zhí)行環(huán)境,改變處理器的運(yùn)行模式和狀態(tài),使能中斷4部分。 初始化臨界I/O設(shè)備。臨界I/O設(shè)備是指哪些使能中斷之前必須進(jìn)行初始化的設(shè)備。如果不對(duì)這些設(shè)備進(jìn)行必要的初始化,它們可能會(huì)在使能中斷后產(chǎn)生一些沒(méi)有意義的中斷請(qǐng)求,從而影響程序的運(yùn)行。 初始化應(yīng)用程序執(zhí)行環(huán)境。程序代碼通過(guò)編譯、鏈接后生成可執(zhí)行映像文件,一個(gè)ARM映像文件由RO,RW和ZI三個(gè)段組成,其中RO為代碼段,RW是已初始化的全局變量,ZI是未初始化的全局變量。映像一開(kāi)始總是存儲(chǔ)在ROM/Flash里面的,其RO部分即可以在ROM/Flash里面執(zhí)行,也可以轉(zhuǎn)移到速度更快的RAM中執(zhí)行;而RW和ZI這兩部分是必須轉(zhuǎn)移到可寫(xiě)的RAM里去。所謂應(yīng)用程序執(zhí)行環(huán)境的初始化,就是完成必要的從ROM到RAM的數(shù)據(jù)傳輸和內(nèi)容清零。 改變處理器的運(yùn)行模式和狀態(tài)。ARM微處理器在復(fù)位或上電狀態(tài)下的默認(rèn)模式為系統(tǒng)管理模式,而在初始化代碼中可能需要切換到其它模式進(jìn)行必要的操作,如初始化各個(gè)模式下的堆棧指針寄存器。因此,在系統(tǒng)的初始化過(guò)程中處理器模式一般會(huì)經(jīng)歷如圖2所示的變化。同時(shí),ARM微處理器在復(fù)位后總是處于ARM狀態(tài),對(duì)于兼容Thumb指令的處理器如果應(yīng)用程序的入口點(diǎn)對(duì)應(yīng)Thumb指令,則必須將微處理器切換到Thumb狀態(tài)。 使能中斷。如果系統(tǒng)需要使用中斷,初始化代碼應(yīng)該使能中斷。中斷使能可以通過(guò)清除CPRS中的中斷禁止位來(lái)完成。 1.6 呼叫主應(yīng)用程序當(dāng)所有的系統(tǒng)初始化工作完成之后,就需要把程序流程轉(zhuǎn)入主應(yīng)用程序。如果主應(yīng)用程序是由C代碼編寫(xiě),可以通過(guò)以下兩種方式進(jìn)入C代碼運(yùn)行,最簡(jiǎn)單的情況如下:
IMPORT C_Entry ;定義一個(gè)外部標(biāo)號(hào),最好不使用main B C_Entry ;跳轉(zhuǎn)到該處執(zhí)行
在ARM的ADS編譯環(huán)境中,還另外提供了一種進(jìn)入C代碼的機(jī)制:
IMPORT __main B __main
__main()是編譯器提供的一個(gè)函數(shù),負(fù)責(zé)完成庫(kù)函數(shù)的初始化和對(duì)C代碼運(yùn)行環(huán)境的初始化,最后自動(dòng)調(diào)轉(zhuǎn)到main()函數(shù)執(zhí)行,此時(shí)應(yīng)用程序的主函數(shù)名必須是main()。 用戶可以根據(jù)需要選擇是否使用main()函數(shù),如果想讓系統(tǒng)自動(dòng)完成初始化過(guò)程,可以使用main()函數(shù);如果所有的初始化過(guò)程都由用戶自己完成,則不使用main()。 |
聯(lián)系客服