×
嵌入式 > 嵌入式开发 > 详情

OK6410 裸机中断最简单代码

发布时间:2020-08-20 发布时间:
|
近来想学ARM开发,使用了S3C6410核的OK6410开发板,为了学习ARM的底层技术,想从裸机开始学习,结果一路挫折,问题多多,经过很长一段时间的摸索也没有太多成果,因为平常上班,项目的事情也忙,看书的时间也不够多,结果走进中断编程都经过了将近一个月!!

中断,我认为在初学单片机开发的时候是一个比较麻烦的事情,所有想把这个东西弄懂,结果在网上找了遍,都没有找到可以用的代码!为什么呢?因为懂的人,觉得没有必要,不懂的人反正是不懂,就像我一样。在论坛上/zixunimg/eepwimg/bbs.witech.com.cn/thread-3809-1-1.html ,我觉得那个裸机视频很好,至少我在视频的帮助下,很快可以完成点灯了,那种兴奋是非常好的,但想走入中断,那就是一个很麻烦的事。高手们写的代码,太长太多,像我只是知道一点点的,是看不懂太多代码的,至于官方的代码,更是难懂,因为太多太复杂,对于初学者不利,容易打退堂鼓。(……好像说了太多废话了,其实我想说的是,初学这东西,还是要有点韧性好)


如果想在OK6410开发板上学着写一个裸机程序,那本文是非常适合你的,我会让你知道写中断的一切我知道,而你也同样需要的知识。如果您是高手,请莫见笑,并烦请指教。

本文将使用最简代码来完成定时器0的中断,每秒中断一次,并轮流显示开发板上的四个小LED灯。

程序两个部分,一部分是启动代码(汇编),另一部分是中断C程序。

节选启动复位代码:

[cpp]view plaincopy
  1. ;允许中断
  2. ENABLE_IRQ
  3. MRSR0,CPSR;将CPSR保存至R0寄存器中
  4. BICR0,R0,#0x80;R0=R0&~0x80,清除中断位
  5. MSRCPSR_c,R0;将R0写回CPSR状态寄存器
  6. MOVPC,LR;返回到调用代码
  7. ResetInit
  8. LDRR14,=0x50100000;初始化一下栈指针
  9. BLENABLE_IRQ;打开中断允许位
  10. BMain;跳入MAIN程序

上面的代码就是一个简单的启动代码,当然来包括中断向量配置这些,这些请查看上传的工程文件。

如果需要完成中断,那么一定得打开中断允许位,不然,任意中断都是不会产生的,这是我摸索过程中的一个问题。这个问题很难吗?不是,而是因为没有人告诉你这么做,后来我在周立功出的ARM基础书上看到的。总之,要完成一个中断的产生,需要具备三个条件:(1)初始化了中断源,(2)配置了中断向量允许位,(3)状态寄存器的标志位请零。上述代码完成了第三个条件,下面,我通过代码来完成中断源的初始化工作。下面给出一张周立功给出的一张图:

如果您因为中断不能进入,请检查是否满足前面的三个条件,也对应于本图的三个环。

当我发现中断不进入的时候,也看到过此图,但并没有理解,只到我调度的时候,在AXD下查看CPU寄存器的时候,发现I与F的标志,将手对修改了I标志,结果中断程序的断点进入了,至此明白了这个图。有时候一个图在这里,如果你没有理解这个图,或者理解这图背后的原理,是很难明白绘图者的真正函义。图对于理解了的,很容易记忆,而且有用,对于其它人而言,也容易理解,但有时候理解并不能把握真实的函义,所以需要学习,将图的理解,并最终成为自己的记忆。

下面代码通过设置寄存器来完成配置工作。在这里的代码,如果你手上没有芯片文档,那基本上是看不懂的天书。因为我是菜鸟,所以我觉得我的问题可能是一些初学者的问题。比如,下面的代码为什么是这样写的,这样写的依据是从哪里来的?你告诉我去参考文档,我知道了这个配置的原理,但我还是无法融汇贯通啊?我当时看文档的时候总是问自己这些问题。为什么呢?因为文档太长太多,而且是英文的,我手里的S3C6410文档就有1371页,是不是我写LED就只看GPIO部分了呢?的确是这样,但你想写中断了,是不是只看定时器单节就可以了,这里回答肯定不是这样的,你需要查看中断相关节,可能还要查看前面几节关于CPU的特性介绍,中断功能的介绍等信息,这也意味着,走入中断,表示你对这个CPU也有所了解了,通过对中断的理解,也表明你可以做更多有意义的事情了。看文档,看资料是必须的,遇到问题再去看资料的时候,会得到一些灵感。

