以KEY2控制LED3亮灭为例:

一、轮询方式

【0】检测按键k2,按键k2按下一次,灯LED2闪一次。

【1】查看原理图,连接引脚和控制逻辑
(1)按键k2 连接在GPX1_1引脚
(2)控制逻辑
       k2 按下  ---- K2闭合 ---- GPX1_1 低电压
       k2 常态  ---- K2打开 ---- GPX1_1 高电压

【2】查看相应的芯片手册

【2-1】循环检测GPX1_1引脚输入的电平,为低电压时,按键按下

(1)配置GPX1_1引脚功能为输入,设置内部上拉下拉禁止。
                  GPX1.CON = GPX1.CON &(~(0xf<<4)) ;

GPX1.PUD = GPX1.PUD & ~(0x3 << 2);
  (2)循环检测:

[cpp] view plaincopy
  1. while(1)
  2. {
  3. if(!(GPX1.DAT & (0x1<<1)))  // 返回为真,按键按下
  4. {
  5. msdelay(10);
  6. if(!(GPX1.DAT & (0x1<<1))) //二次检测,去抖
  7. {
  8. GPX2.DAT |= 0x1 << 7;  //Turn on LED2
  9. mydelay_ms(500);
  10. GPX2.DAT &= ~(0x1<<7);  //Turn off LED2
  11. mydelay_ms(500);
  12. while(!(GPX1.DAT & (0x1<<1)));
  13. }
  14. }
  15. }

这种轮询方式始终占着CPU,不利于操作。

二、中断方式

将K2按下时,GPX1_1引脚获得的电平,作为异常事件。使能异常处理,k2每按下一次,响应一次异常处理。SPI 传递流程如下示:

注:

Exynos4412中断控制器包括160个中断控制源,这些中断源来自软中断(SGI),私有外部中断(PPI),公共外部中断(SPI)。

      Exynos4412采用GIC中断控制器,主要是因为Contex-A9 是多核处理器,GIC(Generic Interrupt Controller)通用中断控制器用来选择使用哪个CPU接口,具体主要有两个功能:

1)分配器:设置一个开关,是否接收外部中断源;为该中断源选择CPU接口;

2)CPU接口:设置一个开发,是否接受该中断源请求;

具体实现如下:

1、外设一级 ---设置 GPIO控制器

1-- 将GPX1_1引脚的上拉和下拉禁止

GPX1PUD[3:2]= 0b00;

2 -- 将GPX1_1引脚功能设置为中断功能 WAKEUP_INT1[1] --- EXT_INT41[1]

GPX1CON[7:4] = 0xf

3 -- EXT_INT41CON  配置触发电平

当前配置成下降沿触发:

EXT_INT41CON[6:4] = 0x2

4 -- EXT_INT41_FLTCON0 配置中断引脚滤波

默认就是打开的,不需要配置

5 -- EXT_INT41_MASK 中断使能寄存器

      使能INT41[1]

EXT_INT41_MASK[1] = 0b0

6 -- EXT_INT41_PEND 中断状态寄存器
       当GPX1_1引脚接收到中断信号,中断发生,中断状态寄存器EXT_INT41_PEND 相应位会自动置1
        注意:中断处理完成的时候,需要清除相应状态位。置1清0.
        EXT_INT41_PEND[1] =0b1

2、中断控制器

1-- 找到外设中断名称和GIC中断控制器对应的名称

 查看芯片手册(本例:Exynos_4412 -- 9.2表)
       WAKEUP_INT1[1] --- EXT_INT41[1] --- INT[9] --- SPI[25]/ID[57]

对应INT[9],中断ID为57,这是非常重要的,在后面的寄存器设置中起很大作用;

下面是外设与中断控制器处理具体流程:

2 -- GIC使能

ICDDCR =1;

使能分配器。

3 -- 使能相应中断到分配器

ICDISER.ICDISER1 |= (0x1 << 25);    //57/32 =1...25 取整数(那个寄存器) 和余数(哪位)

