異常向量表的程式設計處理
《朱老師物聯網大講堂》學習筆記
學習地址: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}^