對於各種中斷源的響應,s3c44b0有兩種中斷模式:向量中斷模式和非向量中斷模式,這就導致在軟體處理上,可以很靈活的處理中斷請求。一般來說做如下處理:
如果系統採用的rom定位在位址0x00,則中斷向量標應該包含一系列分支語句,跳轉到相應的中斷處理程式(這也是s3c44b0所支援的模式)
如果rom定位到別的位址處,向量必須由初始化**進行動態定位。
一般把這部分功能放在bootloader中處理,對於這一點來說初學者很容易搞混,下面就詳細解釋中斷處理的幾種實現方式。
一、中斷處理的實現方式
1、向量中斷模式(也叫向量中斷模式)(
irq
支援,
fiq
不支援)
為了縮短中斷模式在進入所需的服務前所需要的中斷響應時間,s3c44b0提供了一種新的中斷模式——向量中斷模式。當多重中斷源請求中斷時,硬體優先順序邏輯會判斷哪乙個中斷將會被執行,同時,硬體邏輯自動執行由0x18位址到各個中斷源向量位址的跳轉指令,然後再由中斷源向量進入相應的中斷處理程式。簡單的說,每個中斷源對應乙個記憶體位址,只要在對應的位址上設定一條到中斷服務程式的跳轉指令,cpu自動跳轉到響應的中斷處理函式。和原來的軟體實現方式相比,這種方式可顯著縮短中斷響應時間。
當系統發生
irq中斷時候,
cpu的
pc會讀取位於
0x18
處的irq
中斷指令(也就是說跳到位址
0x18
處去執行指令),然後
cpu自動讀取對應於該中斷源確定位址上的指令取代
0x18
處的指令(這個過程是由系統自動完成的,不需要使用者程式設計),通過跳轉指令,系統就直接跳轉到對應位址,這樣節省了中斷處理時間,提高中斷處理速度。——通俗點說,如果採用了向量中斷模式,一旦發生中斷,
cpu就會跳到相應的位址來執行指令。
例如adc
中斷的向量位址為
0xc0,
一旦發生
adc中斷,
pc就先跳到了位址
0x18
再跳到0xc0
上來執行命令,但對於使用者來說,就跟一發生中斷就直接跳到了
0xc0
上沒有區別,這個先跳到
0x18
的過程可以忽略不計,由系統自動完成。如果在
0xc0
處放如下**:
ldr pc , =handleradc
,當adc
中斷產生的時候系統會自動跳轉到
handleradc
函式中。
2、非向量中斷模式
這種模式處理方式是一種傳統的中斷處理方法,當系統產生中斷的時候,系統將
interrupt pending
暫存器中對應標誌位置位(當然向量中斷模式也有這步發生),然後跳轉到位址
0x18
處。使用者需要在位址
0x18
處寫乙個統一中斷函式,該函式通過讀取
interrupt pending
暫存器中對應標誌位,來判斷中斷源,並根據優先順序關係再跳到對應中斷源的處理**中。
在非向量中斷模式下,有兩種方式可以使pc指向相應的中斷處理程式。
第一種方法,可以通過對i_ispr/f_ispr暫存器的分析判斷出中斷的型別,然後再把pc指向相應的中斷處理程式。其中handler***實際上是一段跳轉程式,執行這段程式將把handle***指向的內容值賦給pc。由於handle***所對應的位址中,存放的是每個相應的isr的起始位址,這樣就完成了向特定isr的調轉。這些isr位址存放在handle***指向的表項中,該錶一般定位在ram高階,基位址為isr_startaddress。
第二種方法,對於irq處理程式可以通過對i_cmst暫存器的分析來判斷中斷源的型別,然後再把pc指向相應當中斷處理程式。
之所以被稱為向量中斷模式,是因為它不需要用程式判斷中斷源,通過硬體實現直接跳轉到相應isr。而非向量中斷必須在中斷服務程式中判斷中斷**,進而跳轉到不同的處理程式。
在非向量中斷模式下,中斷響應流程如下:
1、通常情況下,cpu核心收到來自中斷控制器的irq中斷請求,會在0x00000018處執行一條指令,在從0x00000018處取指令時,中斷控制器會在資料匯流排上載入分支指令。這些分支指令使程式計數器能夠對應到每乙個中斷源的向量位址。所以,一般會在從0x00處到0xa0處放置跳轉指令,跳轉到handler***處。
2、handler***處一般放置彙編下面的一段中斷處理巨集(一般定義為handler),入口是跳轉位址,
主要流程:
棧空間遞減儲存跳轉位址
儲存工作暫存器r0到棧
載入中斷入口位址所在位置到r0
載入中斷入口位址到r0
儲存中斷入口位址到棧
二、向量中斷模式的啟動**分析及程式設計。
1、
中斷向量模式中,具體實現如下:
中斷服務入口位址處,寫入乙個呼叫巨集的指令(類似於子程式),這個巨集是乙個「引導程式」,把中斷服務的首位址裝載於
pc中。具體呼叫乙個框圖來表示
,結合以下的程式理解,接下來還有乙個針對框圖的具體的講解。以
adc中斷為例子:
①啟動**
44binit.s
定義了乙個巨集:
$handlerlabel handler。
②啟動**
44binit.s
把「ldr
pc , =handler***
」裝入了對應的位址中(在
0x0為首的一系列位址中),例如「
ldrpc , =handleradc
」這條指令被裝入了
0x000000c0
位址中。
③啟動**
44binit.s
開闢了一些在
sdram
(>0x0c000000
)上的以
_isr_startaddress
(我的板子程式定義為
0x0c7fff00
)為基址的一些位址中,每個位址用乙個標號表示,用於存放中斷服務程式的位址。例如,「
handleadc
# 4」,可以
handleadc
認為是_isr_startaddress+0x20
的這個位址的標號。詳見**。
④在main.c包含的標頭檔案44b.h中,對於
「_isr_startaddress+0x20
」有如下定義,
#define
pisr_adc
(*(unsigned *)(_isr_startaddress+0x20))
,pisr_adc
這是乙個指標,在上乙個步驟中,開闢出來空間就是給這個指標用的。
⑤在main.c或者其他的c檔案裡,包含44b.h這個標頭檔案的前提下,可以編寫乙個中斷處理函式,void
__irq
isr_adc
(),然後再加入語句
pisr_adc=
(unsignde
)isr_adc
,這樣就把
isr_adc
()這個函式的位址寫入了
_isr_startaddress+0x20)
這個位址中。值得注意的是,是位址被寫入了位址。 ⑥
adc中斷發生,
pc跳轉到執行
0x 000000c0處。
⑦cpu
執行存放在位址
0x000000c0
上的「ldr
pc , =handleradc
」這條指令。
⑧pc
再跳至執行巨集指令「
handleradc
handler
handleadc
」,此巨集指令(實質上就是乙個子程式)執行完的結果,就是把
(_isr_startaddress+0x20)
這個位址上存放的子程式
isr_adc
()位址給pc,
pc就執行
isr_adc
()。
⑨執行完畢,返回。
注:(1)步驟
①②③在出現在
44binit.s
,詳見我的啟動**中的注釋。 (
2)_isr_startaddress
的定義在
option.inc
中:_isr_startaddress
equ0xc7fff00 (
3)步驟
④在44b.h中定義:
#define
pisr_adc
(*(unsigned *)(_isr_startaddress+0x20))
(4)在main.c或者其他的c檔案裡,寫入:
void
__irq
isr_adc()和
pisr_adc=
(unsignde
)isr_adc
(5)必須加入在中斷服務程式中
__irq
,以高速編譯器這個是乙個中斷服務程式,這樣編譯器會在編譯時候加上返回使用者模式的**,以實現中斷後程式的自動返還。
U Boot在S3C44B0上的移植方法
bootloader 給嵌入式作業系統提供板上硬體資源資訊,並進一步載入 引導嵌入式作業系統。由於bootloader 的功能直接與cpu和微處理器系統相關,所以不同的cpu體系將需要不同的bootload er。除了依賴於cpu的體系結構外,bootloader 實際上也依賴於具體的嵌入式板級裝置...
S3C44B0的初始化程式的理解(ran
s3c44b0的初始化程式就是初始化各個關鍵的暫存器,建立中斷向量,然後轉移到主函式去執行程式。不過s3c44b0不支援位址對映,所以程式不copy到ram種執行。s3c44b0初始化對我們廣大初學者來說,比較難理解的是中斷的處理和一些少見的操作符號,s3c44b0的中斷子程式位址存放在初始化程式最...
S3C44B0的初始化程式的理解(ran
s3c44b0的初始化程式就是初始化各個關鍵的暫存器,建立中斷向量,然後轉移到主函式去執行程式。不過s3c44b0不支援位址對映,所以程式不copy到ram種執行。s3c44b0初始化對我們廣大初學者來說,比較難理解的是中斷的處理和一些少見的操作符號,s3c44b0的中斷子程式位址存放在初始化程式最...