我的RTOS 之一 --S5PV210 異常向量表基址和軟中斷測試


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


發佈了112 篇原創文章 · 獲贊 39 · 訪問量 56萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章