现在的位置: 首页 > 操作系统 > 正文

exynos4412中断编程

2020年02月13日 操作系统 ⁄ 共 3209字 ⁄ 字号 评论关闭

中断概述

我们知道,ARM核能处理的异常有7种,但仅仅区分异常的种类显然不能够满足需求。拿手机来说,触摸屏幕和按下音量键可能都是irq异常,但是ARM并不能将他们区分开,而事实的情况是针对这两种中断,我们的处理方式显然不同,为此就需要在Soc中集成中断控制器(Generic Interupt Controller),它的核心功能就是进行中断的调度和管理。

SGI VS PPI VS SPI

exynos4412中每种中断都有自己的ID用以标识,exynos4412支持三类中断:Software Generated Interrupt (SGI),Private Peripheral Interrupt (PPI)和Shared Peripheral Interrupt (SPI)。所有的中断可以按照优先级可以划分为0~255级,和大多数芯片一样,数字越小,中断的优先级越高,同时发生的时候优先级更高的中断会被优先处理,当然,Soc对每个中断都有一个默认的优先级。

SGI表示软件生成中断,即上图中CPU和GIC通过一个寄存器进行交互,让GIC给CPU(们)发送一个中断(和ARM汇编中的swi不是一回事!)这个过程并没有真正的外设来触发中断。SGI中断具有边沿触发的属性,在多核Soc中,一个CPU可以通过触发SGI的方式和其他CPU交互。交互的形式有两种:1-N,N-N。前者表示只有一个CPU响应这个SGI,此时需要提供机制来确定到底的哪个CPU接收并响应这个SGI。后者表示所有的CPU都将接收到SGI,当一个CPU收到这个SGI之后,这个SGI在这个CPU的pending状态就被清除了,但是在其他CPU的pending状态还会继续维持。exynos4412支持最多16个SGI

PPI表示该中断只会送给某一个CPU来处理,这是一个外设中断,有边沿触发和平台触发两种触发方式。exynos4412支持最多8个PPI中断

SPI和PPI一样是外设中断,不同的是这个中断可以被GIC调度给任何CPU来处理。exynos4412支持最多128个SPI中断

中断的状态

GIC负责维护每个中断的状态标志,exynos4412的中断有四个状态:inactive,pending,active,active and pending。

Inactive即该中断既不是pending状态也不是active状态。

Pending表示一个从中断源传送到GIC的外设中断或者一个SIG中断正在等待被GIC传送到目标CPU.

Active表示一个中断正在被CPU 响应。

Active and Pending表示CPU正在响应一个中断,而GIC还用一个来自同一个中断源的中断在排队.

编程模型

源码参考上面的中断响应结构图,为了响应一个中断,首先应该在外设层进行设置,诸如中断触发条件,中断连接管脚等,然后需要在GIC层次进行设置,比如中断的调度方法,最后在CPU层次进行设置,比如哪些中断可以进入CPU,哪些不行。

编程使用的原理图如下,程序的目的是按下一个按键,就有一个相应的LED闪烁一下。需要参考的资料有原理图、exynos4412芯片手册:

#include "exynos_4412.h"#include "debug.h"#define LED_ON_TIMER 0xfffffvoid delay(unsigned int x){ unsigned int timer=x; while(timer--);}/* 57号中断(即EINT[9],按键K2,参考原理图和芯片手册中断号表)的中断处理*/void irq57_handler(void){ deprint("irq57\n"); GPX1.CON=GPX1.CON&(~(0xf<<0))|(0x1<<0); //配置LED3的相应管脚(GPX1_1)为输出 GPX1.DAT|=(0x1<<0); //GPX1_1输出高电平 delay(LED_ON_TIMER); //延时 GPX1.DAT&=~(0x1<<0); //GPX1_1输出低电平}void irq58_handler(void){ deprint("irq58\n"); GPF3.CON=GPX2.CON&(~(0xf)<<16)|(0x1<<16); GPF3.DAT|=(0x1<<4); delay(LED_ON_TIMER); GPF3.DAT&=~(0x1<<4);}void do_irq(void){ //irq入口函数 //ICCIAR的低10位是当前触发的中断号 volatile unsigned int IRQ_ID=CPU0.ICCIAR & 0x3ff; switch (IRQ_ID){ case 57: irq57_handler(); //处理完中断应该将相应的中断标志清除, //否则GIC会认为中断没有响应,继续给CPU发送这个中断 // EXT_INT41_PEND=EXT_INT41_PEND|(0x1<<1); // BUG!!!,写一置零,如果低位本来是1,会将其一起清零!!! EXT_INT41_PEND=0x2; break; case 58: irq58_handler(); EXT_INT41_PEND=0x4; break; default: break; } deprint("switch over\n"); //将中断号告诉GIC,表示中断处理完毕,可以将下一个pending的中断送入 CPU0.ICCEOIR = CPU0.ICCEOIR & (~(0x3ff))|IRQ_ID; }int main(){ //外设配置 //1. 将GPX1_1 GPX1_2 设置为中断功能GPX1CON GPX1.CON=GPX1.CON|(0xff<<4); detobin(GPX1.CON); //2. 设置GPX1_1 GPX1_2的触发方式为下降沿触发 EXT_INT41_CON=EXT_INT41_CON|(0x22); detobin(EXT_INT41_CON); //3. 使能GPX1_1 GPX1_2中断 EXT_INT41_MASK=EXT_INT41_MASK&(~(0x3<<1)); detobin(EXT_INT41_MASK); //GIC配置 //4. 全局使能GIC使其可以监控外设的中断信号并转发到CPU接口 ICDDCR=1; detobin(ICDDCR); //5. 在中断管理器中使能57,58号中断,ICDISER1[25] ICDISER.ICDISER1=ICDISER.ICDISER1|(0x3<<25); detobin(ICDISER.ICDISER1); //6. 给57 58号中断选择一个目标CPU。这里选CPU0 ICDIPTR14[23:16][15:8] ICDIPTR.ICDIPTR14=ICDIPTR.ICDIPTR14|(0x1<<16)|(0x1<<8); detobin(ICDIPTR.ICDIPTR14); //CPU配置 //7. 使能全局中断信号开关,使中断能够通过相应接口到达处理器,这里是CPU0 CPU0.ICCICR=1; detobin(CPU0.ICCICR); //8. 优先级低于ICCPMR的中断才能被送入cpu, //这里使所有的中断都能够经过CPU0接口到达处理器,给255。 CPU0.ICCPMR=0xff; detobin(CPU0.ICCPMR); while(1); return 0;}

本文永久更新链接地址:http://www.xuebuyuan.com/Linux/2016-11/137531.htm

以上就上有关exynos4412中断编程的相关介绍,要了解更多exynos4412中断,exynos4412,exynos4412中断编程,编程,Linux编程,Linux Shell,Android,Android教程,JAVA,C语言,Python,HTML5内容请登录学步园。

【上篇】
【下篇】

抱歉!评论已关闭.