在LPC2468上移植vxWorks系统
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在LPC2468上移植vxWorks系统
林先贤senhill@
{辽宁,沈阳,110000}
[摘要] NXP的LPC2468是具有丰富资源的ARM7TDIMI系列CPU,使用片内资源就满足
移植vxWorks的条件,文章列举了在LPC2468上移植vxWorks嵌入式操作系统的特殊之处
及其解决方法,最后经验总结了移植vxWorks的一般步骤和调试方法。
[关键词] L PC2468,移植,vxWorks
Transplanting vxWorks system into
the LPC2468
[Abstract] NXP's LPC2468 is a rich resource ARM7TDIMI series CPU, the use of on-chip resources will meet the conditions for transplanting vxWorks。
This article lists the special features of the LPC2468 for transplanting vxWorks and according solutions,finally summarize the general steps and debugging methods in transplanting vxWorks.
[Keywords] LPC2468,Transplanting,vxWorks
NXP半导体设计的LPC2468微控制器是基于16/32位的ARM7TDMI-S CPU内核。
LPC2468具有512kB片内高速Flash存储器,该Flash存储器具有特殊的128位宽度的存储
器接口以及加速器架构,可以使CPU以高达72MHz的系统时钟速度来按顺序执行Flash存
储器的指令。
片内98kB RAM(包括64kB局部SRAM、16kB以太网SRAM、16kB通用DMA SRAM和2kB电池供电SRAM),4个UART,4个定时器,仅利用这些片内资源就可
以移植vxWorks系统。
内部可用的SRAM不是很大,如果需要更大的内存空间,LPC2468
的外部存储器控制器可以支持外扩的SDRAM或SRAM。
自带的ISP功能通过交叉串口线
就可以进行Flash编程。
以下针对512KB的片内Flash和64K的SRAM存储器资源移植过
程进行描述。
移植的开始是寻找一个尽量接近目标板的BSP,LPC2468的BSP官方网站没有提供,
这里是利用Tornado for ARM自带的wrSbcArm7目录代码进行修改。
首先说明一下,为了节省内存使用,同时也是充分利用内部高速Flash存储器,将vxWorks编译成Text段驻留Flash的,目标文件是vxWork_romResident.bin,bootRom的目
标文件是bootrom_res.bin,这个只是编译选项,具体代码并不需要做任何改动。
将wrSbcArm7复制成LPC2468目录,删除不用的文件,仅留下sngks32cIntrCtl.c,sngks32cSio.c,sngks32cTimer.c,sysLib.c,sysSerial.c,romInit.s,sysALib.s源文件及其依
赖的头文件。
Config.h文件需要对各功能宏定义做修改,比如#undef INCLUDE_NETWORK,#undefi INCLUDE_FLASH等。
Makefile文件中的MACH_EXTRA去除sngks32cEnd.o模块。
否则无法通过编译。
添加LPC2468.h替代sngks32c.h,该文件应包括所有用到的片内设备的接口定义。
另外添加一个usrfunc.c文件,包括启动底层设备初始化的代码,比如晶振,中断向量映射,外设功率设置,管脚功能配置等。
同时Makefile中的MACH_EXTRA添加usrfunc.o模块。
文件组成结构到这里就完成了,接下来是对具体内容的修改调试。
在config.h和Makefile文件中,修改RAM,ROM相应的配置,需要注意RAM的低64Bytes保留为异常向量,高32Bytes保留为IAP程序。
SRAM的基址为0x4000 0000,相关设置如下:
#define ROM_BASE_ADRS 0x00000000 /* base of Flash */
#define ROM_TEXT_ADRS 0x00000000 /* code start addr in ROM */
#define ROM_SIZE 0x0007E000 /* 504K,8K供固化的Boot Block使用*/ #define RAM_LOW_ADRS 0x40001000 /* vxWorks_romResident的data段基址*/ #define RAM_HIGH_ADRS 0x40002000 /* bootrom_res的data段基址*/
将中断模式设置为非抢占的,因而可以减小ISR栈大小。
定义如下:
#define INT_MODE INT_NON_PREEMPT_MODEL
#define ISR_STACK_SIZE 1024
romInit.s作为入口汇编程序,LPC2468不能对整个内存重映射,需要考虑各异常向量的处理。
采用如下语句:
LDR PC, ResetAddr
LDR PC, UndefinedAddr
LDR PC, SWI_Addr
LDR PC, PrefetchAddr
LDR PC, DataAbortAddr
.long 0xb8a06f60 /*满足前8条指令的累加和为0的Flash启动条件*/
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
ResetAddr:
.long cold
UndefinedAddr:
.long excEnterUndef
SWI_Addr:
.long excEnterSwi
PrefetchAddr:
.long excEnterPrefetchAbort
DataAbortAddr:
.long excEnterDataAbort
IRQ_Addr:
.long intEnt
FIQ_Addr:
.long FIQ_Handler
其中excEnterUndef,excEnterSwi,excEnterPrefetchAbort,excEnterDataAbort,intEnt 都是vxWorks提供的5个异常入口,而vxWorks系统不支持FIQ。
这样就实现异常向量与vxWorks系统异常处理的关联。
初始化底层设备的代码也可以在汇编里实现,不过还是建议在c代码中实现,便于编程。
在usrfunc.c文件编写的初始化函数lpc2468Init( ),在汇编跳转到c入口程序romStart( )前先调用。
代码如下:
stmdb sp!, {r0} /* r0入栈*/
BL FUNC(lpc2468Init) /* 带连接的跳转到底层设备初始化c代码*/
ldmia sp!, {r0} /* 恢复r0 */
LDR pc, L$_rStrtInRom /* 跳转到romStart( ) */
对r0操作说明一下,r0是保存冷启动或热启动的信息,作为romStart( )函数的传参,原有的代码是将r0保存到r13,跳转romStart( )前从r13恢复到r0,不过由于r13作为栈指针,在调用lpc2468Init前被初始化,调用之后r0的值已遭破坏,因此这里采用出入栈的办法保存r0的值。
与LPC2468初始化无关的汇编代码都删除,这样就完成了汇编到c的入口。
这里有一个方法确定汇编到c入口的正确跳转,用Tornado自带的objdumparm.exe查看编译后的汇编信息,格式如下
objdumparm –D [目标elf文件] > [输出文件]
通过输出文件查看,romStart的地址是否就是LDR pc, L$_rStrtInRom语句装载的地址。
修改串口,中断,时钟程序,将一个个函数与硬件相关程序的“翻译”成LPC2468相应的操作,这个过程最重要的是查阅CPU手册,了解各控制单元的编程接口。
接下来可以先调通电路板上LED的亮灭程序,通过LED指示状态可以确定代码按正确分支运行或定位代码问题所在。
移植过程中就是通过LED状态发现执行excV ecInit( )异常向量初始化时死机。
由于excV ecInit是vxWorks内部的一个函数,没有源代码,只能使用前面提到的objdumparm输出汇编信息查看,发现excV ecInit调用了armInitExceptionModes( )函数,并且将异常向量与excEnterUndef,excEnterSwi,excEnterPrefetchAbort,excEnterDataAbort,intEnt入口挂接。
这些异常向量挂接操作修改基址为0的内存数据,适用于RAM位于0地址开始的情况;对于LPC2468来说就是对Flash写操作,情况不可预料。
从c代码上这一语句
intV ecBaseSet ((FUNCPTR *) VEC_BASE_ADRS); /* set vector base table */
应该是设置异常向量的基地址,但是对于ARM CPU来说,通过反汇编跟踪,该函数是直接返回的空函数。
excV ecInit函数也不会调用intV ecBaseGet来获得基址。
vxWorks系统为了尽量保持不同体系CPU的源码一致性而保留了这些统一命名的函数框架,因此有些函数只是以空壳存在的无实际意义的操作,可以将intV ec BaseSet语句直接删除。
那么如何解决这一异常向量挂接问题呢?好在romInit.s汇编入口已经完成了这些异常向量跳转功能,因此可以直接去除这里的操作。
armInitExceptionModes函数进一步跟踪查看发现是对ARM不同状态下栈指针初始化,需要保留此代码。
可以直接将exc V ecInit语句改成armInitExceptionModes,但是在利用Tornado工程编译环境重编译时会自动重新生成代码,覆盖用户的手动修改。
需要保证不手动修改编译环境自动产生的文件,利用config.h(自动产生的文件包含config.h文件)的宏定义是比较好的解决方法。
#define exc V ecInit armInitExceptionModes
接下来还有几个问题需要注意,如中断系统相关的:
sngks32cIntrCtl.c文件中中断应答程序需要编写,代码具体实现如下:
sngks32cIntDevInit( )函数添加sysIntLvlV ecAckRtn = sngks32cIntLvlAck;
STA TUS sngks32cIntLvlAck (int level, int vector)
{
VICV ectAddr = 0;
return OK;
}
这是LPC2468的中断控制器要求的,必须在ISR结束时写该寄存器(写任意值),来更新VIC 优先级硬件。
在其它任何时候写该寄存器可能会导致不正确的操作。
另外定时器驱动中sysClkInt( )和sysAuxClkInt( )需要对TxIR(时钟中断标志寄存器)进行清零操作,否则无法进入下一周期的中断响应。
内存相关的就是如何使获得更大的内存资源,因为总共64KByte的SRAM,需要合理分配利用才能满足应用程序的需求。
以下列出一些可行的方法:
1 将RAM_LOW_ADRS的定义降低,也就是扩大数据段空间。
2 在满足要求的情况下减少ISR堆栈。
3 系统启动自动创建的任务tRoot占用堆栈较大,可以修改栈的大小,或者通过taskSpawn( )函数重新创建一个任务,可自主设置栈大小,自行结束tRoot,获得额外的可用内存。
4 精简BSP程序,删除无用的代码。
5 利用Tornado环境裁剪内核组件,获得最小的程序。
6 利用可作为通用SRAM来使用的16kB 以太网接口SRAM。
vxWorks系统本身不能分配这段不连续的空间,应用程序则可用灵活使用。
裁剪之后测试64K SRAM可空余30K以上的内存空间。
另外需要保证内存低端保留64字节,初始化时不被清零。
Config.h中定义如下:
#define RESERVED 64 /* for interrupt vector */
在中断向量重映射之前从Flash拷贝到SRAM,关键代码如下:
MEMMAP = 0x01; /* 用户Flash模式。
中断向量不重新映射,它位于Flash中。
*/
{
int i;
for(i=0;i<16;i++) /* 从Flash拷贝16字(64字节)到RAM */
{
*(UINT32*)(0x40000000+4*i) = *(UINT32*)(4*i);
}
}
MEMMAP = 0x02; /* 用户RAM模式。
中断向量被重新映射到静态RAM。
*/ 这样中断向量映射到RAM,比直接在Flash可以获得更快的中断响应速度(分别测试1000次,前者响应时间7.9us,后者8.1us)。
为了查看内存分配是否合理,可以通过如下命令
objdumparm –h [目标elf文件]
来查看text段,data段,bss段的数据大小,输出如下:
vxWorks_romResident: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0002c350 00000000 00000000 00000094 2**2
CONTENTS, ALLOC, LOAD, CODE
1 .data 00002610 40001000 0002c350 0002c3e8 2**3
CONTENTS, ALLOC, LOAD, DA TA
2 .bss 00001ba0 40003620 40003620 0002ea00 2**5
ALLOC
3 .debug_frame 00000b2c 00000000 00000000 0002ea00 2**2
CONTENTS, READONLY, DEBUGGING
以上是LPC2468移植vxWorks的难点或特殊之处的描述,其他通用的移植步骤就不一一详述。
最后根据多年的移植经验总结一下移植vxWorks的一般调试步骤:
1 先跟踪确定汇编到c程序入口的正确性。
2 Flash,RAM正确设置。
3 编写并调试目标板LED指示灯函数,作为下一步调试的状态信息。
4 先编写并调试不基于中断的串口输出函数,可以作为进一步调试的信息输出。
5 接着进行中断相关的移植。
6 下一步进行定时器相关的移植,调试系统时钟,如果需要也移植辅助时钟。
7 基于中断的串口驱动调试。
8 内存,时钟,中断,串口完成移植并测试通过就完成了精简的vxWorks系统移植。
9 如果需要网络功能,TFFS文件系统就在这基础上进一步调试。
切记,一开始如果能找到相近的BSP代码,很多移植工作就可以省略。
[参考文献]
《LPC2468器件用户手册》广州周立功单片机发展有限公司2007-02.。