6.6410和210的按键中断编程

6.6410和210的按键中断编程

首先是打开6410底板原理图:

可以看到OK6410有六个按键:

可以看到OK6410的六个按键对应的引脚是KEYINT1、KEYINT2、KEYINT3、KEYINT4、KEYINT5和KEYINT6。接着在核心板的原理图里搜索这个词:

可以看到按键中断与GPN系列寄存器的引脚是互用的,接着就是在芯片手册里查看有关GPN系列寄存器的信息,重点是关注GPN控制寄存器:GPNCON:

这里我们使用到的按键对应的中断,需要配置成中断的方式,对应的GPN位设置为10,中断功能,即需要将KEYINT1-6设置为中断功能的,即是将GPNCON对应的前12位设置为101010101010即可。这样就把对应的GPN0-5设置为中断位。实现代码:

上面我们完成了按键的初始化,这样就把六个按键对应的位设置为外部中断的功能了。

接下来就是中断的初始化了。

    1.设置按键中断是发生在下降沿,也就是下降沿触发的方式,即低电平,按键弹开是上升沿,也就是高电平。

这里需要寄存器EINT0CON0:

由原理图知道KEYINT1-KEYINT6对应的中断位是XEINT0-XEINT5,由上面设置从下降沿触发:

设置好了下降沿触发,接着就是把先前屏蔽的功能去掉,就是使能中断:

屏蔽寄存器:

这里我们需要将对中断位EINT0-EINT5的屏蔽功能给去掉,要不然,即使发生了中断也不会送到CPU。这是为了方便,就不一一去设置,直接将该寄存器赋值为0,就是全部中断去掉屏蔽:

取消屏蔽外部中断后,就是使能外部中断的操作:

上面两个寄存器就是使能中断的,每一位控制一种中断源,在系统复位之后默认的值是0,如果需要使能某个中断,就需要将对应的位设置为1=Interrupt enabled。

从上面知道,我们的外部中断0-3是属于中断源0的,外部中断4-11是属于中断源1的。所以要使能六个按键的外部中断,需要使能0号中断源和1号中断源,该中断源是属于VIC0寄存器组的,就是往VIC0INTENABLE的0位和1位写入1即可,代码实现:

这样使能外部中断也完成了。

接下来设置CPSR程序状态寄存器,来打开总的中断控制,因为前面的学习中是把它关闭的。

到这里如果按照2440的非向量中断的设置到这里就结束,但是在6410里还没有,因为6410采用的是向量中断方式。

首先来看看非向量中断方式的流程图:

上面就是非向量中断的中断处理流程,当中断产生的时候,会跳转到对应的统一的入口,去执行对应的中断处理程序,大部分的工作都是软件来完成的。

而6410的向量中断,很大部分的工作是硬件来完成的,这样速度会更快,原理图:

上面就是向量中断的原理。

所以接下来就是在中断初始化的时候,把对应的中断处理程序(就是处理程序的函数名字)安排到对应的寄存器里。接下来就是该操作:先找到对应的寄存器组:

可以看到属于VIC0组的有32个寄存器,属于VIC1组的也有32个寄存器,刚好64寄存器,对应64个中断源。按键1对应的是EINT0,也就是对应寄存器0x71200100.

代码:

上面就是按键的中断处理程序。但是在6410默认是没有使能向量中断的,它是先下兼容,默认是非向量中断的,所以6410要使用向量中断需要使能。注意210就不需要使能了。在CP15的c1寄存器的24位控制的。6410使能代码:

__asm__(

"mrc p15,0,r0,c1,c0,0 "

"orr r0,r0,#(1<<24) "

"mcr p15,0,r0,c1,c0,0 "

"mrs r0,cpsr "

"bic r0, r0, #0x80 "

"msr cpsr_c, r0 "

:

:

);

上面就是使能向量中断的操作,到这里才完成了6410的中断初始化的操作。

最后就是中断处理了。

步骤:

  1. 保存环境
  2. 中断处理
  3. 清除中断
  4. 恢复环境

1.保存环境:

__asm__(

"sub lr, lr, #4 "

"stmfd sp!, {r0-r12, lr} "

:

:

);

2.中断处理:

3.是清中断:

清中断对应的寄存器:

该寄存器当相应的中断产生的时候,对应的中断位会被置1.从该寄存器的NOTES知道,如果往对应的中断位写入1,则就是清除中断。这里为了方便,我们写入全1,清除所有的中断。

我们前面知道每一种向量中断对应一个寄存器

VIC0组的寄存器:

VIC1组寄存器:

上面就是64中断源对应的64个寄存器,在这些寄存器的后面有寄存器VICxADDRESS:

这种寄存器有两个,VIC0ADDRESS和VIC1ADDRESS.例如当VIC0的一个串口中断产生的时候,系统除了会调用对应的处理函数外,还会把中断处理程序的地址保存到VICxADDRESS寄存器里面。

当中断处理完后,要把这两个寄存器清零:

这样就完成了中断处理程序了。

4.最后一步就是清中断:

"ldmfd sp!, {r0-r12, pc}^ "

到这里才完成了中断处理程序的步骤,最后的部分代码如下:

注意到这里虽然中断的处理程序完成了,但是还不能烧写到开发板。这是因为跟2440的情况一样,我们的start.S里只有对svc模式的堆栈进行初始化,没有对irq模式的堆栈进行初始化。所以最后我们还得来对irq的堆栈进行初始化:

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

实现代码:

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

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

最后的代码是:

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

这就是6410的中断处理流程,对于210也是一样的操作,只是210默认是打开向量中断的,不必去设置打开,其他都是一样的。

原文地址:https://www.cnblogs.com/FORFISH/p/5188795.html