ICDISER用于使能相应中断到分配器,一个bit控制一个中断源,一个ICDISER可以控制32个中断源,这里INT[9] 对应的中断ID为57,所以在ICDSER1中进行设置,57/32 =1余25,所以这里在ICDISER1第25位置一。

4 -- 选择CPU接口

设置SPI[25]/ID[57]由那个cpu处理,当前设置为cpu0的irq中断

ICDIPTR.ICDIPTR14 |= 0x01<<8; //SPI25  interrupts are sent to processor 0   //57/4 = 14..1 14号寄存器的[15:8]

ICDIPTR寄存器每8个bit 控制一个中断源

5 -- 全局使能cpu0中断处理

       CPU0.ICCICR |= 0x1;

使能中断到CPU。

6 -- 优先级屏蔽寄存器,设置cpu0能处理所有的中断。

CPU0.ICCPMR = 0xFF;

                          

3、ARM内核(cpu0)

前面两步设置好,就可以等待中断的发生了,当中断发生时,ARM内核的处理过程如下:

 1-- 四大步三小步 --- 硬件

    

(1)拷贝 CPSR 到 SPSR_<mode>
  (2)设置适当的 CPSR 位:                                
    (2-1)--改变处理器状态进入 ARM 态
       (2-2)--改变处理器模式进入相应的异常模式
       (2-3)--设置中断禁止位禁止相应中断 (如果需要)
  (3)保存返回地址到 LR_<mode>
  (4)设置 PC 为相应的异常向量
          

2 -- 中断服务程序 --- start.S 汇编

[cpp] view plaincopy
  1. .text
  2. .global _start
  3. _start:
  4. b       reset
  5. ldr     pc,_undefined_instruction
  6. ldr     pc,_software_interrupt
  7. ldr     pc,_prefetch_abort
  8. ldr     pc,_data_abort
  9. ldr     pc,_not_used
  10. ldr     pc,_irq
  11. ldr     pc,_fiq
  12. _undefined_instruction: .word  _undefined_instruction
  13. _software_interrupt:    .word  _software_interrupt
  14. _prefetch_abort:        .word  _prefetch_abort
  15. _data_abort:            .word  _data_abort
  16. _not_used:              .word  _not_used
  17. _irq:                   .word  irq_handler
  18. _fiq:                   .word  _fiq
  19. reset:
  20. ldr r0,=0x40008000
  21. mcr p15,0,r0,c12,c0,0       @ Vector Base Address Register
  22. init_stack:
  23. ldr     r0,stacktop         /*get stack top pointer*/
  24. /********svc mode stack********/
  25. mov     sp,r0
  26. sub     r0,#128*4          /*512 byte  for irq mode of stack*/
  27. /****irq mode stack**/
  28. msr     cpsr,#0xd2
  29. mov     sp,r0
  30. sub     r0,#128*4          /*512 byte  for irq mode of stack*/
  31. /***fiq mode stack***/
  32. msr     cpsr,#0xd1
  33. mov     sp,r0
  34. sub     r0,#0
  35. /***abort mode stack***/
  36. msr     cpsr,#0xd7
  37. mov     sp,r0
  38. sub     r0,#0
  39. /***undefine mode stack***/
  40. msr     cpsr,#0xdb
  41. mov     sp,r0
  42. sub     r0,#0
  43. /*** sys mode and usr mode stack ***/
  44. msr     cpsr,#0x10
  45. mov     sp,r0             /*1024 byte  for user mode of stack*/
  46. b       main
  47. .align  4
  48. /****  swi_interrupt handler  ****/
  49. /****  irq_handler  ****/
  50. irq_handler:
  51. sub  lr,lr,#4
  52. stmfd sp!,{r0-r12,lr}
  53. .weak do_irq
  54. bl  do_irq
  55. ldmfd sp!,{r0-r12,pc}^
  56. stacktop:    .word      stack+4*512
  57. .data
  58. stack:   .space  4*512

