第九天:按键及中断原理

来源:互联网 发布:境外网络电视直播apk 编辑:程序博客网 时间:2024/06/06 12:35
    1. 什么是按键?
      1. 按键的物理特性
        1. 一般的按键都有四个引脚,这四个引脚:其中一对是常开触点(不按则断,按下则合);一对是常闭触点(不按则闭,按下则断)

     

    1. 按键的电学原理
      1. 硬件接法:   SW5GPH0_2    SW6GPH0_3    SW78910GPH2_0123
      2. 按键的电路连接分析:平时按钮没有按下时,按钮内部断开,GPIO引脚处电压为高电平;当有人按下按钮时,按钮内部导通,外部VDD经过电阻和按钮连接到地,形成回路,此时GPIO引脚处电压就变成了低电平
    2. 按键属于输入类设备
      1. 按键一般用来做输入设备(由人向SoC发送信息的设备,叫做输入设备),由人向SoC发送按键信号(按键信号有2种:按下信号和弹开信号)

     

     

    轮训方式和中断方式

     

    SoC主动的每隔一段时间去读取GPIO的电平高低,以此获得按键信息

    中断方式,就是SoC实现设定好GPIO触发的中断多对应的中断所对应的中断处理程序ISR,当外部按下或弹开时会自动触发GPIO对应的外部中断,导致ISR执行,从而自动处理按键信息。

     

    1. 轮询方式处理按键
      1. X210开发板的按键接法
        1. 查原理图,找到按键对应的GPIO
        2. 原理图上可以看出按键在按下时是低电平,弹起时是高电平
      1. 按键对应的GPIO模式设置
        1. 按键接到GPIO上,按键按下还是弹起,决定外部电路的接通与否,从而决定了这个GPIO引脚的电压是高还是低
      2. 轮询方式处理按键的程序流程
        1. 先初始化GPIO模式为input
        2. 循环读取GPIO
    1. 串口输出和按键消抖
      1. 基于串口输出按键的调试
        1. 以之前的串口stdio的工程为基础来移植添加轮询方式按键处理
        2. 注意USB下载方式可能有错误(有可能不下载,也有可能下载了执行不对),执行方案是用SD卡启动来替代。
      1. 什么是按键消抖
        1. 按键这种物理器件本身会有抖动信号指的是在电平由高到低或者由低到高时的过程中,电平的变化不是立刻变化,而是经过了一段时间的不稳定期才完成变化。
      2. 硬件消抖,尽量减少抖动时间,通过硬件添加电容等元件来减少抖动
      3. 软件,屏蔽掉这段时间抖动在获取电平状态。

     

     

    1. S5PV210的中断体系介绍
      1. 什么是中断
        1. 中断的发明用来解决宏观上的并行需要的。宏观就是从整体来看,并行就是多件事情都完成了。
        2. 微观上的并行,就是指的真正的并行。就是精确到每一秒甚至每一刻,多个事情都是在同时进行的。宏观上的并行并不等于微观上的并行,有时候宏观上是并行的,微观上实际是串行的。

    计算机生成了可选文字:

    1. 我们例子中一个人在看电影,快递来了暂停电影跑去收快递,收完快递继续回来看电影,这个例子就是宏观上的并行和微观上的串行。例子中一个人等同于SoC中一个CPU(也就是单核CPU),这个CPU看电影就不能收快递,收快递就不能看电影(也就是不能真正的并行)。单核心CPU在微观角度是串行的,但是因为CPU很快,所以在宏观看来可以并行。
    2. 上例中大部分时间在看电影,中间少量时间去收快递,那么类比CPU来说,看电影就应该是CPU的常规任务,而收快递则应该是中断例程。也就是说CPU平时一直在进行砍电影任务,等快递来了(中断发生了)快递员(类似于中断源)会打电话叫人去收快递(中断源会触发中断通知CPU去处理中断),人收到电话(CPU收到中断源)后会暂定电影(CPU保存常规任务的现场)跑去收快递(CPU去执行中断处理程序ISR处理中断),收完快递(执行完ISR)回来继续看电影(CPU恢复常规任务的现场,继续执行常规任务)
    3. 为什么需要中断? 因为单核CPU实际无法并行的,但是通过终端机制,可以实现假并行(宏观上的并行,微观上实际还是串行的)。
    1. SoC对中断的实现机制:异常向量表
      1. 异常向量表是CPU中某些特定地址的特定定义。当中断发生的时候,中断要想办法通知CPU去处理中断,怎么做到?这就要靠异常向量表。
      2. CPU设计时,就事先定义了CPU中一些特定地址为特定异常的入口地址(譬如定义0x0000000地址为复位异常向量表地址,则发生复位异常时CPU会自动跳转到0x00000000地址去执行指令。又譬如外部中断对应的异常向量地址为0x30000008,则发生外部中断后,CPU会硬件自动跳转到0x30000008地址去执行指令。)如
      3. 以上讲的是CPU硬件设计时对异常向量表的支持,下来就需要软件支持了。硬件已经决定了发生什么异常CPU自动跳转PC到哪个地址去执行,软件需要做的就是把处理这个异常的代码的首地址填入这个异常向量地址。

     

    1. S5PV210异常向量表
      1. 异常向量表在之前讲过,复习一下
      2. 异常向量表中各个向量的相对位置是固定的,但是他们的起始地址是不固定的,各种SoC可以不一样,而且复杂ARM中可以让用户来软件设置异常向量表的基地址。
      3. 扩展到所有架构的CPU中:所有架构(譬如51单片机、PIC单片机)的CPU实现中断都是通过异常向量表实现的,这个机制是不变的;但是不同CPU异常向量表的构造和位置是不同的。
    2. 异常和中断的区别和联系。
      1. 针对SoC来说,发生复位、软中断、中断、快速中断、取指令异常、数据异常等,我们都统一叫异常。所以说中断其实是异常的一种。。
      2. 异常的定义就是突发事件,打断了CPU的正常常规业务,CPU不得不跳转到异常向量表中去执行异常处理程序;中断时异常的一种,一般特指SoC内的内部外设产生的打断SoC常规业务,或者外部中断(SoCGPIO引脚传回来的中断)
    1. 异常向量表的编程处理
      1. 像内存一样去访问异常向量表
        1. S5PV210的异常向量表可以改变(在CP15协处理器),以适应操作系统的需求。但是目前来说,系统刚启动时,此时DRAM尚未初始化,程序都在SRAM中运行。210iRAM中设置了异常向量表,供暂时使用。
        2. 210Irom application

    note文档中iROM的地址分配,可知,iRAM中的异常向量表其实地址为0xD0037400。知道了异常向量表的起始地址后,各个异常对应的入口就很好知道了。

    1. 函数名的实质就是函数的首地址
      1. 函数名在C语言中的理解方法和变量名其实没区别。编译器会把这个函数的函数体对应的代码段和这个函数的函数名(实质是符号)对应起来,等我们在使用这个函数名符号时,编译器会将函数的函数体实际上做替换。因为函数体都不止4字节,而函数名这个符号只能对应1个地址,所以实际对应的是函数体那一个代码段的首地址。
      2. C语言中的语法来讲,函数名就是这个函数的函数指针。

    总结:当我们将异常处理程序的首地址和异常向量表绑定之后,异常处理初步阶段就完成了

     

    1. 为什么中断处理要先在汇编中进行

    (1)中断处理要注意保护现场(中断从SVC模式来,则保存SVC模式下的必要寄存器的值)和恢复现场(中断处理完成后,准备返回SVC模式前,要将保存的SVC模式下的必要寄存器的值恢复回去,不然到了SVC模式后寄存器的值乱了,SVC模式下原来正在进行的常规任务就被你搞坏了)

    (2)保存现场包括:第一:设置IRQ栈;第二,保存LR;第三,保存R0~R12

    (3)为什么要保存LR寄存器?要考虑中断返回的问题。中断ISR执行完后如何返回SVC模式下去接着执行原来的代码。中断返回其实取决于我们进入中断时如何保存现场。中断返回时关键的2个寄存器就是PC和CPSR。所以我们在进入IRQ模式时,应该将SVC模式下的下一句指令的地址(中断返回地址)和CPSR保存起来,将来恢复时才可以将中断返回地址给PC,将保存的CPSR给CPSR。

    (4)中断返回地址就保存在LR中,而CPSR(自动)保存在(IRQ模式下的)SPSR中

     

    1. 汇编保存现场和恢复现场

    (1)保护现场关键是保存:中断处理程序的返回地址,r0-r12(cpsr是自动保存的)

    (2)恢复现场主要是恢复:r0-r12,pc,cpsr

     

    1. S5PV210的向量中断控制器
      1. 异常处理的两个阶段
        1. 可以将异常处理分为两个阶段。第一个阶段是异常向量表跳转;第二个阶段就是进入了真正的异常处理程序irq_handler之后的部分。
      2. 回顾:中断处理的第一阶段(异常向量表阶段)处理
        1. 第一个阶段之所以能够进行,主要依赖于CPU设计时提供的异常向量表机制。第一个阶段的只要任务是从异常发生响应异常并且保存/恢复现场
        2. 第二个阶段的目的是识别多个中断源中究竟哪一个发生了中断,然后调用相应的中断处理程序来处理这个中断。

     

    1. S3C2440的第二阶段处理过程
      1. 第一个问题,怎么找到具体是哪个中断:S3C2440的中断控制器中有一个寄存器(32位的),寄存器的每一个对应一个中断源(为了解决支持更多中断源,2440又设计了一个子中断机制。在一级中断寄存器中有一些中断是共用的一个bit位,譬如AC97WDT。对于共用中断,用子中断来区分究竟是哪一个发生了中断)
      1. 第二个问题,怎么找到对应的isr的问题:首先明确给每个中断做了个编号,进入isr_handler之后先通过查阅中断源寄存器和字中断源寄存器(中哪一位为1)确定中断的编号,然后用编号去isr数组(isr数组是中断初始化时事先设定好的,就是把各个中断的isr的函数名组成一个数组,用中断编号作为索引来查询这个数组)中查阅得到isr地址。

    评价:2440的中断处理设计不是特别优秀:第一个过程中使用子中断搞成2级的很麻烦;第二个过程中计算中中断编号是个麻烦事,很耗时间。而中断处理的时间是很宝贵的(系统有一个性能指标,叫实时性。实时性就是中断发生到相应的时间,这个时间越短越好)

    1. S5PV210的第二阶段处理过程
      1. 第一个问题,怎么找到具体是哪个中断:S5PV210中因为支持的中断源很多,所以直接设计了4个中断寄存器,每个32位,每位对应一个终端源。(理论支持210最多支持128个中断,实际支持不足128个,有些位是空的);210没有子中断寄存器每个中断源都是并列的。当有中断发生时,在irq_handler中依次查询4个中断源寄存器,看哪一个的哪一位被置1,则这个为对应的寄存器就发生了中断,即找到了中断编号。

     

    1. 第二个问题,怎么找到相应的isr的问题: 210提供另外很多寄存器来解决每个中断源对应isr的寻找问题,具体寻找过程和建立过程见下节,实现的效果是当发生相应中断时,硬件会自动的将相应isr推入一定的寄存器中,我们软件只要去这个寄存器中执行函数就行了

    总结:第一阶段都相同,第二阶段各不同

    1. 第一阶段(异常向量表阶段)2440 210几乎完全是相同的
    2. 第二阶段就彼此不同了。各个SoC根据自己对实时性的要求,和支持的中断源的多少,各自发明了各自处理中断,找到中断编号,进一步找到isr地址的方式。
    1. S5PV210中断处理的主要寄存器
      1. VICnINTENABLE VICNINTENCLEAR
        1. VICnINTENBLE对应 interrupt enble,   INTENCLEAR对应 interrupt enble clear
        2. VICnINTEABLE寄存器负责相应的中断的使能,VICnINTENCLEAR寄存器负责相应的中断的禁止。
        3. 当我们想使能(意思是启用这个中断,意思是当硬件产生中断时CPU能接收的到)某个中断时,只要在这个中断编号对应的VICnINTENBLE的相应bit位写1即可(注意这个为写 1其他位写0诶有影响);如果我们想禁止某个中断源时,只要向VICnINTENCLEAR中相应的位写1即可。

    注意:这里的设计一共有2种:有些CPU是中断使能和禁止是一个寄存器,写1就使能0就禁止(或者相反),这样的中断使能设计就要非常小心,要使用我们之前的读改写三部曲来操作;另一种就是使能和禁止分开位2个寄存器,要使能就写使能寄存器,要禁止就写禁止寄存器。这样的好处是我们使能/禁止操作时不需要读改写,直接写即可。

    1. VICnINSELECT
      1. 设置各个中断的模式为irq还是fiq.一般都设置成irq
      2. ORQ FIQ究竟有何区别。 210中支持2中中断,irq fiq . irq是普通中断,fiq是快速中断。快速中断提供一种更快响应处理的中断通道,用于对实时性要求很高的中断源。fiqCPU设计时预先提供了一些机制保证fiq可以被快速处理,从而保证实时性。fiq的限制就是只能有一个中断源被设置为fiq,其他都是irq
      3. CPU如何保证fiqirq快?
        1. 第一,fiq有专用的r8~r12,因此在fiqisr中可以直接使用r8~r12,而不用保存,这就能节省时间
        2. 第二,异常向量表中fiq是最后一个异常向量入口。因此fiqisr不需要跳转,可以直接写在原地,这样就比其他异常少跳转一次,省了些时间。
      4. VICnIRQSTATUS   VICnFIQSTATUS
        1. 中断状态寄存器,是只读的。当发生了中断时,硬件会自动将该寄存器的对应位置位1,表示中断发生了。软件在处理中断第二阶段的第一阶段,就是靠查询这个寄存器来得到中断编号的。
      5. VICnVECTPRIORITY0~VICnVECTPRIORITY31
        1. 中断优先级设置寄存器,设置多个中断同时发生时先处理谁后处理谁的问题。一般来说高优先级的中断可以打断低优先级的中断,从而嵌套处理中断。当然了有些硬件/软件可以设置不支持中断嵌套。
      6. VICnVECTADDR0~VICnVECTDDR31VICnADDR
        1. 这“三个”寄存器和210中断处理第二阶段的第二阶段有关。
        2. VICnVECATDDR03132个寄存器分别用来存放真正的各个中断对应的isr的函数地址。相当于每一个中断源都有一个VECTADDR寄存器,程序员在设置中断的时候,把这个中断的isr地址直接放入这个中断对应的VECTADDR寄存器即可。
        3. VICnADDR这个寄存器是只需要读的,它里面的内容是由硬件自动设置的。当发生了相应的中断时,硬件会自动识别中断编号,并且会自动找到这个中断的VECTADDR寄存器,然后将其读出复制到VICnADDR中,供我们使用,这样的设计避免了软件查找中断源和isr,节省了时间,提高了210的中断响应速度
    1. S5PV210中断处理的编程实战
      1. 上节中代码中的小问题
      2. 中断控制器初始化
        1. 绑定异常向量表到异常处理程序
        2. 禁止所有中断源
        3. 选择所有中断类型为IRQ
        4. 清理VICnADDR寄存器位0
      3. 中断的使能与禁止
        1. 先根据中断号判断这个中断属于VIC几,然后再用中断源减去这个VIC的偏移量,得到这个中断号在本VIC中的偏移量,然后1<<x位,写入相应的VICINTENABLE/INTENCLEAR寄存器即可
      4. 绑定自己实现的isrVICnVECTADDR
        1. 绑定
      5. 真正的中断处理程序如何获取isr
        1. 当发生中断源时,硬件会自动把相应,

    总结:第四步绑定isr地址到VICVECTADDR和第五步中断发生时第二阶段的第二阶段如何获取isr地址,这两步是相关的。这两个的结合技术,就是我们一直说的210的硬件自动寻找isr的机制。

     

    整个中断的流程梳理:

    整个中断的工作分为两部分:

    第一部分是我们为中断响应而做的预备工作:

    1. 初始化中断控制器
    2. 绑定写好的isr到中断控制器
    3. 相应中断的所有条件使能

    第二部分是当硬件产生中断后如何自动执行isr

    1. 第一步,经过异常向量表跳转入IRQ/FIQ的入口
    2. 第二步,做中断现场保护(在strat.S中),然后跳入isr_handler
    3. 第三步,在isr_hangdler中先搞清楚是那个VIC中断了,然后直接去这个VICADDR寄存器中取ISR来执行即可。
    4. 第四步,isr执行完,中断现场恢复,直接返回继续做常规任务。

     外部中断

      1. 什么是外部中断?
        1. SoC支持的中断类型中有一类叫外部中断。 内部中断就是指的中断源来自于SoC内部(一般是内部外设),譬如串口、定时器等部件产生的中断;外部中断是SoC外部的设备,通过外部中断对应的GPIO引脚产生的中断。
        2. 按键在SoC中就使用外部中断来实现。具体实现方法是:将按键电路接在外部中断的GPIO上,然后将GPIO配置为外部中断模式。此时人通过按按键改变按键电路的电压高低,这个电压高低会触发GPIO对应的外部中断,通过引脚传进去给CPU处理。
        3. 外部中断相关介绍和寄存器都在GPIO 部分
      1. 电平触发和边缘触发
        1. 外部中断的触发模式主要有2种:电平触发和边缘触发。
        2. 电平触发就是说GPIO上的电平只要满足条件,就会不停触发中断。电平触发分为高电平触发和低电平触发。滴娘·电平触发的特点是,只要电平满足条件就会不断触发中断。
        3. 边沿触发分为上升沿触发、下降沿触发和双边沿触发三种。边沿触发不关心常规状态,只关心电平变化的瞬间(边沿触发不关心电平本身是高还是低,只关心变化还是从高到低)
      1. 关键寄存器:CONPENDMASK
        1. 外部中断的主要配置寄存器:EXT_CONEXT_PENDEXT_MASK
        2. EXT_CON 配置外部中断的触发方式。触发方式就是说外部电平怎么变化就能出发中断,也就是说这个外部中断产生的条件是什么
        3. EXT_PEND寄存器时中断挂起寄存器。这个寄存器中每一位对应一个外部中断,平时没有中断时值为0.当发生了中断后,硬件会自动将这个寄存器的位就相当于是一个标志,如果发生了中断
        4. EXT_MASK寄存器

       

       

       

       

       

       

       

       

       

       

       

       

       



    0 0
    原创粉丝点击