ARM 匯編若干問(wèn)題(一般中斷問(wèn)題與軟中斷SWI分析)
ARM CPU 在上電啟動(dòng)之后會(huì)自動(dòng)進(jìn)入SVC模式,也是ARM上電后的默認(rèn)工作模式,如果發(fā)生了中斷,ARM會(huì)自動(dòng)切換到外部中斷模式(IRQ為例),如果是FIQ那么就切換到FIQ模式下面進(jìn)行處理。
在每一個(gè)模式下面都有一組可以訪問(wèn)的寄存器,SVC和IRQ模式下的R0~R12是共用的,這就涉及到寄存器Rx內(nèi)容的保存:壓棧,恢復(fù):出棧操作。在IRQ處理中用到了哪些Rx就要進(jìn)行相應(yīng)的保護(hù)與恢復(fù),否則當(dāng)處理退出IRQ時(shí)就會(huì)出錯(cuò)誤。
發(fā)生中斷時(shí)候,ARM是要首先完成當(dāng)前正在執(zhí)行的指令,然后再進(jìn)行為IRQ的必要處理。具體的內(nèi)容如下:
將當(dāng)前CPSR,保存到IRQ模式下的的SPSR_irq,進(jìn)行備份。
把PC-4所指向的地址放到LR。LR = PC-4。為中斷返回是有個(gè)退出點(diǎn)。
強(qiáng)制PC= 0X00000018,指向IRQ的中斷向量的地址,通常地址0X00000018放置一條跳命令,跳轉(zhuǎn)到IRQ的中斷服務(wù)函數(shù)的入口地址。B HANDLERIRQ.
補(bǔ)充一點(diǎn):ARM的正在執(zhí)行的指令地址x,和取指令的地址PC,地址y,之間是差x=y-8.
難點(diǎn):中斷服務(wù)函數(shù)退出地址的計(jì)算
PC-8 --------------->|正在執(zhí)行的指令的地址|0x120 如果此時(shí)發(fā)生中斷了
PC-4 --------------->|真正的中斷返回點(diǎn)地址|0x124
PC ---------------->|取指令的地址 |0x128
通過(guò)上述分析可以得出:真正的中斷返回點(diǎn)地址是0X124,真正應(yīng)該存入LR的地址是0X124.但是實(shí)際情況是:0X128 ?????
分析:ARM 總是執(zhí)行完當(dāng)前的指令才會(huì)處理其他事情,問(wèn)題就出在這里,當(dāng)ARM執(zhí)行完當(dāng)前的指令的時(shí)候PC已經(jīng)更新了,如下
PC = PC+4;PC = 0X128+4 = 0X12C,存放到LR=PC-4; LR = 0X12C-4=0X128;這個(gè)0X128不是真正的中斷函數(shù)的返回點(diǎn)。真正的函數(shù)返回點(diǎn)是0X124.怎么辦????
在給PC恢復(fù)數(shù)值是進(jìn)行這樣的處理下:LR = LR-4,PC=LR. ==>SUBS PC,LR,#4. 并且自動(dòng)恢復(fù)CPSR=SPSR_irq
SWI軟中斷問(wèn)題分析
軟中斷和一般的中斷處理流程有不同的地方:CPU在執(zhí)行指令時(shí)候,遇見一般的中斷,先要執(zhí)行完當(dāng)前的指令,更新PC,然后把LR=PC-4.SPSR_irq=CPSR.CPSR=XXX.進(jìn)入IRQ中斷處理過(guò)程。真正的斷點(diǎn)返回地址是:LR-4。在返回時(shí)需要進(jìn)行地址的調(diào)整。 ==>SUBS PC,LR,#4.并且自動(dòng)恢復(fù)CPSR=SPSR_irq。
swi軟中斷還是很特別的玩意,軟中斷發(fā)生的時(shí)候,CPU切換到SVC工作模式,PC的數(shù)值不進(jìn)行更新,即:不是等到把當(dāng)前的指令執(zhí)行完畢之后在執(zhí)行其他的處理。而是立刻處理。CPU立即把軟中斷的返回地址寫入LR中。LR=PC-4,這是真正的返回地址,PC的數(shù)據(jù)不更新。?。。?!。SWI中斷返回地址不需要調(diào)整就是正確的地址。
然后就是軟中斷編號(hào)的計(jì)算,方法:發(fā)生軟中斷時(shí)那條指令地址里面數(shù)據(jù)的低24位放的就是軟中斷標(biāo)號(hào),從中取出來(lái)放到R0里面,R0是函數(shù)的第一個(gè)參數(shù),也是存放函數(shù)返回結(jié)果的地方。
HandlerSWI
STMFD SP!,{R0-R3,R12,LR},LR存放的是swi真正的軟中斷要返回的中斷地址點(diǎn)。
LDR R0,[LR,#-4];找到到底在哪一條指令時(shí)發(fā)生了軟中斷,很明顯:就是LR真正斷點(diǎn)返回地址的上面一條地址。LR-4或者PC-8。找個(gè)這個(gè)指令的地址,取出其中的內(nèi)容。軟中斷的編號(hào)就是存放在發(fā)生軟中斷那條指令地址的低24位數(shù)據(jù)里面。
BIC R0,R0,#0xFF000000,低24位是軟中斷號(hào)
BL my_swi_handler;
LDMFD SP! ,{R0-R3,R12,PC}^,其中^表示CPSR=SPSR_svc.只能手動(dòng)恢復(fù)。
使用方法
extern void my_swi_handler(unsigned int num);
__swi(0x1)led_one(void);
__swi(0x2)led_two(void);
main()
{
led_one();
delay(100ms);
led_two();
}
void my_swi_handler(unsigned int num)
{
case 0x1:{ do_some_thing}break;
case 0x2:{do_another_thing}break;
default: break;
}
評(píng)論