zoukankan      html  css  js  c++  java
  • 5.2440的按照中断编程

    5.2440的按照中断编程

    首先是打开底板的原理图,找到按键的信息:

    可以找到四个按键:

    可以看到四个按键对应的引脚是EINT1、EINT4、EINT2和EINT0. 然后在核心板原理图里去搜索这四个按键,可以看到下面的信息:

    可以看到,按键中断与寄存器组GPF的引脚是互用的。所以接下来就是查看芯片手册里的GPF组寄存器的信息:重点是关注GPF控制寄存器:GPFCON

    由于是按键,要配置成中断的方式,所以对应的GPF位设置为10=EINT[*]的方式。由上面知道要设置的位是EINT0、EINT4、EINT1和EINT2.

    其实上面的这些设置就是中断源的设置。

    代码:

    上面就是初始化按键,也就是初始化中断源。

    接下来是中断控制器的初始化:interrupt.c

    由芯片手册知道,中断从发生到CPU响应的流程:

    由于这里是按键中断,不用考虑SUBMASK,而且主要是讲按键中断的MASK操作,所以中断的模式MODE也不考虑和Priority保持为默认值。所以找到中断控制器的MASK寄存器:

    它是由很多位构成的,每个位控制一种中断:

    上面的信息知道对应的位如果是1,该中断会被屏蔽。由于我们要使用四个按键,对应的中断是EINT4、EINT2、EINT1和EINT0,所以要把这四位设置为0.但是这里需要注意的是[4]位控制了EINT4_7四个中断,所以要设置EINT4的时候,还需要在EINTMASK寄存器里进行相应的设置。

    从上面知道,只有把该寄存器的第[4]位设置为0即可。

    注意的是EINT4在EINTMASK寄存器里的设置必须在前面。

    上面就完成了中断控制器的设置。

    由于前面把中断给屏蔽了,现在就要把它打开,通过CPSR寄存器的I位:

    重要位的解释:

    可以看到只要将对应的位置为0就是打开中断。这里CPSR的末尾8位是属于control域的,我们使能中断也只是需要操作这8位。中断打开实现代码:

    上面到这里才完成了中断的初始化。接下来是中断处理的部分。

    中断处理:

    保存环境的流程示意图:

    可以看到,当中断产生的时候,系统会把处理完中断要跳转回来继续执行的位置lr-4的地址保存入lr寄存器里,用于保存环境。然后批量的保存现场的寄存器里的值:

    stmfd sp!, {r0-r12, lr} /* 保护现场 */

    这里的sp是堆栈指针,就是不r0-r12,13个寄存器的值和lr寄存器的值都保存到堆栈里。注意sp后面的!是指每一次的修改都将改变sp指针的值。

    这样就保存好了现场,接下来就是中断处理程序的执行:

    跳转到handle_int来处理不同的中断处理:

    1. 判断产生中断的中断源
    2. 根据中断源执行相应的中断处理程序。

    1.要判断产生中断的中断源,需要通过一个寄存器INTOFFSET,它的每一个位代表一种中断信号:

    所以接下来定义一个值,把这个寄存器里的值读出来。

    由按键的原理图:

    从上图知道,当一号按键K1被按下的时候,产生的中断是EINT1,当二号按键K2被按下的时候,产生的是EINT4,当三号按键被按下的时候,产生的是EINT2,当四号按键被按下的时候,产生的是EINT0.这四种中断源对应的OFFSET的值如下图:

    下面是通过switch语句来实现不同按键按下相应的中断处理程序:

    上面就完成了按键中断处理程序,但是此时我们还不能进行编译执行,再回去看中断处理的流程图:

    /

    在这流程图中还有SRCPND和INTPND寄存器没有设置。这两个寄存器是干啥用的呢?先来看芯片手册:

    原来这个寄存器的作用是把处理完的中断对应的中断位清0的,这样,下一次中断产生才会被相应而得到相应的处理。所以我们处理完按键中断后,也需要对相应的位进行清0操作。

    该寄存器对应的位的信息:

    INTPND寄存器也是同理的,INTPND寄存器对应的参数:

    接着就是对上面两个寄存器对应的位进行清零操作:对于这两个寄存器要注意的是,如果我们想往对应的位写入0,需要将该位设置为1,这是跟其他寄存器不同的地方。

    这里由于我们用到了EINT4产生的中断源,它是属于EINT4_7寄存器组的,所以我们也需要设置清除EINTPND寄存器。

    同理就是往对应的位写入1就是清零。

    最后实现中断清零的代码:

    处理完中断后就是恢复现场,把保存在堆栈里寄存器的值全部恢复回来,只是现在lr寄存器要变成pc程序状态寄存器了。

    到这里我们就完成了中断的设置工作,执行make进行编译操作,将bin文件烧写到开发板,发现LED灯不亮,就是说我们的程序还存在着问题。那么这问题究竟出在哪呢?

        其实问题就出在没有初始化堆栈,因为刚开始初始化的堆栈是在SVC模式下的:

    可以看到程序一开始就工作在SVC模式,而我们的按键中断是工作在irq模式的。我们需要这是工作在irq模式的堆栈,才能让程序正常运行。要设置系统工作在irq模式,需要将CPSR的模式位设置为10010:

    实现代码:

    这里的cpsr_c是CPSR寄存器的末尾8位:

    这里设置的值为0xd2=0b 11010010,可以看到该值把中断打开了,而且还设置系统工作在irq模式。

    最后的代码是:

    我们给irq模式下的sp堆栈设置了值,接着给SVC模型下的sp堆栈设置了值。重新编译一下烧写到开发板,当我们按下相应的按键的时候,可以看到对应的LED灯亮了。

  • 相关阅读:
    投产包错误的思考
    Oracle----用户操作
    3.27 学习记录
    3.26 学习记录
    3.25 学习记录
    3.24 学习记录
    3. 23构建之法读后感
    3.22 学习记录
    3. 21学习记录
    3.20 学习记录
  • 原文地址:https://www.cnblogs.com/FORFISH/p/5188792.html
Copyright © 2011-2022 走看看