首页 > 学院 > 开发设计 > 正文

ARM:ARM中断异常的处理流程

2019-11-08 02:12:43
字体:
来源:转载
供稿:网友
裸板开发中,使用的就是现在的框架:………………………………………………………………    main (void) {        // 一系列的初始化        while (1) {            // 周期性的事物        }    }             ↓+↓          异常处理  (异步事件的处理)………………………………………………………………1、异常如何触发     用按键触发异常,触发IRQ / FIQ类型的异常。 1.1 电路原理图 // x6818bv2【底板】.pdf    当SW6对应的按键 - 断开,导线GPIOA28 - 高电平。    当SW6对应的按键 - 闭合,导线GPIOA28 - 低电平。    导线GPIOA28 → 连接到了 → CPU的GPIOA28的管脚。1.2 对GPIOA28管脚进行配置 - (市长)    配置后GPIOA28管脚上的变化才会被视为IRQ / FIQ异常    异常上报给ARM core    GPIOA28'管脚上出现一个下降沿时触发中断'信号--->P66. // 确认I/O输出    GPIOA28 - I/O: Function0---> P759. // 配置:输出功能 function0    GPIOA_ALTFN1 - 0xc001a024 - [25:24] 00=ALT Function0---> P745. // 配置:输入模式 mode    GPIOA_OUTENB - 0xc001a004 - [ 28 ] 0=Input Mode---> P752. // 配置:检测模式 (1+2=3bit)    GPIOA_DETMODE1 - 0xc001a00c - [25:24] 2-bit 10=Falling Edge    GPIOA_DETMODEEX - 0xc001a028 - [ 28 ] 1-bit 0=Falling Edge        010 : 检测下降沿,检测到下降沿信号产生中断异常---> P770. // 配置:检测使能    GPIOA_DETENB - 0xc001a03c - [ 28 ] 1=Enable---> P756. // 配置:中断源级使能    GPIOA_INTENB - 0xc001a010 - [ 28 ] 1/0=Enable/Disable---> P756. // 配置:检测状态显示    GPIOA_DET - 0xc001a014 - [ 28 ] read: 0/1=未/检测到配置的信号                                                     write: 1=清除对应的检测bit位【对应的代码】    key_irq.c        void key_irq_init (void) {...}        该函数在main.c中被调用,效果是当按键按下时产生一个中断信号
/** 代码演示  - key_irq.c **/void do_gpioa_irq(void) {    uart_puts("/n/r do_gpioa_irq /n/r");    GPIOA_DET |= (1<<28);}void key_irq_init(void) {    GPIOA_INTENB &= ~(1<<28);  // 先做中断源级屏蔽    //GPIO 配置    //  1、GPIO配置为输入    //  2、禁止内部上、下拉电阻    //  3、GPIO检测使能    //  4、GPIO检测下降沿事件    //  5、GPIO中断使能    //  FUNC 0      //  输入口,禁止内部上下拉电阻    GPIOA_ALTFN1 &= ~(3<<(24));    GPIOA_OUTEN &= ~(1<<28);    //清除检测标志位    GPIOA_DET |= (1<<28);    //检测下降沿事件,使能检测    GPIOA_DETMODE1 = (GPIOA_DETMODE1 & ~(3<<24)) | (2<<24);    GPIOA_DETMODEEX &=  ~(1<<28);    GPIOA_DETENB |= (1<<28);    GPIOA_INTENB |= (1<<28); // 最后中断源级使能}/** ------------------------------------------------------ **/1.3 中断控制器 GIC - (省长)【特点】     1)中断源可以配置为group0或者group1;     2)group0中的中断可以配置为IRQ/FIQ的形式向目标处理器报告;     3)grout1中的中断只能以IRQ的形式向目标处理器报告;【支持4种类型的中断】     SGI * 16 :软件产生的中断信号,cpu和cpu之间的通信。     PPI * 6 :私有外围设备中断     PPI * 1 :私有内部设备中断     SPI * 128 :'共享的外部设备中断(按键就属于SPI)【中断状态】    inactive:非中断未决和中断进行。    pending:中断未决。中断已产生,等待cpu处理阶段。    active:中断进行。中断已产生,并正在执行相应的中断服务过程中。【中断被处理的模式】    1-N model    /    N-N model【中断优先级】了解【中断编号】interrupt IDs    ID0~ID15:SGI    ID16~ID31:PPI    ID32~ID1019:SPI   // 按键可用的编号在此范围内【中断源】---> P472.    GPIOA中断对应的interrupt ID是 32 + 53 == 85【关于特殊功能寄存器的设置,分两部分】    distributor<分配器> + CPU interface<接口> = '中断控制器(GIC)'    1)以GICD_xxxx开头的寄存器,对distributor配置;    2)以GICC_xxxx开头的寄存器,对CPU interface配置。" GICD_CTRL    // 归为group的中断信号是否可向interface    GICD_CTRL - 0xc0009000 - [ 0 ] 0=屏蔽,1=使能    " GICD_IGROUPR    // 决定中断归为group0还是group1    GICD_IGROUPR2 - 0xc0009088 - [ 21 ] 0=group0" GICD_ITARGETSR21    //配置中断产生后分配给那个核(cpu0,cou1...)           GICD_ITARGETSR21          配置中断产生后分发给哪个核(cpu0 cpu1 ...cpu7)          [15:8] 00000001 ID=85的中断发送到CPU0       GICD_ipRORITYR21          [15:8] 0x0a ID=85的中断优先级为10       GICD_ICPENDERR2          READ:             1, 中断产生了未得到处理 PENDING (未决/挂起)          WRITE,             1  导致对应的bit 清0          GPIOA ID = 85             [21] 向其中写入1,将其清0       GICD_ISENABLER2            [21] 0/1 屏蔽/使能 ID=85的中断信号           GICC_CTRL          [0], 0/1 禁止/使能上报group0组的中断信号给CPUn          [1], 0/1 禁止/使能上报group1组的中断信号给CPUn          [3], 0/1 group0的中断按照IRQ/FIQ方式上报      GICC_PMR               中断优先级阈值设置               优先级高于阈值的中断信号才有可能上报给CPU          [7:0]           【对应的代码】interrupt.c      int interrupt_init (void){ }      该函数在main.c1.4 ARM core设置       CPSR            [I] 0,响应上报的IRQ信号               1,屏蔽上报的IRQ信号                     start.s          enable_interrupts

      该函数在main.c中被调用   

 

2、异常的处理流程   增加start.s      而且调整shell.lds      IRQ异常产生,硬件会自动做4件事      1)备份CPSR 到spsr_<irq>      2) 修改CPSR         [4:0] 10010         [5]  T=0         [6]  F=1         [7]  I=1      3) 保存返回地址到LR_<irq>         LR_<irq> = PC -4       4) 给PC寄存器赋值         PC = vector_base + 0x18            = 0x48000000 + 0x18   start.s      1)异常向量表        b reset        ldr ...        ldr ...      2)reset:        重新设置异常向量表首地址        栈空间设置        bl main ( ) {               中断源 中断控制 arm初始化 //按键就出异常并且异常可以传递ARM CORE                              while(1) {               }           }   当有人按下key1键 ,IRQ异常报告给ARM CORE   ARM CORE      1)备份cpsr      2)修改CPSR      3)保存返回地址到LR      4)PC = 0X48000018   软件代码执行       ldr   pc, _irq       irq:          保护现场  stmfd sp!, {r0-r12, lr}           执行按键处理动作 bl do_irq           恢复现场 ldmfd sp!, {r0-r12, r15}^                       r15= lr                       ^: cpsr = spsr_<irq>       do_irq()       {          /*确认哪个触发的IRQ*/          GPIOA28 interrupt id = 85          判断是否为GPIOA28触发的中断?          {              do_gpioa_irq()              {                 /*重要的事:清除中断源的中断标志位*/              }              清除gpioa28在中断控制器中的pending位          }       }练习:    梳理按键异常是如何产生的?流程    异常的软硬件响应过程?    能不能向其中再增加一个按键?
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表