<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > arm啟動(dòng)代碼詳細(xì)分析

          arm啟動(dòng)代碼詳細(xì)分析

          作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò) 收藏
          arm啟動(dòng)代碼詳細(xì)分析
          所謂啟動(dòng)代碼,就是處理器在啟動(dòng)的時(shí)候執(zhí)行的一段代碼,主要任務(wù)是初始化處理器模式,設(shè)置堆棧,初始化變量等等.由于以上的操作均與處理器體系結(jié)構(gòu)和系統(tǒng)配置密切相關(guān),所以一般由匯編來(lái)編寫.
            具體到S64,啟動(dòng)代碼分成兩部分,一是與ARM7TDMI內(nèi)核相關(guān)的部分,包括處理器各異常向量的配置,各處理器模式的堆棧設(shè)置,如有必要,復(fù)制向量到RAM,以便remap之后處理器正確處理異常,初始化數(shù)據(jù)(包括RW與ZI),最后跳轉(zhuǎn)到Main.二是與處理器外部設(shè)備相關(guān)的部分,這和廠商的聯(lián)系比較大.雖然都采用了ARM7TDMI的內(nèi)核,但是不同的廠家整合了不同的片上外設(shè),需要不同的初始化,其中比較重要的是初始化WDT,初始化各子系統(tǒng)時(shí)鐘,有必要的話,進(jìn)行remap.這一部分與一般控制器的初始化類似,因此,本文不作重點(diǎn)描述.
            在進(jìn)行分析之前,請(qǐng)確認(rèn)如下相關(guān)概念:
          S64片上FLASH起始于0x100000,共64kB,片上RAM起始于0x200000,共16kB.
          S64復(fù)位之后,程序會(huì)從0開(kāi)始執(zhí)行,此時(shí)FLASH被映射到0地址,因此,S64可以取得指令并執(zhí)行.顯然,此時(shí)還是駐留在0x100000地址.如果使用remap命令,將會(huì)把RAM映射到0地址,同樣的這時(shí)0地址的內(nèi)容也只是RAM的鏡像.
          S64的FLASH可以保證在最差情況時(shí)以30MHz進(jìn)行單周期訪問(wèn),而RAM可以保證在最大速度時(shí)的單周期訪問(wèn).
          OK,以下開(kāi)始分析啟動(dòng)代碼.

          一,處理器異常
          S64將異常向量至于0地址開(kāi)始的幾個(gè)直接,這些是必需要處理的.由于復(fù)位向量位于0,也需要一條跳轉(zhuǎn)指令.具體代碼如下:
          RESET
          B SYSINIT ; Reset
          B UDFHANDLER ; UNDEFINED
          B SWIHANDLER ; SWI
          B PABTHANDLER ; PREFETCH ABORT
          B DABTHANDLER ; DATA ABORT
          B . ; RESERVED
          B VECTORED_IRQ_HANDLER
          B . ; ADD FIQ CODE HERE

          UDFHANDLER
          B .

          SWIHANDLER
          B .

          PABTHANDLER
          B .

          DABTHANDLER
          B .

          請(qǐng)注意,B指令經(jīng)匯編后會(huì)替換為當(dāng)前PC值加上一個(gè)修正值(+/-),所以這條指令是代碼位置無(wú)關(guān)的,也就是不管這條指令是在0地址還是在 0x100000執(zhí)行,都能跳轉(zhuǎn)到指定的位置,而LDR PC,=???將向PC直接裝載一個(gè)標(biāo)號(hào)的值,請(qǐng)注意,標(biāo)號(hào)在編譯過(guò)后將被替換為一個(gè)與RO相對(duì)應(yīng)的值,也就是說(shuō),這樣的指令無(wú)論在哪里執(zhí)行,都只會(huì)跳轉(zhuǎn)到一個(gè)指定的位置.下面舉一個(gè)具體的例子來(lái)說(shuō)明兩者的區(qū)別:
          假定有如下程序:
          RESET
          B INIT 或者 LDR PC,=INIT


          INIT

          其中RESET為起始時(shí)的代碼,也就是這條代碼的偏移為0,設(shè)INIT的偏移量為offset.如果將這段程序按照RO=0x1000000編譯, 那么B INIT可理解為ADD PC, PC, #offset,而LDR PC,=INIT可被理解為 MOV PC,#(RO+offset) .顯然當(dāng)系統(tǒng)復(fù)位時(shí),程序從0開(kāi)始運(yùn)行,而0地址有FLASH的副本,執(zhí)行B INIT將把PC指向位于0地址處的鏡像代碼位置,也即INIT;如果執(zhí)行LDR PC,=INIT將會(huì)將PC直接指向位于FLASH中的原始代碼.因此以上兩者都能正確運(yùn)行.下面將RO設(shè)置為0x200000,編譯后生成代碼,還是得燒寫到FLASH中,也就是還是0x100000,系統(tǒng)復(fù)位后從0地址執(zhí)行,還是FLASH的副本,此時(shí)執(zhí)行B INIT,將跳到副本中的INIT位置執(zhí)行,此處有對(duì)應(yīng)的代碼;但是如果執(zhí)行LDR PC,=INIT,將向PC加載0x200000+offset,這將使得PC跳到RAM中,而此時(shí)由于代碼沒(méi)有復(fù)制,RAM中的指定位置并沒(méi)有代碼,程序無(wú)法運(yùn)行.

          二,處理器模式
          ARM的處理器可工作于多種模式,不同模式有不同的堆棧 ,以下設(shè)置各模式及其堆棧.
          預(yù)定義一些參數(shù):
          MODUSR EQU 0x10
          MODSYS EQU 0x1F
          MODSVC EQU 0x13
          MODABT EQU 0x17
          MODUDF EQU 0x1B
          MODIRQ EQU 0x12
          MODFIQ EQU 0x11

          IRQBIT EQU 0x80
          FIQBIT EQU 0x40

          RAMEND EQU 0x00204000 ; S64 : 16KB RAM

          VECTSIZE EQU 0x100 ;

          UsrStkSz EQU 8 ; size of USR stack
          SysStkSz EQU 128 ; size of SYS stack
          SvcStkSz EQU 8 ; size of SVC stack
          UdfStkSz EQU 8 ; size of UDF stack
          AbtStkSz EQU 8 ; size of ABT stack
          IrqStkSz EQU 128 ; size of IRQ stack
          FiqStkSz EQU 16 ; size of FIQ stack

          修改這些值即可修改相應(yīng)模式堆棧的尺寸.
          以下為各模式代碼:
          SYSINIT
          ;
          MRS R0,CPSR
          BIC R0,R0,#0x1F

          MOV R2,#RAMEND
          ORR R1,R0,#(MODSVC :OR: IRQBIT :OR: FIQBIT)
          MSR cpsr_cxsf,R1 ; ENTER SVC MODE
          MOV sp,R2
          SUB R2,R2,#SvcStkSz

          ORR R1,R0,#(MODFIQ :OR: IRQBIT :OR: FIQBIT)
          MSR CPSR_cxsf,R1 ; ENTER FIQ MODE
          MOV sp,R2
          SUB R2,R2,#FiqStkSz

          ORR R1,R0,#(MODIRQ :OR: IRQBIT :OR: FIQBIT)
          MSR CPSR_cxsf,R1 ; ENTER IRQ MODE
          MOV sp,R2
          SUB R2,R2,#IrqStkSz

          ORR R1,R0,#(MODUDF :OR: IRQBIT :OR: FIQBIT)
          MSR CPSR_cxsf,R1 ; ENTER UDF MODE
          MOV sp,R2
          SUB R2,R2,#UdfStkSz

          ORR R1,R0,#(MODABT :OR: IRQBIT :OR: FIQBIT)
          MSR CPSR_cxsf,R1 ; ENTER ABT MODE
          MOV sp,R2
          SUB R2,R2,#AbtStkSz

          ;ORR R1,R0,#(MODUSR :OR: IRQBIT :OR: FIQBIT)
          ;MSR CPSR_cxsf,R1 ; ENTER USR MODE
          ;MOV sp,R2
          ;SUB R2,R2,#UsrStkSz

          ORR R1,R0,#(MODSYS :OR: IRQBIT :OR: FIQBIT)
          MSR CPSR_cxsf,R1 ; ENTER SYS MODE
          MOV sp,R2 ;

          三,初始化變量
          編譯完成之后,連接器會(huì)生成三個(gè)基本的段,分別是RO,RW,ZI,并會(huì)在image中順序擺放.顯然,RW,ZI在運(yùn)行開(kāi)始時(shí)并不位于指定的RW位置,因此必須初始化
          LDR R0,=|Image$$RO$$Limit|
          LDR R1,=|Image$$RW$$Base|
          LDR R2,=|Image$$ZI$$Base|
          1
          CMP R1,R2
          LDRLO R3,[R0],#4
          STRLO R3,[R1],#4
          BLO ?

          MOV R3,#0
          LDR R1,=|Image$$ZI$$Limit|
          2
          CMP R2,R1
          STRLO R3,[R2],#4
          BLO ?

          四,復(fù)制異常向量
          由于代碼于RAM運(yùn)行時(shí),有明顯的速度優(yōu)勢(shì),而且變量可以動(dòng)態(tài)配置,因此可以通過(guò)remap將RAM映射到0,使得出現(xiàn)異常時(shí)ARM從RAM中取得向量.
          IMPORT |Image$$RO$$Base|
          IMPORT |Image$$RO$$Limit|
          IMPORT |Image$$RW$$Base|
          IMPORT |Image$$RW$$Limit|
          IMPORT |Image$$ZI$$Base|
          IMPORT |Image$$ZI$$Limit|


          COPY_VECT_TO_RAM
          LDR R0,=|Image$$RO$$Base|
          LDR R1,=SYSINIT
          LDR R2,=0x200000 ; RAM START
          0
          CMP R0,R1
          LDRLO R3,[R0],#4
          STRLO R3,[R2],#4
          BLO ?

          這段程序?qū)YSINIT之前的代碼,也就是異常處理函數(shù),全部復(fù)制到RAM中, 這就意味著不能將RW設(shè)置為0x200000,這樣會(huì)使得向量被沖掉.

          四,在RAM中運(yùn)行
          如果有必要,且代碼足夠小,可以將代碼置于RAM中運(yùn)行,由于RAM中本身沒(méi)有代碼,就需要將代碼復(fù)制到RAM中:
          COPY_BEGIN
          LDR R0,=0x200000
          LDR R1,=RESET ; =|Image$$RO$$Base|
          CMP R1,R0 ;
          BLO COPY_END ;

          ADR R0,RESET
          ADR R2,COPY_END
          SUB R0,R2,R0
          ADD R1,R1,R0

          LDR R3,=|Image$$RO$$Limit|
          3
          CMP R1,R3
          LDRLO R4,[R2],#4
          STRLO R4,[R1],#4
          BLO ?

          LDR PC,=COPY_END

          COPY_END
          程序首先取得RESET的連接地址,判斷程序是否時(shí)是在RAM中運(yùn)行,方法是與RAM起始地址比較,如果小于,那么就跳過(guò)代碼復(fù)制.
          在復(fù)制代碼的時(shí)候需要注意,在這段程序結(jié)束之前的代碼沒(méi)有必要復(fù)制,因?yàn)檫@些代碼都已經(jīng)執(zhí)行過(guò)了,所以,先取得COPY_END,作為復(fù)制起始地址,然后計(jì)算其相對(duì)RESET的偏移,然后以RO的值加上這個(gè)偏移,就是復(fù)制目的地的起始地址,然后開(kāi)始復(fù)制.

          五,開(kāi)始主程序
          以上步驟完成,就可以跳轉(zhuǎn)到main運(yùn)行
          IMPORT Main

          LDR PC,=Main
          B .
          六,器件初始化
          主程序首先要進(jìn)行器件的初始化,對(duì)S64而言,應(yīng)該先初始化WDT,因?yàn)槟J(rèn)情況下,WDT是打開(kāi)的,然后是各設(shè)備的時(shí)鐘分配,最后應(yīng)該remap



          關(guān)鍵詞: ARM啟動(dòng)代

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();