使用NXP的LPC2214系列MCU真是对技术的磨炼,如果手里没有中文的技术手册不知道什么时候才能弄明白它的使用方法,这里感谢一下ZLG。
首先说一下之所以说LPC2214非常麻烦,主要有几方面,首先,就是他里面有大量的管脚复用,通过不同的配置寄存器将管脚配置为多种不同的应用,很多管脚在启动过程中又有着不同的功能,如PINSEL2配置寄存器中,当有多个外设时,如带有片外flash,片外SRAM,以及FPGA等等,需要将根据其位宽选择不同的A0,A1管脚,需要根据片外访问空间大小确定使用地址线的数量,选择最多支持到A23,但是A23地址线被该MCU设置为XCLK,时钟同步输出,为了使用时钟同步,就不能将A23配置为地址线,这样就不能使用最大容量的片外存储器,很麻烦,不知道当时在设计时怎么考虑的。还有就是LPC2214连接管脚很有意思,千万要注意的是,在设计时A0,A1地址线的使用,8位外设使用A0~,16位使用A1~,32位使用A2~千万不要接错了,否则后果很严重。会出现各种各样意向不到的错误,如memcpy内存块操作时莫名其妙的丢数,在使用过程中对方面需要极度小心。
还有就是几个特别的管脚,P0.14,P0.16在MCU启动时的高低电平会作为启动方式的选择,需要根据自身需要小心连接,最好通过跳线引出来。在使用中对几个重要的寄存器的使用很有技巧,在使用LPC2214过程中,首先要启动PPL,配置相关寄存器,接着就要设置GPIO,就是PINSEL0~2,这里需要将每个引脚的作用考虑清楚,要怎么使用就怎么配置,特别是PINSEL2寄存器,一定要注意对A0,A1,A23地址线的配置,如果硬件连接没有问题的话,建议A0,A1即使片外使用的是16位,32位存储器A0,A1并未使用也将其设置为地址线,手册上虽然没说,但应用中发现A0地址线作为GPIO,输出数据会出现错误。在设置完GPIO后,就是设置MEM了,LPC2214可以连接4个外设,CS0~CS3,我们需要配置BCFG0~3来设置外设的访问位宽以及访存时间,这里为了保险起见可以设置为最保险的访存时间,0xXXXXffef,如果为了追求高性能,需要根据外设的属性进行相应的调整。接着就是MEMAP,LPC2214支持存储器映射异常向量,需要根据自己的要求进行修改,这里是比较特殊的地方,需要注意根据不同的运行环境选择不同的配置,简单来说就是,如果运行在片内flash的话就直接设为1,如果运行在片内RAM中的话,首先将中断向量拷贝到RAM相应位置,再将该寄存器设为2,最后如果是由片外flash启动并且不想拷贝异常vector到RAM的话,需要将该位设置为3,这里需要注意的是如果该MEMAP设为3,即由片外flash中断映射的话,一定要先将GPIO,BCFG设置完后再设置MEMAP寄存器。因为设置MEMAP为3,需要访问外部flash,就需要使用BCFG0,PINSEL2的配置进行访问了,这里郁闷了我很久,才最后终于想明白的。
LPC2214带有256KB的片内flash,同时支持片外Norflash的启动方式,这里又是一个**烦,首先说明一下,如果所编的程序能够在256KB(有8KB为片内Bootloader,实际存储空间为248KB)的容量内装下的话,就坚决使用程序跑在片内flash中,片外flash作为数据存储器的方式来存放,主要原因是LPC2214对片内flash访问有缓冲区,通过2片缓冲区交替读取命令,可以使MCU达到1个周期读取一条指令的速度,执行效率非常高。因为有片内flash,有片外flash,就有了LPC2214的多种启动方式的选择。前面说过,LPC通过P0.14的在启动时的高低电平来判断进入何种状态,LPC2214的启动过程是个难点,主要的原因就在于它是带有固化的bootloader的,每次启动首先启动的是固化在内部的bootloader,具体的过程可以参看官方用户手册,我只简单说一下,在1.61版以后的官方bootloader启动后与用户程序相关的部分主要在于系统bootloader启动后首先检查BOOT 0,1 管脚状态,如果不为1 1就进入外部flash引导模式,反之就会进入内部flash引导模式,这里需要注意的是通常外部通过BOOT 0,1引脚来选择外部flash的操作位宽,我们只能使用CS0上的flash作为片外引导flash,需要根据引导flash位宽来进行配置,如对ZLG的EASYARM2200板子上的SST1601就是16bit的,需要将BOOT设置为0 1由外部16位引导。这里如果外部引导程序不能运行,则系统就会什么都不执行,一直等待,不会尝试引导片内flash的。只有当BOOT O 1为1 1时才会引导片内flash的,需要注意的是引导片内flash,bootloader会首先验证片内flash程序的有效性,该有效性的验证就是通过vector14中的值来进行判断的,需要全部异常向量的指令之加和为0才能被认为是有效地程序。
下面说一下题目中的关于eCos在LPC2214上跑的问题,首先,很早以前eCos就被我移植到了片内的flash中,eCos3.0中有好几个模板都是基于LPC22XX系列MCU的,如phycore2294/2292,olpc e/h/l三款板子都是基于LPC22XX的CPU来的板子,我们可以根据自己的移植目标板进行相应的移植修改。推荐使用olpch的,因为olpch的板子所包含的外设最少,最方便我们在其基础上添加自己的配件,减少麻烦。phycore的板子外设很多,如果移植的目标板是大而全的,可以使用该模板进行修改。具体的移植流程网上很多,我就不详细说明了,主要说一下重点的片外flash的问题,通过上面我所说的使用片外flash的进行引导应该很简单的,正常只需要修改eCos中目标开发板的XXXXrom.ldi,以及XXXXrom.h就是开发板的存储空间分配,以及链接文件,将ROM修改为0x80000000~0x8XXXXXXX就可以了,直接编译烧进去就应该能启动了,可是却不是这么简单的,问题很奇怪,在片内flash中跑的完全正常的程序,修改ldi,rom空间分配后,烧录的时候确实烧录到片外flash中了,使用仿真器仿真也能运行,但RST后就是没有反应,百思不得其解,网上发现很多人也有同样的问题,并且没有相应的解决方案,看来只有自己努力了。首先,定位问题,通过现象可以看出,程序烧录的时候自动将hex文件烧录到0x80000000开始的片外flash中,证明修改ldi文件有效,程序的空间确实已经转移到0x80000000开始的片外了,通过仿真器也能运行,证明程序本身没有问题,而就是RST后出问题,问题只能出现在启动引导过程中,因为我在仿真器中,每次调用set PC,0X80000000相当于手动引导CPU执行0x80000000处的程序了。开始以为是片内bootloader的问题,仔细阅读手册后发现问题应该还是出现在eCos中。但是还是确定不了问题所在,只好通过反汇编正常片外启动的程序,与现在不能正常启动的程序了,这一对比,发现居然异常向量不一致,仔细一想就明白了,应该是在eCos中异常向量表调用的是b RESET,而正常片外引导的程序使用的是ldr pc,=RESET,两者的区别就是b只能访问前后32M空间的,而ldr则能访问全空间,在片外引导时,需要由0跳转到0x80000000,这样显然就不能够正常引导了,但是改程序在片内运行时绝对没有问题,因为片内flash空间就在0x00000000~0x00003fff的256K空间中跳转,绝对不会出错。确定问题所在就好办了,通过对eCos架构的了解,修改ARM体系中Vector.S文件,将其中引导程序改为ldr,pc,=Reset,阅读Vector.S文件会发现,eCos中在未定义XXXJ_USE_JUMP宏时采用的同样是ldr pc,=Reset,但我也没找到在哪定义的该宏,只好将该宏的部分注释掉,只保留ldr部分,测试,正常。至此使用eCos就可以在LPC2214的片外的flash启动了。
以上是我在使用LPC2214,以及配置eCos时遇到的一些注意的要点以及解决办法,希望对大家有帮助。总结一下,首先LPC2214的MCU确实很强大,但也许正因为其强大,它的配置非常复杂,很多事项都是相互关联的,需要由透彻的理解才能由全局的角度来把握;其次对eCos系统来说,从嵌入式开发的角度来说eCos系统确实很好很强大,但其系统源码的风格确实不敢恭维,如果遇到系统级的问题很难解决,尤其是该问题涉及到具体的硬件实现时,这种时候不要急于分析源代码,首先要根据现象想清楚可能的原因,再有针对性的查找相应的源码进行改写。 |