1:s5pv210的中断步骤
(1):建立异常向量表;
(2):写入中断处理函数;
(3):中断初始化;
(4):建立中断号与中断处理函数的联系,使能中断;
当中断发生时,中断处理函数会自动处理中断;
流程如下:
2:建立异常向量表:
s5pv210异常向量表的基地址为0xD003_7400,下图为异常对于基地址的偏移量;
第一步建立异常向量表:
代码如下:
/* * s5pv210 裸机 * * 异常向量表初始化 * */ #define VECTOR_TABLE_BASE 0xD0037400 #define Reset_offset 0x0 #define Undef_offset 0x4 #define SVC_offset 0x8 #define Prectch_offset 0xC #define Data_Abort_offset 0x10 #define IRQ_offset 0x18 #define FIQ_offset 0x1C #define _PFUNC_Reset (*(unsigned int*)(VECTOR_TABLE_BASE+Reset_offset)) #define _PFUNC_Undef (*(unsigned int*)(VECTOR_TABLE_BASE+Undef_offset)) #define _PFUNC_SVC (*(unsigned int*)(VECTOR_TABLE_BASE+SVC_offset)) #define _PFUNC_Prectch (*(unsigned int*)(VECTOR_TABLE_BASE+Prectch_offset)) #define _PFUNC_Data_Abort (*(unsigned int*)(VECTOR_TABLE_BASE+Data_Abort_offset)) #define _PFUNC_IRQ (*(unsigned int*)(VECTOR_TABLE_BASE+IRQ_offset)) #define _PFUNC_FIQ (*(unsigned int*)(VECTOR_TABLE_BASE+FIQ_offset)) void Reset_handle(void) { } void Undef_handle(void) { } void SVC_handle(void) { } void Prectch_handle(void) { } void Data_Abort_handle(void) { } void vector_table_init(void) { _PFUN_Reset = Reset_handle; _PFUNC_Undef = Undef_handle; _PFUNC_SVC = SVC_handle; _PFUNC_Prectch = Prectch_handle; _PFUNC_Data_Abort = Data_Abort_handle; _PFUNC_IRQ = IRQ_handle; _PFUNC_FIQ = IRQ_handle; //FIQ、IRQ都是采用IRQ中断 }
IRQ_handle要写在汇编IRQ_handle.S中;
代码如下:
/* * * * * */ #define IRQ_STACK 0xD0037F80 .global IRQ_handle IRQ_handle: //设置IRQ的栈 ldr sp, =IRQ_STACK //由于三级流水线的存在,pc为此时的程序语句+8,保存的时候要把下一句保存到lr中 sub lr, lr, #4 //保存现场 stmd sp! {r0-r12, lr} //跳转到中断处理函数 bl isr_handler //恢复现场 ldmfd sp! {r0-r8, lr}^
ARM保存中断时为什么使用 sub lr, lr, #4
1. 首先要谈流水线,在arm执行过程中一般分为取指,译码,执行阶段
也就是假设当前 第一条指令在执行阶段
第二条指令在译码阶段
第三条指令在取指阶段
当前正在执行的指令地址为pc-8,第二条就为pc-4,而pc现在真正指向已处于pc位置
2. 一般pc在发生中断时lr保存的是当前的pc值,这里pc值是多少呢??
当发生中断肯定保存的pc是第三条指令,而我们从中断返回肯定不是执行第三条指令,而是紧接着的第二条指令,所以应该保存的 lr = pc - 4,
但是当执行到此位置时pc值已经改变,肯定不对,还好发生中断时 mov lr,pc 所以这里就可以直接使用 sub lr,lr,#4
————————————————————未完待续————————————————————————————
时间: 2024-09-28 19:50:19