色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > ARM異常處理設置

ARM異常處理設置 時間:2019-07-11      來源:沈陽中心,楊老師

Arm異常有下列這些

復位異常、數據異常、快速中斷異常、外部中斷異常、預取異常、軟中斷異常、未定義指令異常。

那么每種異常有一個相應的異常指令執行地址,即異常向量表

異常                   執行地址

復位異常             0x0000 0000

未定義指令異常       0x0000 0004

軟中斷異常           0x0000 0008

預取異常             0x0000 000C

數據異常             0x0000 0010

外部中斷異常(IRQ)    0x0000 0018

快速中斷異常(FIQ)    0x0000 001C

如果想理解異常處理過程,就要理解Arm啟動代碼, 下面以IRQ中斷為例,講解異常處理過程。

一 啟動代碼

1) Arm啟動先執行一段啟動代碼(start.S),這段代碼是用匯編寫的

2) 然后,匯編代碼再執行到c的main函數

二 start.S講解

//////////////////////////////////////////////////////////////////

.text

.global _start                        @@@@  _start  是一個全局標號 (表示在其他函數可以調用_start)

_start:                                           @@@@  通常被指定為0x0000 0000地址 

b reset             @@@@  此段代碼放在0x0000 0000地址處 ,命令功能是跳轉到reset處去執行

ldr pc,_undefined_instruction

ldr pc,_software_interrupt

ldr pc,_prefetch_abort

ldr pc,_data_abort

ldr pc,_not_used

ldr pc,_irq           @@@@  將_irq地址處的指令地址給PC ,相當于一條跳轉命令,這條指令回放在0x0000 0018處

ldr pc,_fiq

_undefined_instruction: .word  _undefined_instruction

_software_interrupt: .word  _software_interrupt

_prefetch_abort: .word  _prefetch_abort

_data_abort: .word  _data_abort

_not_used: .word  _not_used

_irq: .word  irq_handler    @@@@  .word  是一條偽指令,相當于定義一個4字節的變量_irq,值為irq_handler

     @@@@  等價于 int _irq = irq_handler

_fiq: .word  _fiq

      @@@@    偽指令:不是一條實際的匯編指令,變量定義,宏定義,數組定義

reset:

        @@@@  初始化 協處理器

ldr r0,=0x40008000

mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register 

@@@@  設置cpsr的值,為0xd3

mrs   r0,cpsr         

bic r0,r0,#0x1f

orr r0,r0,#0xd3   @@@@   0xd3    1101 0011  禁止FIQ, IRQ, 處于ARM狀態 ,模式為管理模式 SVC

msr cpsr,r0         @ Enable svc mode of cpu

init_stack:    @@@@初始化堆棧, svc, irq, fiq.... 每種模式的堆棧大小為512字節

ldr r0,stacktop         /*get stack top pointer*/

/********svc mode stack********/

mov sp,r0

sub r0,#128*4          /*512 byte  for irq mode of stack*/

/****irq mode stack**/

msr cpsr,#0xd2

mov sp,r0

sub r0,#128*4          /*512 byte  for irq mode of stack*/

/***fiq mode stack***/

msr cpsr,#0xd1

mov sp,r0

sub r0,#0

/***abort mode stack***/

msr cpsr,#0xd7

mov sp,r0

sub r0,#0

/***undefine mode stack***/

msr cpsr,#0xdb

mov sp,r0

sub r0,#0

/*** sys mode and usr mode stack ***/

msr cpsr,#0x10

mov sp,r0             /*1024 byte  for user mode of stack*/

@@@此處可以添加自己的初始化代碼

b main     @@@@  跳轉到main函數,不會回來了

.align 4

/****  swi_interrupt handler  ****/

//到中斷時再講

/****  irq_handler  ****/

irq_handler:    @@@@    一旦IRQ中斷會跳轉到這,  1) ARM 會將PC  ->  LR

sub  lr,lr,#4 @@@@ 指令流水線         取指   譯碼   執行   (正在執行的指令是  PC - 8, 下一條要執行的是PC - 4)

