5.2440的按照中断编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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灯亮了。

以上是关于5.2440的按照中断编程的主要内容,如果未能解决你的问题,请参考以下文章

系统定时器HZjiffies

单片机C语言如何满足条件就立即退出中断函数

通过系统调用分析system_call中断处理过程

T6 中断编程

编程处理0号中断

stm32中断优先级管理与外部中断编程