3--中断处理程序 --- do_irq函数 C语言(函数原型void name(void))

(1) 读取正在处理的中断ID寄存器(ICCIAR)

irq_num = (CPU0.ICCIAR & 0x1FF);

(2)根据irq_num,分支处理中断

[cpp] view plaincopy
  1. switch(irq_num)
  2. {
  3. .
  4. case 57:
  5. break;
  6. ....
  7. }

 (3)清除中断状态位

(3-1)i.外设级,EXT_INT41_PEND |= 0x1 << 1;
        (3-2)ii.GIC级,ICDICPR.ICDICPR1 |= 0x1 << 25;
        (3-3)iii.CPU0级 CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;

下面是C 程序:

[cpp] view plaincopy
  1. #include "exynos_4412.h"
  2. #include "led.h"
  3. void  delay_ms(unsigned int num)
  4. {
  5. int i,j;
  6. for(i=num; i>0;i--)
  7. for(j=1000;j>0;j--)
  8. ;
  9. }
  10. void do_irq(void)
  11. {
  12. static int a = 1;
  13. int irq_num;
  14. irq_num = CPU0.ICCIAR&0x3ff;  //获取中断号
  15. switch(irq_num)
  16. {
  17. case 57:
  18. printf("in the irq_handler\n");
  19. if(a)
  20. led_on(1);
  21. else
  22. led_off(1);
  23. a = !a;
  24. EXT_INT41_PEND = EXT_INT41_PEND |((0x1 << 1)); //清GPIO中断标志位
  25. ICDICPR.ICDICPR1 = ICDICPR.ICDICPR1 | (0x1 << 25); //清GIC中断标志位
  26. break;
  27. }
  28. CPU0.ICCEOIR = CPU0.ICCEOIR&(~(0x3ff))|irq_num; //清cpu中断标志位
  29. }
  30. /*
  31. *  裸机代码,不同于LINUX 应用层, 一定加循环控制
  32. */
  33. int main (void)
  34. {
  35. GPX1.CON =GPX1.CON & (~(0xf << 4)) |(0xf << 4); //配置引脚功能为外部中断
  36. GPX1.PUD = GPX1.PUD & (~(0x3 << 2));  //关闭上下拉电阻
  37. EXT_INT41_CON = EXT_INT41_CON &(~(0xf << 4))|(0x2 << 4); //外部中断触发方式
  38. EXT_INT41_MASK = EXT_INT41_MASK & (~(0x1 << 1));  //使能中断
  39. ICDDCR = 1;  //使能分配器
  40. ICDISER.ICDISER1 = ICDISER.ICDISER1 | (0x1 << 25); //使能相应中断到分配器
  41. ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xff << 8))|(0x1 << 8); //选择CPU接口
  42. CPU0.ICCPMR = 255; //中断屏蔽优先级
  43. CPU0.ICCICR = 1;   //使能中断到CPU
  44. led_init();
  45. while(1)
  46. {
  47. }
  48. return 0;
  49. }