@@@@   pc-->0x1108     0x1108  0x1104  0x1100

stmfd sp!,{r0-r12,lr}    @@@@ 將r0-r12, lr寄存器入棧,,,,保護現場

bl do_irq           @@@@ 跳轉到中斷服務程序do_irq, 執行完再回來

ldmfd sp!,{r0-r12,pc}^   @@@@ 將棧中數據出棧,給r0-r12, lr寄存器,,,,恢復現場

stacktop:    .word stack+4*512 @@@@ .word 定義一個整型變量    int stacktop 

.data

stack: .space  4*512 @@@@.space   相當于定義一個數組   char stack[4 * 512];

/////////////////////////////////下面是C代碼//////////////////////////////

void do_irq(void ) //C語言的中斷服務程序代碼,這段程序是程序員需要重點完成的

{

int irq_num;

irq_num = (CPU0.ICCIAR & 0x1FF);

switch (irq_num) {

case 58: //turn on LED2; turn off LED3

GPX2.GPX2DAT = 0x1 << 7;

GPX1.GPX1DAT &= ~0x1;

printf("IRQ interrupt !! turn on LED2; turn off LED3\n");

//Clear Pend

EXT_INT41_PEND |= 0x1 << 2;

ICDICPR.ICDICPR1 |= 0x1 << 26;

break;

}

// End of interrupt

CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;

}

int main(void)

{

//.....

}

三 中斷處理

Arm, Cortex A9是4核處理器

1 讀懂寄存器

Cortex A9采用的是ARM官方規定的中斷處理機制

有兩大類寄存器決定了中斷工作狀態

1) exynos 4412 特有的寄存器(在第26章)

2) Cortex A9 規定的工作寄存器(在第9章和第10章)


2 中斷服務程序注意事項

1)  沒有參數,沒有返回值

2)  執行時間要短

delay(1000); //延時1秒

3)  中斷服務程序中變量要少

4)  中斷服務程序要考慮重入的問題

中斷源:

外部中斷EINT(按鍵...)

定時器TIMER2

串口接收數據

網卡接收數據

3 GIC控制器初始化, ARM提供(Generic Interrupt Controller)

////////4412 的中斷控制器部分,采用了ARM公司的GIC中斷控制器架構

GIC中斷共152個, 分為三部分

SGI   16個    Software Generated Interrupt (SGI)

PPI   8個     Private Peripheral Interrupt (PPI)

SPI   128     Shared Peripheral Interrupt (SPI)   外部中斷  定時器中斷  串口中斷

每個中斷都被編了一個ID

可以根據GIC Interrupt Table 來查找

exynos4412 已經連接了兩個外部中斷(EINT)

 中斷源     SPI Port No      ID

EINT[9]      25              57

練習:查找EINT9,EINT10,  TIMER0 和 WDT的中斷源編號

 中斷源     SPI Port No      ID

EINT[9]      25              57    K2

EINT[10]      26              58        K3

TIMER0      37              69

WDT          43              75

GIC 設置流程:

1 設置GIC中的某個SPI 中斷允許還是禁止

////////////////

ICDISER(n)   ICDISER1,  ICDISER2, ICDISER3, ICDISER4

SPI中斷共128個,分成了4組

ICDISER1  ---- > 控制 0-31 (第1組) (控制此中斷編號是否可以產生中斷 1 允許,0 禁止)

ICDISER2  ---- > 控制 32-63 (第2組)

ICDISER3  ---- > 控制 64-95 (第3組)

ICDISER4  ---- > 控制 96-127 (第4組)

EINT9  ---- 25號    EINT10 ---- 26號    

ICDISER1 (GIC的通道號0-31)    如果某一位為1 那么中斷允許 

允許EINT9 產生中斷  

ICDISER.ICDISER1 |= (0x1 << 25);            //中斷使能寄存器

允許INT10 產生中斷  

ICDISER.ICDISER1 |= (0x1 << 26);            //中斷使能寄存器

練習:

允許WDT產生中斷(43)

ICDISER.ICDISER2 |= 0x1 << 11;   (43 % 32)

