1. 程式人生 > >異常向量表的程式設計處理

異常向量表的程式設計處理

《朱老師物聯網大講堂》學習筆記

學習地址:www.zhulaoshi.org

像記憶體一樣去訪問異常向量表。

在我們開發板中iRAM的向量異常表的起始地址為0xd0037400,

結合上節說的,相對地址是固定的,而這裡起始地址又確定了,

各種異常對應的入口地址就很好知道了。


函式名的實質就是函式的首地址,拿C語言中的語言來講,函式名就是這個函式的函式指標,

將異常向量表和異常處理程式的首地址繫結起來後,異常處理初步階段就完成了,

目前如果相應異常發生後,硬體自動跳轉到對應異常向量表入口去執行,進而執行我們事先繫結的函式。

第一眼看到下面的異常向量表繫結,會覺得不知所以,其實前面有巨集定義,

#define exception_vector_table_base  0xD0037400


#define exception_reset     (exception_vector_table_base + 0x00)


#define r_exception_reset  (*(volatile unsigned int *)exception_reset)

void system_init_exception(void)
{
	r_exception_reset = (unsigned int)reset_exception;
	r_exception_undef = (unsigned int)undef_exception;
	r_exception_sotf_int = (unsigned int)sotf_int_exception;
	r_exception_prefetch = (unsigned int)prefetch_exception;
	r_exception_data = (unsigned int)data_exception;
	r_exception_irq = (unsigned int)IRQ_handle;
	r_exception_fiq = (unsigned int)IRQ_handle;	
	intc_init();
}


為什麼中斷處理要先在彙編中進行,

因為中斷是從SVC模式開始的,要儲存該模式下必要的暫存器值,

中斷完成後返回SVC,恢復這些暫存器的值,

否則SVC模式暫存器的值就亂了,SVC模式下原來正在進行的常規任務就被你破壞了。

現場儲存包括

1.設定IRQ棧,各個模式的棧不同,所以各自要單獨設定,

ldrsp, IRQ_STACK

sp名字只有一個,不過在不同模式下會自動切換到對應的sp,

2.儲存LR,中斷返回時2個關鍵暫存器就是pc和CPSR,

在進入IRQ模式時,應該將SVC模式下的下一句指令的地址和CPSR儲存起來,

將來恢復時將返回地址給PC,將儲存的CPSR給CPSR,

中斷返回地址就儲存在LR中,而CPSR自動儲存在IRQ的SPSR中,

3.儲存R0~R12。

#define IRQ_STACK 0xd0037f80

IRQ_handle:
	ldr	sp,	IRQ_STACK
	sub lr, lr, #4
//這裡的4這樣理解,+8-4,因為是3級指令,
	stmfd sp!	{r0-r12, lr}
	bl	irq_handler
	ldrfd	sp!	{r0-r12, pc}^