1. 程式人生 > >智能小車37:異常在ARM、JAVA、硬件裏的實現

智能小車37:異常在ARM、JAVA、硬件裏的實現

來源 地址 cloud 不同的 lin ddn exc 開發 指針

幾乎所有編程語言都有異常,可以說有程序就有異常。今天學習Arm的中斷(異常)處理,聯想到Java的異常,硬件中如何實現等問題,下面給大家分享一下。

一、Arm的中斷。
1.觸發異常
2.保存現場
3.cpu進入異常工作模式,程序指針(pc)跳入異常入口(處理異常的代碼地址)
a.分辨中斷源
b.進行邏輯處理
c.清理工作
4.恢復現場
流程圖(來源於《2440數據手冊》)如下:
技術分享
這裏的工作模式,其實就是不同情況下,cpu有一組不同的寄存器。正是有了不同的寄存器,程序在可以在不同的狀態下來回切換。如下圖:
技術分享
中斷例子的匯編代碼如下:

b Reset

@******************一堆設置代碼已省略************************************************* Reset:
ldr sp, =4096 @ 設置棧指針,以下都是C函數,調用前需要設好棧
bl disable_watch_dog @ 關閉WATCHDOG,否則CPU會不斷重啟
msr cpsr_c, #0xd2 @ 進入中斷模式,d的前兩位是11,意思是關閉所有的中斷
ldr sp, =3072 @ 設置中斷模式棧指針
msr cpsr_c, #0xd3 @ 進入管理模式
ldr sp, =4096 @ 設置管理模式棧指針,
@ 其實復位之後,CPU就處於管理模式,
@ 前面的“ldr sp, =4096”完成同樣的功能,此句可省略
bl init_led @ 初始化LED的GPIO管腳
bl init_irq @ 調用中斷初始化函數,在init.c中
msr cpsr_c, #0x53 @ 設置I-bit=0,開IRQ中斷
ldr lr, =halt_loop @ 設置返回地址
ldr pc, =main @ 調用main函數
halt_loop:
b halt_loop
@中斷函數
HandleIRQ:
sub lr, lr, #4 @ 計算返回地址,arm架構規定的
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器,保存現場
@ 註意,此時的sp是中斷模式的sp
@ 初始值是上面設置的3072
ldr lr, =int_return @ 設置調用ISR即EINT_Handle函數後的返回地址
ldr pc, =EINT_Handle @ 調用中斷服務函數,在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值復制到cpsr

EINT_Handle 函數的實現就是判斷是那個按鈕然後點相應的燈,我這裏就不復制代碼了。
msr cpsr_c指令值的來源如下圖(來源於《嵌入式Linux應用開發完全手冊》):

技術分享


二、java中的異常,很簡單。
try{
}catch(Exception e){
}finally{
}
不用關心什麽工作模式,catch中代碼命中就執行,finally裏的代碼一定會執行。根據自己的邏輯來寫就行了。

java中的中斷,Thread有個interrupt方法,但調用這個方法並不知道線程會在什麽狀態下中斷,我沒有用過這種方式。需要中斷的話,我一般自己寫個狀態變量,在while裏判斷中斷狀態做下處理。

三、硬件實現中斷。
用繼電器就可以實現開關,如下圖:
技術分享
給線圈一點電壓就能切換這個開關,也就能觸發工作模式的切換了。

智能小車37:異常在ARM、JAVA、硬件裏的實現