s5pv210——中断实战
以下內容源于博客http://www.cnblogs.com/biaohc/p/6354068.html的學習,以及朱有鵬老師課程的學習,和網絡資源的整理。
一、s5pv210的中斷步驟
(1)建立異常向量表;
(2)中斷初始化;
(3)使能(如外部中斷,寫中斷處理函數);
(4)建立中斷號與中斷處理函數的聯系,使能。
當中斷發生時,中斷處理函數會自動處理中斷;
流程如下圖:
下面按上述步驟編寫代碼,內容細節見博客http://blog.csdn.net/oqqhutu12345678/article/details/71635611
二、代碼
1、建立異常向量表
/** s5pv210 裸機** 異常向量表初始化**/ #define VECTOR_TABLE_BASE 0xD0037400 #define Reset_offset 0x0 #define Undef_offset 0x4 #define SVC_offset 0x8 #define Prectch_offset 0xC #define Data_Abort_offset 0x10 #define IRQ_offset 0x18 #define FIQ_offset 0x1C#define _PFUNC_Reset (*(unsigned int*)(VECTOR_TABLE_BASE+Reset_offset)) #define _PFUNC_Undef (*(unsigned int*)(VECTOR_TABLE_BASE+Undef_offset)) #define _PFUNC_SVC (*(unsigned int*)(VECTOR_TABLE_BASE+SVC_offset)) #define _PFUNC_Prectch (*(unsigned int*)(VECTOR_TABLE_BASE+Prectch_offset)) #define _PFUNC_Data_Abort (*(unsigned int*)(VECTOR_TABLE_BASE+Data_Abort_offset)) #define _PFUNC_IRQ (*(unsigned int*)(VECTOR_TABLE_BASE+IRQ_offset)) #define _PFUNC_FIQ (*(unsigned int*)(VECTOR_TABLE_BASE+FIQ_offset)) extern void IRQ_handle(void);void Reset_handle(void) {} void Undef_handle(void) {} void SVC_handle(void) {} void Prectch_handle(void) {} void Data_Abort_handle(void) {}void vector_table_init(void) { _PFUNC_Reset = (unsigned int)Reset_handle;_PFUNC_Undef = (unsigned int)Undef_handle;_PFUNC_SVC = (unsigned int)SVC_handle;_PFUNC_Prectch = (unsigned int)Prectch_handle;_PFUNC_Data_Abort = (unsigned int)Data_Abort_handle;_PFUNC_IRQ = (unsigned int)IRQ_handle;//但凡是中斷,都會進入到此模式_PFUNC_FIQ = (unsigned int)IRQ_handle;//FIQ、IRQ都是采用IRQ中斷}其中,IRQ_handle要寫在匯編IRQ_handle.S中(因為要設置棧,以及保存現場 ),如下
#define IRQ_STACK 0xD0037F80 .global IRQ_handle IRQ_handle://設置IRQ的棧ldr sp, =IRQ_STACK//由于三級流水線的存在,pc為此時的程序語句+8,保存的時候要把下一句保存到lr中sub lr, lr, #4//保存現場stmd sp! {r0-r12, lr}//跳轉到中斷處理函數bl isr_handler//恢復現場ldmfd sp! {r0-r8, pc}^//這里為什么不是恢復r0~r12
ARM保存中斷時為什么使用 sub lr, lr, #4?
(1)首先要談流水線,在arm執行過程中一般分為取指,譯碼,執行階段;
- 假設當前第一條指令在執行階段,第二條指令在譯碼階段,第三條指令在取指階段;
- 若當前正在執行的指令地址為pc-8,那第二條就為pc-4,而pc指向取址。
(2)一般pc在發生中斷時lr保存的是當前的pc值,這里pc值是多少呢?
- 當發生中斷時,肯定保存的pc是第三條指令,而我們從中斷返回肯定不是執行第三條指令,而是緊接著的第二條指令,所以應該保存的 lr = pc - 4,(但是當執行到此位置時pc值已經改變,肯定不對,還好發生中斷時 mov lr,pc ,)所以這里就可以直接使用 sub lr,lr,#4,即lr=pc-4。
2、中斷初始化
//清除4個中斷處理函數 void clean_vicaddress(void) {_REG_VIC0ADDRESS = 0x0;_REG_VIC1ADDRESS = 0x0;_REG_VIC2ADDRESS = 0x0;_REG_VIC3ADDRESS = 0x0;}void interrupt_init(void) {//第一步初始化中斷之前要關閉所有中斷_REG_VIC0INTENCLEAR = 0xFFFFFFFF;_REG_VIC1INTENCLEAR = 0xFFFFFFFF;_REG_VIC2INTENCLEAR = 0xFFFFFFFF;_REG_VIC3INTENCLEAR = 0xFFFFFFFF;//第三步:設置中斷為IRQ中斷_REG_VIC0INTSELECT = 0x0;_REG_VIC1INTSELECT = 0x0;_REG_VIC2INTSELECT = 0x0;_REG_VIC3INTSELECT = 0x0;//第三步:清中斷處理函數地址clean_vicaddress();}void int_disable(unsigned int num) {if (num < 32) {_REG_VIC0INTENCLEAR = (0x1<<num);}else if (num < 64) {_REG_VIC1INTENCLEAR = (0x1<<(num-32)); }else if (num < 96) {_REG_VIC2INTENCLEAR = (0x1<<(num-64));}else if (num < 128) {_REG_VIC3INTENCLEAR = (0x1<<(num-96));}else {}}void int_enable(unsigned int num) {if (num < 32) {_REG_VIC0INTENABLE = (0x1<<num);}else if (num < 64) {_REG_VIC1INTENABLE = (0x1<<(num-32)); }else if (num < 96) {_REG_VIC2INTENABLE = (0x1<<(num-64));}else if (num < 128) {_REG_VIC3INTENABLE = (0x1<<(num-96));}else {_REG_VIC0INTENABLE = 0xFFFFFFFF;_REG_VIC1INTENABLE = 0xFFFFFFFF;_REG_VIC2INTENABLE = 0xFFFFFFFF;_REG_VIC3INTENABLE = 0xFFFFFFFF;}}void creat_israddr(unsigned int num, void (*PIRQ_handler)(void)) {if (num < 32) { //*( (void (*)(void))(VIC0VECTADDR + 4*num) )= PIRQ_handler;*( (volatile unsigned long *)(VIC0VECTADDR + 4*(num-0)) ) = (unsigned)PIRQ_handler;}else if (num < 64) {//(void (*)(void))(VIC1VECTADDR + 4*(num-32))= PIRQ_handler;*( (volatile unsigned long *)(VIC1VECTADDR + 4*(num-32)) ) = (unsigned)PIRQ_handler;}else if (num < 96) {//(void (*)(void))(VIC2VECTADDR + 4*(num-64))= PIRQ_handler;*( (volatile unsigned long *)(VIC2VECTADDR + 4*(num-64)) ) = (unsigned)PIRQ_handler;}else {//(void (*)(void))(VIC3VECTADDR + 4*(num-96))= PIRQ_handler;*( (volatile unsigned long *)(VIC3VECTADDR + 4*(num-96)) ) = (unsigned)PIRQ_handler;}}//判斷中斷在哪個address中static int check_int_addr(void) {if (_REG_VIC0IRQSTATUS) {return 0;}else if (_REG_VIC1IRQSTATUS) {return 1;}else if (_REG_VIC2IRQSTATUS) {return 2;}else if (_REG_VIC3IRQSTATUS) {return 3;}else {return -1;}} void isr_handler(void) {void (*p_isr)(void) = NULL;int i;i = check_int_addr();switch (i) {case 0 :p_isr = (void (*)(void))_REG_VIC0ADDRESS;break;case 1 :p_isr = (void (*)(void))_REG_VIC1ADDRESS;break;case 2 :p_isr = (void (*)(void))_REG_VIC2ADDRESS;break;case 3 :p_isr = (void (*)(void))_REG_VIC2ADDRESS;break;default :break;}p_isr();}3、使能外部中斷中斷處理函數
void int_led_blink(void) {//中斷處理函數 led_blink();//清楚外部中斷掛起,注意寫1清掛起clean_int_pend();//清vicaddressclean_vicaddress(); }4、建立中斷號與中斷函數聯系,使能中斷
#include "interrupt.h" #include "stdio.h" extern void led_blink(void); extern void led1_on(void); extern void vector_table_init(void); extern void key_init(void); extern void uart_init(void);int main(void) {//按鍵初始化key_inter_init();//異常向量表初始化vector_table_init();//中斷初始化interrupt_init();//創建函數creat_israddr(NUM_EINT2, int_led_blink);creat_israddr(NUM_EINT3, int_led_blink);creat_israddr(NUM_EINT16_31, int_led_blink);//使能中斷int_enable(NUM_EINT2);int_enable(NUM_EINT3);int_enable(NUM_EINT16_31);while (1) {printf("a");}}
小總結:
一、S5PV210中斷處理的編程實踐
2、中斷控制器初始化
- 主要工作有:第一階段綁定異常向量表到異常處理程序;禁止所有中斷源;選擇所有中斷類型為IRQ;清理VICnADDR寄存器為0.
3、中斷的使能與禁止
- 思路是先根據中斷號判斷這個中斷屬于VIC幾,然后在用中斷源減去這個VIC的偏移量,得到這個中斷號在本VIC中的偏移量,然后1<<x位,寫入相應的VIC的INTENABLE/INTENCLEAR寄存器即可。
4、綁定自己實現的isr到VICnVECTADDR
- 搞清楚2個寄存器的區別:VICnVECTADDR和VICnADDR
- VICVECTADDR寄存器一共有4×32個,每個中斷源都有一個VECTADDR寄存器,將自己為這個中斷源寫的isr地址丟到這個中斷源對應的VECTADDR寄存器中即可。
5、真正的中斷處理程序如何獲取isr
- 發生中斷時,硬件自動把相應中斷源的isr地址從VICnVECTADDR寄存器推到VICnADDR寄存器中,所以只需要到相應的VICnADDR中去拿出isr地址,調用執行即可。
- 第4步綁定isr地址到VICnVECTADDR,以及第5步中斷發生時第二階段的第二階段如何獲取isr地址,這兩步是相關的。這兩個的結合技術,就是x210的硬件自動尋找isr的機制。
二、整個中斷的流程梳理:
整個中斷的工作分為2部分:
第一部分是我們為中斷響應而做的預備工作:
1. 初始化中斷控制器
2. 綁定寫好的isr到中斷控制器
3. 相應中斷的所有條件使能
第二部分是當硬件產生中斷后如何自動執行isr:
1. 第一步,經過異常向量表跳轉入IRQ/FIQ的入口
2. 第二步,做中斷現場保護(在start.S中),然后跳入isr_handler
3. 第三步,在isr_handler中先去搞清楚是哪個VIC中斷了,然后直接去這個VIC的ADDR寄存器中取isr來執行即可。
4. 第四步,isr執行完,中斷現場恢復,直接返回繼續做常規任務。
總結
以上是生活随笔為你收集整理的s5pv210——中断实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CTF|逆向工程软件之IDA
- 下一篇: 抑郁症调研