<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ARM簡(jiǎn)單啟動(dòng)代碼及中斷處理分析

ARM簡(jiǎn)單啟動(dòng)代碼及中斷處理分析

作者: 時(shí)間:2016-11-24 來(lái)源:網(wǎng)絡(luò ) 收藏
前言:本篇分析的是一個(gè)最精簡(jiǎn)的啟動(dòng)代碼,并且包含一個(gè)簡(jiǎn)單的中斷處理,C程序部分省略,重點(diǎn)分析匯編部分,這是因為對于我來(lái)說(shuō),匯編代碼實(shí)在是讓人厭煩,但是又不能不用。
下面是對代碼的分析,紅色部分是分析結果
.extern main //.extern 表示main在另外的文件中定義,在這里要引用,至于為什么只聲明了extern而沒(méi) //有聲明別的,目前還不知道,不過(guò)都聲明一下,應該沒(méi)問(wèn)題
.text //.text 表示后面的內容編譯出來(lái)放在代碼段
.global _start //.global 告訴編譯器后面聲明的是一個(gè)全局可見(jiàn)的名字,由于這是啟動(dòng)代碼,所以cpu上電后 //必須要找到_start函數,所以_start必須聲明為全局的,當然這個(gè)名字可以改,無(wú)所謂
_start: //查看反匯編地址就可以發(fā)現,_start的地址就是0x0
b Reset //不帶返回的跳轉到Reset中,為什么不用返回呢,因為沒(méi)必要,reset中直接進(jìn)入到主函數內了
HandleUndef: //查看反匯編地址可知HandleUndef的地址位0x04,這個(gè)很好理解,因為一條指令4個(gè)字節
b HandleUndef //在這里由于是精簡(jiǎn)的啟動(dòng)代碼,所以一旦發(fā)生了未定義異常時(shí),就讓CPU自己玩死自己吧
HandleSWI: //反匯編地址0x08,其他分析同上
b HandleSWI
HandlePrefetchAbort: //反匯編地址0x0C,其他分析同上
b HandlePrefetchAbort
HandleDataAbort: //反匯編地址0x10,其他分析同上
b HandleDataAbort
HandleNotUsed: //反匯編地址0x14,其他分析同上
b HandleNotUsed
HandleIRQ:
b HandlerIRQ //反匯編地址0x18,看到這里相比就有點(diǎn)感覺(jué)了,0x18是普通中斷向量地址,這個(gè)就有很 //多地方可說(shuō)了,首先這里依然是使用B指令進(jìn)行跳轉,這個(gè)之所以不直接用BL的原因 ///是,中斷還不太算是調用函數那么簡(jiǎn)單,發(fā)生中斷的時(shí)候,要保存現場(chǎng),而現場(chǎng)的數 //據有很多,具體為R0-R12、PC、CPSR的內容,這些都需要進(jìn)棧保存,所以這些的內容不 //是BL一條命令能完成的,所以保存現場(chǎng)的內容就直接放到了中斷程序中了。其次要特別 //注意這個(gè)里面跳轉的程序時(shí)HandlerIRQ不是HandleIRQ,如果還像上面那樣,那么發(fā)生中 //斷時(shí),CPU就會(huì )不停的循環(huán)來(lái)回跳了,所以這點(diǎn)需要特別留意,當然還有一種方法,就是 //不要這條命令的標號HandleIRQ,直接使用一條 b HandlerIRQ即可。
HandleFIQ:
b HandleFIQ //反匯編地址位0x1C,由于本程序只分析簡(jiǎn)單的普通中斷,所以認為發(fā)生快速 //中斷的時(shí)候,讓CPU自己玩
Reset:
ldr sp,=4096 //由于要在匯編中調用C函數,所以要先設置堆棧指針,具體為什么,就 //不詳細分析了,簡(jiǎn)單的說(shuō),C函數要使用很多的中間內存存放運算數據,所以 //要開(kāi)辟一段堆棧用。這里還要特別提到一點(diǎn),由于ARM工作模式的特點(diǎn),此時(shí) //設置的堆棧指針SP,即R14,對應的是系統模式下的堆棧指針寄存器,即R14_svc
bl disable_watch_dog //關(guān)閉看門(mén)狗
msr cpsr_c,# 0xd2 //設置CPU進(jìn)入到中斷模式
ldr sp,=3072 //由于發(fā)生中斷時(shí),要用到堆棧用于保存現場(chǎng),所以需要先設置中斷模式下的堆 //棧指針地址(設置堆棧指針就相當于開(kāi)辟堆棧了,因為堆棧就是有堆棧指針的 //一片普通內存區域),即設置R14_irq,特別注意R14_irq和R14_svc是不一樣 //的,只是同名,但是指向的物理地址是完全不同的。
msr cpsr_c,# 0xdf //從普通中斷模式返回到系統模式
bl init_led //這個(gè)非常值得分析,首先這里使用了BL指令進(jìn)行跳轉,BL指令的特點(diǎn)就是,跳轉 //的同時(shí),會(huì )自動(dòng)的將PC的值放到LR中,而且,如果后面跳轉的是C函數的話(huà),C函 //數中就不用設置返回命令了,而如果BL后面跟的是一個(gè)匯編子程序,那就需要程 //序員自己添加返回命令,這是為什么呢?如果用專(zhuān)業(yè)術(shù)語(yǔ)說(shuō),如果調用C函數, //函數運行結束后,編譯器會(huì )自動(dòng)的將上面保存的LR中的內容減去4重新傳遞給 //PC(為什么減4下面分析),也就實(shí)現了自動(dòng)返回的功能,但是匯編函數不行,因 //為匯編的編譯器沒(méi)有這項功能,所以通俗的講,為什么C語(yǔ)言是高級語(yǔ)言,除了語(yǔ) //法高級人性化,配套的編譯器也比較人性化,會(huì )幫程序員做一些通用的工作。而 //匯編語(yǔ)言就比較一根筋,所有的事兒,哪怕是最簡(jiǎn)單的事兒,都要程序員一條一 //條的把代碼敲上去告訴它怎么干(這也是我為什么討厭匯編的原因,比較懶,呵 //呵),至于調用匯編子程序怎么返回怎么做,分析在下面
bl init_irq //分析同上
msr cpsr_c,# 0x5f //開(kāi)中斷,即允許普通中斷IRQ
ldr lr,=halt_loop //這個(gè)也很有意思,在這里為什么不直接用 bl main代替這兩條命令呢,因 //為。。。。。想嘚瑟一下(玩笑了),主要是想學(xué)習另外一種常見(jiàn)常用的跳轉方 //法。BL命令很好用,但是有缺點(diǎn),就是跳轉的范圍,因為它只能跳轉區區32MB, //換算成ARM的命令,也就只有8M的地址(因為一條命令4個(gè)字節),也就 //是-4MB~+4MB,所以范圍有限,而嵌入式程序,尤其是有操作系統時(shí),程序存放地 //址跨度比較大,所以呢,需要有一個(gè)長(cháng)跳轉指令,所以就引出了LDR命令,這個(gè)命 //令的跳轉范圍是4G,所以知道為什么LDR長(cháng)用了吧,因為無(wú)論地址在哪,它都能跳 //到,跳轉范圍大是LDR命令的優(yōu)點(diǎn),但是它也有缺點(diǎn),就是它負責跳轉,不能保存 //PC,如果在跳轉前不往LR中放返回地址,就會(huì )出現,跳到了子程序的位置,子程序 //執行完后,跳不回來(lái)了,所以如果使用ldr調用子程序,一定要在調用前給LR一個(gè) //返回地址。
ldr pc,=main
halt_loop:
b halt_loop //main函數的返回地址,或者說(shuō)是返回操作,讓CPU原地踏步
HandlerIRQ:
sub lr,lr,# 4 //這條指令用于計算中斷處理完畢后的返回地址,在這里有個(gè)隱含的地方,即當發(fā)生中 //斷時(shí),處理器會(huì )自動(dòng)的向LR寄存器中存放被中斷指令的地址加4,或者也可以理解成,
//存放的是PC的值,而PC的值是當前運行命令地址加8,雖然發(fā)生了中斷,但是CPU仍然會(huì ) //運行完當前命令后才去處理中斷,所以L(fǎng)R-4的值,正是被中斷指令的下一條命令,當中 //斷處理完畢以后,返回到被中斷指令的下一條指令進(jìn)行執行。
stmdb sp!,{r0-r12,lr} //入棧指令,表示將R0~R12,以及LR寄存器的內容入棧,這個(gè)命令格式暫不分析,具體的可以參考 //相關(guān)手冊
ldr lr,=int_return //這兩條命令的分析跟上面跳轉到main函數原理是一樣的,可以使用一條命令
//bl EINT_Handle代替,因為這個(gè)程序本身并不大,不會(huì )超過(guò)4Kb
ldr pc,=EINT_Handle
int_return:
ldmia sp!,{r0-r12,pc}^ //出棧指令,跟上面的入棧指令相呼應,表示將sp對應的地址內容遞增(因為ARM的堆棧式滿(mǎn)遞減 //形式)的依次存放到r0~r12,以及pc中,而且這個(gè)很有意思,按照順序,sp即r13肯定不包括在 //內,所以到pc的時(shí)候,賦值的內容寄存器正好是LR,而LR已經(jīng)在中斷開(kāi)頭處理了,而且^表示將 //spsr的值復制到cpsr中,至此完成了中斷的返回



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

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>