1、异常向量表基址
s5pv210 默认指定了异常向量基址0xD003_4700, 当异常比如中断触发时,会自动跳转到基址查找异常处理函数s5pv210 默认指定了异常向量基址0xD003_4700, 当异常比如中断触发时,会自动跳转到基址查找异常处理函数
通过代码可以这样实现,通过代码可以这样实现,
#define _Exception_Vector 0xD0037400 #define pExceptionRESET ( *((volatile unsigned long *)(_Exception_Vector + 0x0)) ) #define pExceptionUNDEF ( *((volatile unsigned long *)(_Exception_Vector + 0x4)) ) #define pExceptionSWI ( *((volatile unsigned long *)(_Exception_Vector + 0x8)) ) #define pExceptionPABORT ( *((volatile unsigned long *)(_Exception_Vector + 0xc)) ) #define pExceptionDABORT ( *((volatile unsigned long *)(_Exception_Vector + 0x10)) ) #define pExceptionRESERVED ( *((volatile unsigned long *)(_Exception_Vector + 0x14)) ) #define pExceptionIRQ ( *((volatile unsigned long *)(_Exception_Vector + 0x18)) ) #define pExceptionFIQ ( *((volatile unsigned long *)(_Exception_Vector + 0x1c)) ) void system_vector_init( void) { pExceptionRESET = (unsigned long)exceptionreset; pExceptionUNDEF = (unsigned long)exceptionundef; pExceptionSWI = (unsigned long)SWI_handle; pExceptionSWI1 = (unsigned long)exceptionswi; pExceptionPABORT = (unsigned long)exceptionpabort; pExceptionDABORT = (unsigned long)exceptiondabort; pExceptionIRQ = (unsigned long)IRQ_handle; pExceptionFIQ = (unsigned long)exceptionfiq; }
查找三星手册也没有找到原因。
2、异常向量基址可以设置
s5pv210 也通过操作协处理器设置向量基址为高地址,或者通过MMU映射到内存的任何地方,但是它具有更灵活的功能,可以设置异常向量基址到任何地方,这样方便移植裸机和移植RTOS。
s5pv210可以设置三种模式(安全模式 监视模式 和 非安全模式)的异常向量基址。
通过测试,通过设置异常向量基址,SWI软中断测试成功.
通过修改C12设置当前模式下异常向量基址:
.global _set_interrupt_vector _set_interrupt_vector: mcr p15, 0, r0, c12, c0, 0 mrc p15, 0, r0, c12, c0, 0 mov pc, lr
static inline unsigned int get_vectors_address(void) { unsigned int temp; /* read SCTLR */ __asm__ __volatile__( "mrc p15, 0, %0, c1, c0, 0\n" :"=r"(temp) : ); if (temp & (1<<13)) return (unsigned int ) 0xffff0000; /* read VBAR */ __asm__ __volatile__("mrc p15, 0, %0, c12, c0, 0\n" : "=r" (temp) : ); return (unsigned int ) temp; }
通过 “swi xxx” 或者 “svc xxx”可以触发软中断, xxx必须是立即数,不能是 寄存器。
软中断触发之后,处理器(硬件上)会自动把 swi的下一条指令,保存到 svc模式下的lr,把当前下的cpsr保存到 svc模式下的spsr。swi必须有下一条指令,并且可以正常运行。
所以,可以这样实现swi触发函数
switest: stmfd sp!, {fp, lr} swi 0x8 ldmfd sp!, {fp, pc}swi的下一条指令 正好可以把swi中断完成之后的操作 放到switest函数后面。
swi的处理函数可以这样完成:
swi_handle: stmfd sp!, {r0-r12, lr} mov r1, r0 mrs r0, spsr stmfd sp!, {r0} tst r0, #0x20 ldrne r0, [lr, #-2] bicne r0, r0, #0xff00 ldreq r0, [lr, #-4] biceq r0, r0, #0xff000000 bl c_swi_handler ldmfd sp!, {r0} msr spsr_cf, r0 ldmfd sp!, {r0-r12, pc}^
4、程序运行
Timer0IntCounter = 0 Timer0IntCounter = 1 Timer0IntCounter = 2 swi test:1 c_swi_handler:8,arg:3 Timer0IntCounter = 3 Timer0IntCounter = 4 Timer0IntCounter = 5 swi test:2 c_swi_handler:8,arg:6 Timer0IntCounter = 6 Timer0IntCounter = 7 Timer0IntCounter = 8 swi test:3 c_swi_handler:8,arg:9 Timer0IntCounter = 9 Timer0IntCounter = 10 Timer0IntCounter = 11 swi test:4
demo链接http://download.csdn.net/detail/liujia2100/8102515