2 設置 某個CPU是否允許響應中斷(默認情況,4個CPU都不響應中斷)

ICCICR:  對應于每個CPU,都有一個ICCICR,他的功能是   控制這個CPU的總的中斷開關,1表示這個CPU響應中斷, 0表示不響應中斷

CPU0.ICCICR = 0x1;   (把它值1,表明CPU0響應中斷) 

3 設置 某個CPU響應的中斷的最高優先級

CPU0.ICCPMR = 0xFF;    //上面允許了中斷,ICCPMR中斷優先級小于設置值的中斷允許進入  0xFF最低

4 設置 ICDDCR  GIC控制寄存器,控制GIC是否工作,也就是是否響應中斷

ICDDCR 

ICDDCR = 1;   //總的中斷允許位

中斷產生時的中斷標志位, 具體中斷標志在哪參照ICDICPR

ICDICPR1   每組32位,對應相應的中斷,如果產生了中斷,那么ICDICPR相應位為0

ICDICPR2

ICDICPR3

ICDICPR4

5 設置某個中斷是由哪個CPU來響應(815頁)

ICDIPTR0(0-7, 8-15, 16-23, 24-31) ,  四組代表4個中斷源,設置某個中斷源由哪個CPU來處理

假設中斷源0, 由CPU1來處理

ICDIPTR0 = 0x00 00 00 02

假設中斷源1, 由CPU2來處理

ICDIPTR0 = 0x00 00 04 00 //0x04 ---> 0000 0100

ICDIPTR  有很多組:4個中斷為1組(中斷ID號最大159,   160 / 4  = 40,   ICDIPTR  有40個編號從0-39   )

如果設置EINT9由CPU0來響應(EINT9 是57號,所以在編號14的寄存器中(56, 57, 58, 59))

ICDIPTR.ICDIPTR14 = 0x00000100; //表示總中斷號為   57的中斷由CPU0來處理

如果設置EINT9由CPU1來響應

ICDIPTR.ICDIPTR14 = 0x00000200; //表示總中斷號為   57的中斷由CPU1來處理

如果設置EINT9由CPU2來響應

ICDIPTR.ICDIPTR14 = 0x00000400; //表示總中斷號為   57的中斷由CPU2來處理

如果設置EINT9由CPU3來響應

ICDIPTR.ICDIPTR14 = 0x00000800; //表示總中斷號為   57的中斷由CPU3來處理

如果設置EINT9由CPU4來響應

ICDIPTR.ICDIPTR14 = 0x00001000; //表示總中斷號為   57的中斷由CPU4來處理

//上面的寄存器設置我的中斷由哪個CPU來處理

ICDIPTR 有很多(設置某個中斷由哪個CPU來執行)

ICDIPTR1  ICDIPTR1 ICDIPTR2  ICDIPTR3 ICDIPTR4  ICDIPTR5........

有 160 / 4 個,  共40個, 每個寄存器控制4個中斷

每個寄存器是32位的,8位為1組,     每組代表某種中斷由哪個CPU來執行

0000 0001  表示由 CPU0來處理

0000 0010  表示由 CPU1來處理

0000 0100  表示由 CPU2來處理

0000 1000  表示由 CPU3來處理

0001 0000  表示由 CPU4來處理

0010 0000  表示由 CPU5來處理

0100 0000  表示由 CPU6來處理

1000 0000  表示由 CPU7來處理

一個32位寄存器可以分四組

ICDIPTR.ICDIPTR14 = 0x01010101;   //編號56,57,58,59四個中斷,由CPU0來處理

14  是 總的中斷編號 / 4

練習1:設置EINT10 由CPU1 響應(58)   ICDIPTR.ICDIPTR14 = 0x00020000;

練習2:設置WDT 由CPU0 響應(75)     ICDIPTR.ICDIPTR18 = 0x01000000;

如果設置EINT9 (57) 中斷優先級10

ICDIPR14 = 0x00000A00;

定時中斷

練習:

   完成定時功能, LED2 往復 亮,滅, 時間間隔兩秒鐘(精確延時),

如果實現WDT中斷程序