Exynos4412裸机开发——中断处理相关推荐

  1. Exynos4412 裸机开发—— 流水灯

    这里我们使用的开发板是4412,开发板4412上有4个LED灯,我们这里可以利用其来做流水灯实验.下面是4个LED的原理图: 查看原理图,4412开发板的LED由CPX2_7 CPX1_0 GPF3_ ...

  2. Exynos4412 裸机开发 —— IIC总线

    前言: I2C(Inter-Integrated Circuit)总线(也称 IIC 或 I2C) 是有PHILIPS公司开发的两线式串行总线,用于连接微控制器及外围设备,是微电子通信控制领域广泛采用 ...

  3. Exynos4412裸机开发 —— UART

    一.Exynos4412 UART 的特性 Exynos4412 中UART,有4 个独立的通道,每个通道都可以工作于中断模式或DMA 模式,即 UART 可以发出中断或 DMA 请求以便在UART ...

  4. Exynos4412裸机开发 —— A/D转换器

    一.Exynos4412 A/D转换器概述 1.简述 10位或12位CMOS再循环式模拟数字转换器,它具有10通道输入,并可将模拟量转换至10位或12位二进制数.5Mhz A/D 转换时钟时,最大1M ...

  5. Exynos4412裸机开发综合练习

    下面是一个案例需求: 1.编写一段程序,该程序的主要功能是监控电路板上的电压值,若电压值超过当前的电压限制则通过蜂鸣器报警,通过按键解除报警; 2.其具体要求如下; a) 程序下载20s后,进入电压采 ...

  6. Exynos4412裸机开发 —— RTC 实时时钟单元

    RTC(Real-Time Clock) 实时时钟.RTC是集成电路,通常称为时钟芯片.在一个嵌入式系统中,通常采用RTC来提供可靠的系统时间,包括时分秒和年月日等,而且要求在系统处于关机状态下它也能 ...

  7. 利用汇编和C语言实现Exynos4412裸机开发系列之实现LED跑马灯(含源码)

    一.前言 本篇使用华清远见的FS4412开发板,对开发板的LED进行操作,来实现流水灯的效果,知识包含GPIO寄存器介绍.与ubuntu下linux操作系统通过进行交叉编译生成开发板可执行代码,通过本 ...

  8. Exynos4412裸机开发 —— 看门狗定时器

    http://blog.csdn.net/zqixiao_09/article/details/50755286 转载于:https://www.cnblogs.com/tureno/articles ...

  9. 从51到ARM裸机开发实验(006)Exynos4412 GPIO实验

    本次实验基于Tiny4412开发板,开发板上有四个可编程控制的LED.四个按键.来实现这样一种场景:每个按键控制一盏LED,每按一次则对应的LED状态发生改变,按一次开灯,再按一次关灯.核心控制为三星 ...

最新文章

  1. WinCE项目应用之车载导航
  2. 在setInterval函数中传递参数
  3. AT4439-[AGC028E]High Elements【结论,线段树】
  4. html5贝塞尔,使用HTML5画布绘制贝塞尔曲线
  5. wxpython下载缓慢_我可以在wxPython的wx.grid.Grid中加速优化GridCellAttr的使用吗?
  6. Spring Boot——Redis安装配置与应用整合
  7. ddr4服务器内存和普通内存_国产DDR4内存上架,价格动心!
  8. 参加西安第三届数字油田高端论坛暨第二届国际学术会议
  9. 蓝桥杯c语言b组试题及答案,2014蓝桥杯C语言本科B组预赛试题
  10. CodeForces 711B. Chris and Magic Square(水题)
  11. HTML实现图片360度循环旋转
  12. 无法访问eclipse官网?镜像源可以帮你
  13. co作为前缀的意思_品牌故事之Tiffany Co
  14. 韩国区块链步入快车道:SM、Kakao、三星、LG等巨头ALL IN
  15. SaaS小读-客户成功
  16. ?软件测试mysql面试题:varchar(50)中50的涵义?
  17. Kafka,ActiveMQ,RabbitMQ等消息队列使用的场景介绍
  18. js之 实现下载图片保存到本地
  19. noiLinux中编程工具的使用
  20. Android绝对布局AbsoluteLayout

热门文章

  1. 怎样判断网页是静态还是伪静态呢
  2. oracle技术之查询初始化参数的方法(六)
  3. ESXI忘记密码怎么办?
  4. 女人必知:10个好习惯 让老公不想出轨
  5. java的classpath
  6. 双绞线施工质量的检测方法
  7. 单据打印_Excel多功能进销存套表,自动库存单据,查询打印一键操作
  8. leetcode1337. 方阵中战斗力最弱的 K 行(优先队列)
  9. refract推导_我们如何利用Refract来利用React式编程的力量
  10. RESTful服务的第三部分:HATEOAS和Richardson成熟度模型