這個 2440test里面的中斷寫的向量有些隱蔽,兜了很多個圈,也難怪這么難理解,下面
就對這個東西抽絲剝繭,看清楚這究竟是一個怎么樣的過程。
中斷向量
b HandlerIRQ ;handler for IRQ interrupt
很自然,因為所有的單片機都是那樣,中斷向量一般放在開頭,用過單片機的人都會很熟悉
那就不多說了。
異常服務程序
這里不用中斷(interrupt)而用異常(exception),畢竟中斷只是異常的一種情況,呵呵
下面主要分析的是“中斷異常”說白了,就是我們平時單片機里面用的中斷!!!所有有器件
引起的中斷,例如TIMER中斷,UART中斷,外部中斷等等,都有一個統(tǒng)一的入口,那就是中斷
異常 IRQ ! 然后從IRQ的服務函數(shù)里面分辨出,當前究竟是什么中斷,再跳轉(zhuǎn)到相應的中斷
服務程序。這樣看來,ARM比單片機要復雜一些了,不過原理是不變的。
上面說的就是思路,跟著這個思路來接著分析。
HandlerIRQ 很明顯是一個標號,我們找到了
HandlerIRQ HANDLER HandleIRQ
這里是一個宏定義,我們再找到這個宏,看他是怎么定義的:
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original
address)
ldr r0,=$HandleLabel ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
用 HandlerIRQ 將這個宏展開之后得到的結(jié)果實際是這樣的
HandlerIRQ
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original
address)
ldr r0,=HandleIRQ ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
至于具體的跳轉(zhuǎn)原理下面再說好了,這樣的話就容易看的多了,很明顯, HandlerIRQ 還是一個標號,IRQ異常向量就是跳
轉(zhuǎn)到這里執(zhí)行的,這里粗略看一下,應該是保存現(xiàn)場,然后跳轉(zhuǎn)到真正的處理函數(shù),那么很容易
發(fā)現(xiàn)了這么一句 ldr r0,=HandleIRQ ,沒錯,我們又找到了一個標號 HandleIRQ ,看來真正的處理函數(shù)應該是這個 HandleIRQ ,繼續(xù)尋找
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
最后我們發(fā)現(xiàn)在這里找到了 HandleIRQ ,^ 其實就是 MAP ,這段程序的意思是,從 _ISR_STARTADDRESS
開始,預留一個變量,每個變量一個標號,預留的空間為 4個字節(jié),也就是 32BIT,其實這里放的是真正
的C寫的處理函數(shù)的地址,說白了,就是函數(shù)指針 - -
這樣做的話就很靈活了
好好學習,天天向上作者: Hugo801122 時間: 2014-2-20 01:41
這個 2440test里面的中斷寫的向量有些隱蔽,兜了很多個圈,也難怪這么難理解,下面
就對這個東西抽絲剝繭,看清楚這究竟是一個怎么樣的過程。
中斷向量
b HandlerIRQ ;handler for IRQ interrupt
很自然,因為所有的單片機都是那樣,中斷向量一般放在開頭,用過單片機的人都會很熟悉
那就不多說了。
異常服務程序
這里不用中斷(interrupt)而用異常(exception),畢竟中斷只是異常的一種情況,呵呵
下面主要分析的是“中斷異常”說白了,就是我們平時單片機里面用的中斷!!!所有有器件
引起的中斷,例如TIMER中斷,UART中斷,外部中斷等等,都有一個統(tǒng)一的入口,那就是中斷
異常 IRQ ! 然后從IRQ的服務函數(shù)里面分辨出,當前究竟是什么中斷,再跳轉(zhuǎn)到相應的中斷
服務程序。這樣看來,ARM比單片機要復雜一些了,不過原理是不變的。
上面說的就是思路,跟著這個思路來接著分析。
HandlerIRQ 很明顯是一個標號,我們找到了
HandlerIRQ HANDLER HandleIRQ
這里是一個宏定義,我們再找到這個宏,看他是怎么定義的:
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} USH the work register to stack(lr does not push because it return to original
address)
ldr r0,=$HandleLabel ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} OP the work register and pc(jump to ISR)
MEND
用 HandlerIRQ 將這個宏展開之后得到的結(jié)果實際是這樣的
HandlerIRQ
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} USH the work register to stack(lr does not push because it return to original
address)
ldr r0,=HandleIRQ ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} OP the work register and pc(jump to ISR)
至于具體的跳轉(zhuǎn)原理下面再說好了,這樣的話就容易看的多了,很明顯, HandlerIRQ 還是一個標號,IRQ異常向量就是跳
轉(zhuǎn)到這里執(zhí)行的,這里粗略看一下,應該是保存現(xiàn)場,然后跳轉(zhuǎn)到真正的處理函數(shù),那么很容易
發(fā)現(xiàn)了這么一句 ldr r0,=HandleIRQ ,沒錯,我們又找到了一個標號 HandleIRQ ,看來真正的處理函數(shù)應該是這個 HandleIRQ ,繼續(xù)尋找
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
最后我們發(fā)現(xiàn)在這里找到了 HandleIRQ ,^ 其實就是 MAP ,這段程序的意思是,從 _ISR_STARTADDRESS
開始,預留一個變量,每個變量一個標號,預留的空間為 4個字節(jié),也就是 32BIT,其實這里放的是真正
的C寫的處理函數(shù)的地址,說白了,就是函數(shù)指針 - -
這樣做的話就很靈活了