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;
}
虽然IRQ中断可以成功实现跳转,但是SWI软中断却失败。
查找三星手册也没有找到原因。
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
在C代码中也可以读取向量基址
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;
}
3、软中断
通过 “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}^
先保存寄存器,再保存spsr,因为不知道swi处理的过程中有没有再次异常发生,注意判断c程序是不是thump编译的,所以需要检测spsr的thump标志位。 处理完成后,处理器会从svc模式返回到 执行swi之前的模式。
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