首先,謝謝大家能夠進來看我的這個問題。
我想請教一個問題:
代碼:
NoInt EQU 0x80
USR32Mode EQU 0x10
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
;引入的外部标号在這聲明
IMPORT OSIntCtxSw ;任務切換函數
IMPORT OSIntExit ;中斷退出函數
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSIntNesting ;中斷嵌套計數器
IMPORT StackUsr
IMPORT OsEnterSum
CODE32
PRESERVE8
AREA IRQ,CODE,READONLY
MACRO
$IRQ_Label HANDLER $IRQ_Exception_Function
EXPORT $IRQ_Label ; 輸出的标号
IMPORT $IRQ_Exception_Function ; 引用的外部标号
$IRQ_Label
SUB LR, LR, #4 ; 計算傳回位址
STMFD SP!, {R0-R3, R12, LR} ; 儲存任務環境
MRS R3, SPSR ; 儲存狀态
STMFD SP, {R3, SP, LR}^ ; 儲存使用者狀态的R3,SP,LR,注意不能回寫
; 如果回寫的是使用者的SP,是以後面要調整SP
LDR R2, =OSIntNesting ; OSIntNesting++
LDRB R1, [R2]
ADD R1, R1, #1
STRB R1, [R2]
SUB SP, SP, #4*3
MSR CPSR_c, #(NoInt | SYS32Mode) ; 切換到系統模式
CMP R1, #1
LDREQ SP, =StackUsr
BL $IRQ_Exception_Function ; 調用c語言的中斷處理程式
; MSR CPSR_c, #(NoInt | SYS32Mode) ; 切換到系統模式
LDR R2, =OsEnterSum ; OsEnterSum,使OSIntExit退出時中斷關閉
MOV R1, #1
STR R1, [R2]
BL OSIntExit
LDR R2, =OsEnterSum ; 因為中斷服務程式要退出,是以OsEnterSum=0
MOV R1, #0
STR R1, [R2]
MSR CPSR_c, #(NoInt | IRQ32Mode) ; 切換回irq模式
LDMFD SP, {R3, SP, LR}^ ; 恢複使用者狀态的R3,SP,LR,注意不能回寫
; 如果回寫的是使用者的SP,是以後面要調整SP
LDR R0, =OSTCBHighRdy
LDR R0, [R0]
LDR R1, =OSTCBCur
LDR R1, [R1]
CMP R0, R1
ADD SP, SP, #4*3 ;
MSR SPSR_cxsf, R3
LDMEQFD SP!, {R0-R3, R12, PC}^ ; 不進行任務切換
LDR PC, =OSIntCtxSw ; 進行任務切換
MEND
;
;
IRQ_Handler HANDLER IRQ_Exception
UART1_Handler HANDLER UART1_Exception
;
Timer0_Handler HANDLER Timer0_Exception
END
個人了解:
這裡是定義一個Handler的宏,該宏是用來做進入中斷前的處理。
問題:
為什麼在UC/OS-II中添加3個中斷句柄,而在一個while(1)的前背景系統中沒有定義?
是不是該這樣了解:
進入中斷函數有兩種方式,一種是C語言的,另一種是彙編語言的,彙編語言就采用了句柄的方式,而在彙編中采用的是在函數名前加_IRQ,來表示該函數為中斷函數,兩者是等同的作用。如果是這樣的話,那用_IRQ方式的句柄,他在進入中斷前處理的代碼在哪裡呢?是編譯器自動生成的嗎?怎樣可以檢視?是編譯器處理的話,是不是不同的編譯器處理的代碼有或多或少的差別呢?
附:
用的是keil的編譯環境。
用沒有人可以系統地講解一下,謝謝大家了!