近来想学ARM开发,运用了S3C6410核的OK6410开发板,为了学习ARM的底层技能,想从裸机开端学习,作用一路波折,问题多多,经过很长一段时刻的探索也没有太多作用,由于往常上班,项目的作业也忙,看书的时刻也不够多,作用走进中止编程都经过了将近一个月!!
中止,我以为在初学单片机开发的时分是一个比较费事的作业,全部想把这个东西弄懂,作用在网上找了遍,都没有找到能够用的代码!为什么呢?由于懂的人,觉得没有必要,不了解的人反正是不了解,就像我相同。在论坛上http://bbs.witech.com.cn/thread-3809-1-1.html ,我觉得那个裸机视频很好,至少我在视频的协助下,很快能够完结点灯了,那种振奋是十分好的,但想走入中止,那便是一个很费事的事。高手们写的代码,太长太多,像我仅仅知道一点点的,是看不了解太多代码的,至于官方的代码,更是难明,由于太多太杂乱,关于初学者晦气,简略打退堂鼓。(……如同说了太多废话了,其实我想说的是,初学这东西,仍是要有点耐性好)
假如想在OK6410开发板上学着写一个裸机程序,那本文是十分合适你的,我会让你知道写中止的全部我知道,而你也相同需求的常识。假如您是高手,请莫见笑,并烦请指导。
本文将运用最简代码来完结守时器0的中止,每秒中止一次,并轮番显现开发板上的四个小LED灯。
程序两个部分,一部分是发动代码(汇编),另一部分是中止C程序。
节选发动复位代码:
- ;答应中止
- ENABLE_IRQ
- MRSR0,CPSR;将CPSR保存至R0寄存器中
- BICR0,R0,#0x80;R0=R0&~0x80,铲除中止位
- MSRCPSR_c,R0;将R0写回CPSR状况寄存器
- MOVPC,LR;回来到调用代码
- ResetInit
- LDRR14,=0x50100000;初始化一下栈指针
- BLENABLE_IRQ;翻开中止答应位
- BMain;跳入MAIN程序
上面的代码便是一个简略的发动代码,当然来包含中止向量装备这些,这些请检查上传的工程文件。
假如需求完结中止,那么必定得翻开中止答应位,否则,恣意中止都是不会发生的,这是我探索过程中的一个问题。这个问题很难吗?不是,而是由于没有人告知你这么做,后来我在周建功出的ARM根底书上看到的。总归,要完结一个中止的发生,需求具有三个条件:(1)初始化了中止源,(2)装备了中止向量答应位,(3)状况寄存器的标志位请零。上述代码完结了第三个条件,下面,我经过代码来完结中止源的初始化作业。下面给出一张周建功给出的一张图:
假如您由于中止不能进入,请检查是否满意前面的三个条件,也对应于本图的三个环。
当我发现中止不进入的时分,也看到过此图,但并没有了解,只到我调度的时分,在AXD下检查CPU寄存器的时分,发现I与F的标志,将手对修改了I标志,作用中止程序的断点进入了,至此了解了这个图。有时分一个图在这儿,假如你没有了解这个图,或许了解这图背面的原理,是很难了解绘图者的实在函义。图关于了解了的,很简略回忆,并且有用,关于其它人而言,也简略了解,但有时分了解并不能掌握实在的函义,所以需求学习,将图的了解,并终究成为自己的回忆。
下面代码经过设置寄存器来完结装备作业。在这儿的代码,假如你手上没有芯片文档,那根本上是看不了解的天书。由于我是菜鸟,所以我觉得我的问题或许是一些初学者的问题。比方,下面的代码为什么是这样写的,这样写的根据是从哪里来的?你告知我去参阅文档,我知道了这个装备的原理,但我仍是无法融汇贯通啊?我其时看文档的时分总是问自己这些问题。为什么呢?由于文档太长太多,并且是英文的,我手里的S3C6410文档就有1371页,是不是我写LED就只看GPIO部分了呢?的确是这样,但你想写中止了,是不是只看守时器单节就能够了,这儿答复必定不是这样的,你需求检查中止相关节,或许还要检查前面几节关于CPU的特性介绍,中止功用的介绍等信息,这也意味着,走入中止,标明你对这个CPU也有所了解了,经过对中止的了解,也标明你能够做更多有意义的作业了。看文档,看材料是有必要的,遇到问题再去看材料的时分,会得到一些创意。
- //初始化守时器0,重动重载计数值
- //这儿为什么是这样的次序,为什么这么写,请参阅S3C6410芯片文档
- voidtimer_init(void)
- {
- rTINT_CSTAT|=1<<0;//开timer0中止,答应timer0中止发生
- rV%&&&&&%0INTENABLE|=1<<23;//开timer0的使能(相当于关掉mask)
- rTCFG0&=~0xFF;//铲除预分频因子位
- rTCFG0|=0x42;//设置分频因子(66分频),守时器时钟频率为1Mhz
- rTCFG1&=~0x11;//设置DividerMUX0为零1分频
- rTCNTB0=1000000;//设初值(1s)
- rTCON|=1<<1;//开ManualUpdate(UpdateTCNTB0,TCMPB0)设置初值后要更新TCNTB
- rTCON|=1<<3;//AutoReloadon主动重装敞开
- rTCON|=1<<0;//timer0open;
- rTCON&=~(1<<1);//不再UpdateTCNTB0,TCMPB0
- }
上在的代码完也了守时器的初始化,开端,我经过写守时器状况零位,翻开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设置为中止前的地址,以使主程序断续。
- IRQHandler
- STMFDSP!,{r0-r3,r12,lr};保存现场
- ldrlr,=int_return;设置中止反常处理程序回来地址到下面的方位
- BIRQ_Exception;直接进入到中止函数处理
- int_return
- LDMFDSP!,{r0-r3,r12,lr};康复现场
- SUBSPC,LR,#4;回来进入中止前的代码
经过上面的粗陋代码,能够让中止进入到咱们的C程序IRQ_Exception程序中。
下面给出简略的中止跑马灯代码:
- inti=0;
- //IRQ反常中止
- voidIRQ_Exception()
- {
- i%=4;
- //翻开一个灯,并闭别的一个灯
- rGPMDAT=~(1<
- //铲除守时器中止状况位
- while((rTINT_CSTAT&0x20))rTINT_CSTAT|=(1<<5);
- }
中止程序很简略,切换灯,并铲除中止。铲除中止是我最终的一个难点,这一行代码,我查了许多材料,还不是很了解。首要,中止状况必定要铲除的,否则程序进入中止后,将不会再出来了,由于中止状况不清,中止将会不断的发生。还有中止状况铲除是经过置位寄存器指定位来清零的,假如不参加while等候,那么铲除指令操作很或许没有正确履行,导致中止会立刻再次进入,并且体现在灯作用上,便是四个灯只要两个隔着亮,这儿的原因是第2次清中止,一条指令就能够成功,第一次不会成功。假如在中止参加延时代码,也会每次都成功。后来剖析,并参阅材料,说是在电平中止时,只要在中止无效状况时,该方位位才有用。这也是这儿为什么必定会运用while等候的原因了。
好了,中止程序就这样介绍完了,这儿还有怎么设置发动代码,寄存器假如界说等相关内容,能够参阅由上面给出的飞凌论坛的《裸机教育视频第一季》。假如出了第二季,我就不会这么走的如此艰苦了。
程序下载地址:http://download.csdn.net/source/3567988