1 工程中添加start.S文件(中斷相應的過程, 是一段匯編代碼)

2 修改Makefile(當前的可以不改)

3 start.lds (也可以不改)

4 start.c改成main.c

#include <exynos_4412.h>

/**********************************************************************

 * @brief IRQ Interrupt Service Routine program body

 * @param[in] None

 * @return None

 **********************************************************************/

int flag = 0;

void do_irq(void)

{

int irq_num;

irq_num = (CPU0.ICCIAR & 0x3FF); //獲取中斷編號  0000 0000 0011 1111 1111

printf("\n ******* WDT  interrupt !!********  irqno %d\n", irq_num); //75

if(flag == 0)

{

//點亮

flag = 1;

}

else

{

//點滅

flag = 0;

}

//換成點亮或點滅LED3    GPX1_0

WDT.WTCLRINT = 1; //清exynos4412中斷標志位

// End of interrupt

CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x3FF)) | irq_num; //向GIC控制器通知,此中斷已經處理完

}

void wdt_init()

{

WDT.WTCNT = 6000; //initial value  ,, 延時大概有兩秒

WDT.WTDAT = 6000; //initial value  ,, 延時大概有兩秒

WDT.WTCON = 0xff<<8 | 1<<5 | 3<<3 | 1<<2 ;

}

void mydelay_ms(int time)

{

int i, j;

while(time--)

{

for (i = 0; i < 5; i++)

for (j = 0; j < 514; j++);

}

}

int main(void)

{

/*

* GIC interrupt controller:

* */

// Enables the corresponding interrupt SPI43, WDT

ICDISER.ICDISER2 |= 1<<11;  //ICDISER2:spi 32[bit0] ~ 63[bit31], 43 - 32 = [bit11]

CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts

CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold

ICDDCR = 1; //Bit1:  GIC monitors the peripheral interrupt signals and

// forwards pending interrupts to the CPU interfaces2

//ICDIPTR18:SPI40~SPI43; SPI43  interrupts are sent to processor 0

ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xFF<<24)) | 1<<24;

wdt_init();

printf("\n****************WDT Interrupt test!!***************\n");

while(1)

{

mydelay_ms(200);

mydelay_ms(200);

printf("working...\n");

}

return 0;

}

上一篇:STM32之外設DMA

下一篇:單鏈表

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 精品va久久久噜噜久久软件 | 成午夜免费视频在线观看 | 妺妺窝人体色WWW聚色窝仙踪 | 中国裸体BBBBXXXX | 蜜臀久久99精品久久久画质超高清 | 老司机亚洲精品影院无码 | 国产一级影院 | 亚洲AV永久无码AV激情A片 | 办公室啪啪激烈高潮动态图 | 久久青青草原国产精品最新片 | 色综合色天天久久婷婷基地 | 蜜臀98精品国产免费观看 | 亚洲伊人久久精品酒店 | 日日噜噜噜夜夜爽爽狠狠片 | 亚洲日韩精品无码专区加勒比 | 免费两性的视频网站 | 精品国产综合成人亚洲区2022 | 国产极品美女高潮无套在线观看 | 日本乱偷人妻中文字幕 | 天天综合网久久综合免费人成 | 女人高潮特级毛片 | 精品无人乱码一区二区三区的优势 | 亚洲成AV人片在线观看天堂无 | 亚洲AV无码国产一区二区三区 | 欧美国产激情一区二区在线 | 亚洲国产成人精品无码区在线秒播 | 日日夜夜免费精品视频 | 麻豆tv在线观看入口 | 四虎在线观看 | 黄的网站在线观看 | 韩国精品福利一区二区三区 | 特级小箩利无码毛片 | 精品无码国产污污污免费网站国产 | 农村熟女大胆露脸自拍 | 亚洲av无码片在线播放 | 国产毛片一区二区精品 | 色六月婷婷亚洲婷婷六月 | 夜夜爽一区二区三区精品 | 国产精一品亚洲二区在线播放 | 精品国产一区二区三区AV傅贞怡 | 久久综合九色综合97婷婷 |