我的RTOS 之一 --S5PV210 异常向量表基址和软中断测试


1、异常向量表基址

s5pv210 默认指定了异常向量基址0xD003_4700, 当异常比如中断触发时,会自动跳转到基址查找异常处理函数s5pv210 默认指定了异常向量基址0xD003_4700, 当异常比如中断触发时,会自动跳转到基址查找异常处理函数

我的RTOS 之一 --S5PV210 异常向量表基址和软中断测试_第1张图片

通过代码可以这样实现,通过代码可以这样实现,

#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


你可能感兴趣的:(我的RTOS 之一 --S5PV210 异常向量表基址和软中断测试)