日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

s5pv210——中断实战

發布時間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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——中断实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。