[cpp]view plaincopy
  1. //初始化定时器0,重动重载计数值
  2. //这里为什么是这样的顺序,为什么这么写,请参考S3C6410芯片文档
  3. voidtimer_init(void)
  4. {
  5. rTINT_CSTAT|=1<<0;//开timer0中断,允许timer0中断发生
  6. rVIC0INTENABLE|=1<<23;//开timer0的使能(相当于关掉mask)
  7. rTCFG0&=~0xFF;//清除预分频因子位
  8. rTCFG0|=0x42;//设置分频因子(66分频),定时器时钟频率为1Mhz
  9. rTCFG1&=~0x11;//设置DividerMUX0为零1分频
  10. rTCNTB0=1000000;//设初值(1s)
  11. rTCON|=1<<1;//开ManualUpdate(UpdateTCNTB0,TCMPB0)设置初值后要更新TCNTB
  12. rTCON|=1<<3;//AutoReloadon自动重装开启
  13. rTCON|=1<<0;//timer0open;
  14. rTCON&=~(1<<1);//不再UpdateTCNTB0,TCMPB0
  15. }
上在的代码完也了定时器的初始化,开始,我通过写定时器状态零位,打开TIME0中断,然后,基本中断向量允许位,这也是中断条件(2)需要的,这样定时器中断配置就配置好了,然后, 需要初始人中断源的配置信息,这是条件(1)所要求的,我们需要定时器完成定时任务,就需要定时器计数到零的时候,自动装载计算值,重新计数,以重新产生中断。这里为什么要这么设置了,设置的顺序在文档中有说明的,比如这里对rTCON的配置就是要求的一个顺序。定时器分频在S3C6410文档的PWM节有描述,这里将时间频率设为1MHz,这样我们就好计算定时的时间了。

关于定时器初值的计算,我说一下我的理解。

MHz是兆赫兹,表示一秒内振荡的资料,这表示1MHz = 每秒震荡1000 000次,反过来,如果你需要一秒的定时,你需要计数1000,000次,也就是要求频率为1MHz,那如何配置频率为1MHz呢?参考手册上有这个参数:

Timer input clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value}

这样如果需要一秒的时间一次中断,在没有配置PPL(可以配置CPU的倍频的东西)的情况下,CPU的频率为FOSC的频率,即66MHz,在分频为66,预分频为0,那么需要设置计数值为1000,000,这样就可以产生每秒一次的中断了。

中断初始化完成之后,主程序可以进入死循环,等待中断的来临……

在等待之前,我们需要正确设置中断向量,进入C语言代码的中断程序,再正确返回到程序的原为位置。中进入中断向量之前,CPU进入中断状态,使用中断状态下的特殊寄存器,通过寄存器仍然使用中断之前模式的,为了防止破坏中断之前的代码,需要备份这些寄存器,之后,将中断函数的返回地址设置好后,就可以进入实际中断处理函数了。中断处理函数返回后,需要恢复寄存器现场,并通过将PC设置为中断前的地址,以使主程序断续。

[cpp]view plaincopy
  1. IRQHandler
  2. STMFDSP!,{r0-r3,r12,lr};保存现场
  3. ldrlr,=int_return;设置中断异常处理程序返回地址到下面的位置
  4. BIRQ_Exception;直接进入到中断函数处理
  5. int_return
  6. LDMFDSP!,{r0-r3,r12,lr};恢复现场
  7. SUBSPC,LR,#4;返回进入中断前的代码
通过上面的简陋代码,可以让中断进入到我们的C程序IRQ_Exception程序中。

下面给出简单的中断跑马灯代码:

[cpp]view plaincopy
  1. inti=0;
  2. //IRQ异常中断
  3. voidIRQ_Exception()
  4. {
  5. i%=4;
  6. //打开一个灯,并闭另外一个灯
  7. rGPMDAT=~(1<
  8. //清除定时器中断状态位
  9. while((rTINT_CSTAT&0x20))rTINT_CSTAT|=(1<<5);
  10. }
中断程序很简单,切换灯,并清除中断。清除中断是我最后的一个难点,这一行代码,我查了很多资料,还不是很明白。首先,中断状态一定要清除的,不然程序进入中断后,将不会再出来了,因为中断状态不清,中断将会不断的产生。还有中断状态清除是通过置位寄存器指定位来清零的,如果不加入while等待,那么清除指令操作很可能没有正确执行,导致中断会马上再次进入,而且表现在灯效果上,就是四个灯只有两个隔着亮,这里的原因是第二次清中断,一条指令就可以成功,第一次不会成功。如果在中断加入延时代码,也会每次都成功。后来分析,并参考资料,说是在电平中断时,只有在中断无效状态时,该位置位才有效。这也是这里为什么一定会使用while等待的原因了。

好了,中断程序就这样介绍完了,这里还有如何设置启动代码,寄存器如果定义等相关内容,可以参考由上面给出的飞凌论坛的《裸机教学视频第一季》。如果出了第二季,我就不会这么走的如此艰辛了。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
智能化系统工程设计中的若干技术问题