谢谢大家能够进来看我的这个问题。 我想请教一个问题: 代码:
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 ;/*定时器0中断*/ Timer0_Handler HANDLER Timer0_Exception
END
个人理解: 这里是定义一个Handler的宏,该宏是用来做进入中断前的处理。
问题: 为什么在UC/OS-II中添加3个中断句柄,而在一个while(1)的前后台系统中没有定义? 是不是该这样理解: 进入中断函数有两种方式,一种是C语言的,另一种是汇编语言的,汇编语言就采用了句柄的方式,而在C中采用的是在函数名前加_IRQ,来表示该函数为中断函数,两者是等同的作用。如果是这样的话,那用_IRQ方式的句柄,他在进入中断前处理的代码在哪里呢?是编译器自动生成的吗?怎样可以查看?是编译器处理的话,是不是不同的编译器处理的代码有或多或少的区别呢? 附: 用的是keil的编译环境。
用没有人可以系统地讲解一下,谢谢大家了!
|