汽车电子expert成长之路

本博客发布的个人原创精品----嵌入式系统技术文章,欢迎大家参考学习,并转发分享!

小试牛刀之S3C2440的winCE 5.0 BSP移植和开发学习总结

0
阅读(3512)
小试牛刀之S3C2440的winCE 5.0 BSP移植和开发学习总结
博文序
本文基于我之前在公司上班所写的工作总结和工作周报,但是以下大家所见到的这篇博文绝非是我在公司应付老板内容的简单移植,而是加入了我这段时间对S3C2440的winCE 5.0 BSP移植的诸多学习感悟和总结,希望能够对刚刚开始或者正准备学习和从事这方面工作的同志们有所帮助。
另外,由于种种原因现在我已经离开了原来的那家公司,在新的公司从事FPGA方面的工作,S3C2440的winCE 5.0 BSP移植已经不再是我工作的分内之事了,但是,通过之前在上一个公司20多天这方面的学习和努力工作,我已经着迷于其中,因此,以后我还会在工作终于继续这项工作,把S3C2440的winCE 5.0 BSP移植和学习进行到底。
鉴于以上,下面的博文里中难免会存在一些错误,还请大家不吝指出。另外,在以后的学习中我还将继续与大家分享我的学习感悟与总结。同样会以博文的形式与大家见面,希望同大家一同学习和进步~!
好了,如题,下面进入博客中文。
博客正文
1、BSP构建
本文使用BSP为mini2440提供的BSP+SDMK2440A三星官方提供BSP中Bootloader的整合,整合时需要更改目录下相应的DIRS和sources文件。
我更改好的BSP存放路径为:E:\WINCE500\PLATFORM\mini2440,可以直接使用,但是需要在PB中安装此BSP,若以前PB已经安装了mini2440的BSP,请先行卸载,否则,编译不一定成功!
本BSP所用工程路径为:E:\WINCE500\PBWorkspaces\MyBootloader
使用本文档所涉及的编译结果可在以下两个路径下找到:
① E:\WINCE500\PBWorkspaces\MyBootloader\RelDir\mini2440_ARMV4I_Release
② E:\WINCE500\PLATFORM\mini2440\target\ARMV4I\retail
实质上,PB在生成BSP的最后过程调用buildrel.Bat将最终编译、链接生成的结果从②拷贝至①中
2、Stlpldr移植说明
本本文使用工程目录下E:\WINCE500\PLATFORM\mini2440\Src\Bootloader\Stepldr存放的STEPLDR工程,即S3C2440A的Nboot,它的功能在于 初始化 CPU 相关的寄存器,关闭看门狗、中断,配置系统启动所需的 IO 口(包括调试回用到的 LED 和串口的相关寄存器设置),配置 PLL (这里主要注意板子外部输入晶振的不同, SMDK2440 使用的是 16MHz 晶振,而我们的板子使用的是 12MHz 晶振,相关寄存器为 UPLLCON MPLLCON ),初始化配置内存管理器(这里需要根据自己的硬件平台进行配置),接着处理 MMU 和电源管理。(注意以上操作均在 startup.s 中使用汇编完成!)
这里我所提供的stepldr已经更改以上关键点和目录下的utils.c文件并在代码中加入了相应的LED和串口跟踪调试信息(具体可查看我程序中相应的注释!)
以上移植工作 已经完成 LED 和串口跟踪调试(使用 UART0 )信息的输出,跟踪调试结果为该 nboot 已经完成 startup.c 中的 CPU 和外设初始化功能,进入 main.c 并能够准确读出 NAND Flash ID 信息(包括 K9F1208 K9F2G08x0A ),但是在进一步读取 Nand Flash Block 内容是死在 waitting to detect RB!
以下为 UART0 打印出来的调试信息:
starting Copy image from NAND flash to RAM......
Have entered the for loops!
Now,copying pages--
0x00000040
(LOAD_SIZE_PAGES + NAND_COPY_PAGE_OFFSET) =
0x00000240
nBlock =
0x00000002
This Nand Flash's ID is %d
0xecda1095
ENTERING NF_ReadPage,and begin NAND flash reading!
blockPage =
0x00000040
ENTERING void NF_Reset(void)
sending reset command to nana flash controller
waitting to detect RB!
have detected RB!
exitting void NF_Reset(void)
waitting to detect RB!
原因分析:现在程序所以Nand Flash操作相关函数为mini2440网站上下载的nboot里面的函数移植,其默认操作的Nand Flash为64M的K9F1208,而现在使用测试的板子为Micro2440,其上Nand Flash为2G的K9F2G08x0A,两片Flash的内部结构及相应的操作时不同的,具体可参考芯片手册!
K9F1208的特征为:
K9F2G08x0a的特征如下:
从以上截图可以看出, 两片 Flash 的内部 Block 数量不同,每页的大小也不一样,在操作时,读写前者只需 4cycles 而后者则需要 5cycles 。因此若选用后则,所有 BSP 中所有涉及 Nand Flash 操作的地方都需要改写!
3、Eboot移植说明
本文档使用的eboot代码位于路径:E:\WINCE500\PLATFORM\mini2440\Src\Bootloader\Eboot
完成移植工作:根据移植stepldr的经验,现已完成eboot的启动汇编代码的移植,程序能够正常进入C语言main函数(E:\WINCE500\PLATFORM\mini2440\Src\Bootloader\Eboot\main.c),并成功操作调试LED,这可以从main函数第一条语句
// Clear LEDs.
// hu enwei set as debug!
OEMWriteDebugLED(0, 0x6); //set leds 1100 MMLL M->灭 L->亮
及此时板子上LED的亮灭状态确定!
但是此时程序进入E:\WINCE500\PLATFORM\COMMON\SRC\COMMON\BOOT\BLCOMMON\blcommon.c中定义的BootloaderMain()函数,完成以下工作:
该目录的文件就是微软提供的eboot框架,最终被编译成库文件被调用!
以下是摘自CSDN的一篇博客,专门分析此目录下boot相关代码的:
if (!KernelRelocate (pTOC)) { HALT (BLERR_KERNELRELOCATE); }
而这个传入的参数却这样定义:ROMHDR * volatile const pTOC = (ROMHDR *)-1; 按照程序的内容来说,这个函数到这里一定是死循环了,可是事实上这个死循环不会得到执行,也就是pTOC = (ROMHDR *)-1并没有真正的起到作用。在pTOC第一次使用前检查了一下pTOC的值,结果如下:pTOC=0x8C04D694。也就是说pTOC在没有被改变之前就已经不再是-1了,而且pTOC是被定义成const的,也没有办法去改变,看样子就只能是编译器的过程中这个指针就已经被动了手脚。而查看eboot.map中该地址所对应的内容居然是bootpart.obj的内容。感觉是无从下手了,这样子让人太费解了。仔细比较eboot.exe和eboot.nb0后发现,eboot.exe通过romimage处理后长度增加了,而且结构上改变了许多,在原.eboot.exe后增加了一系列原来没有内容,pTOC的内容就是属于这部分内容中的一部分。由于牵涉到windowsCE的Image Chain结构,所以无法继续往下分析,这部分的内容就先跳过。以后再回头来看。
随后在 BootloaderMain中对调试界面进行初始化,由OEMDebugInit完成这个函数的实现是由具体的硬件决定的通常来说为串口的初始化,再次以后就通过该调试界面进行调试信息的发布。
然后在OEMPlatformInit()中对eboot所要用到的硬件资源进行初始化设备,通常这些会包含:存储设备(FLASH、硬盘等)、传输界面(以太网卡、USB-RNDIS、无线网卡、CF—LAN等等)、系统时钟,为下面将会进行的os镜像传输、os镜像存储、读取等等一系列动作做好准备。
做好准备以后就可以调用OEMPreDownload ()来进行传输OS的准备了,在这个函数中通常会实现一系列功能,诸如:设备的设置、存储设备的格式化、网卡IP的指定、等等。windowsCE所支持的标准操作则只是两个,一个是跳转、一个是下载、分别对应下载OS镜像和跳入OS的入口点,前面提到的那些功能都是自己的扩展实现。
下面我们分别来看这两个标准操作的分支:首先是下载的分支,在下载的分支中首先通过OEMReadData来获取在最先收到的标示位也就是被称为魔法数的数据,用以比较确认该传输的内容是否为windowsCE的镜像数据,随后继续进一步获取将接收的数据的效验和,待接收的镜像的数量,镜像起始地址、长度等信息,有了这些个信息,很自然地就是接收镜像了,随后检查数据的效验和。下一个镜像的信息的接收,如此往复循环直至所有的镜像信息接收完毕。
由于串口UART0的调试需要先初始化,而串口的初始化是在上面的OEMPlatformInit()函数里面调用其他函数实现的(主要是位E:\WINCE500\PLATFORM\mini2440\Src\Kernel\Oal下的debug.c)我也将相关的函数和头文件定义改写好了,但是调试发现,串口还是不能收到调试信息,因此我认为程序极可能死在了blcommon.c里面BootloaderMain()函数的第一步KernelRelocate (pTOC)里面了,还需要进一步调试验证!!!
4、烧写程序说明
由于ADS和PB5.0下生成的bin文件格式不同:
PB5.0下面编译生成的bin是一种二进制镜像格式,以片断(section)为单位组织数据,每个片断都包括一个头,头里指定了起始地址,长度,校验值。Platform Builder调用工具将WINCE内核所有文件以bin格式合并成一个文件,默认文件名为nk.bin。BootLoader又以同样的格式将nk.bin分解成多个文件放到RAM中。因此它的0000地址处存放的并非真实的程序代码指令,而是bin文件的格式说明,所以不能直接下载到板子的Nor Flash或者RAM上运行。
然而,值得注意的是PB编译过程后在生成.bin文件的同时已生成里同名的.nb0,.nb1的文件。nb0格式是原始的(RAW)二进制镜像,它不包括头,与ADS下编译生成的.bin文件格式一致,所以我们应该将内核下载到板子的Nor Flash或者RAM中运行。
这里由于我们采用的是现在到板子的Nor Flash中调试运行程序,而现在Nor Flash所使用的工具——J-link软件并不支持.nb0格式文件的烧写,因此我们需要将生成的eboot.nb0和STEPLDR.nb0文件重命名为eboot.bin和STEPLDR.bin
切忌:不能将PB生成的.bin文件直接下载到Nor Flash中运行,那样是看不见任何反应的!
5、Boot调试总结
Bootloader的调试由于其与硬件平台的依赖性和存储bootloader Flash资源以及CPU支持的限制,在十分熟悉自己所使用的硬件平台的基础上,仔细阅读CPU和板子硬件的datasheet的基础上,还需要对CPU(ARM)的汇编指令有一定的了解和掌握。
在调试的最初阶段,点亮LED和使用其串口是调试的关键所在,在整个bootloader的调试阶段,LED和串口的使用都是极为关键和重要的。
写在最后
ARM9的WINCE BSP移植并不是简单的“移植”那么简单,需要具备一定的知识基础,根据我这段时间从事这方面工作和学习的体会,简单列举一些基础知识以供大家参考:
1、一定的嵌入式硬件基础。
包括能够看懂一般的电路原理图,懂得常用MCU外设的硬件电路工作原理,对MCU的存储器管理及IO功能扩张有所了解和熟悉,特别是ARM体系的MCU。
2、一定的C语言和数据结构基础。
C语言在BSP开发过程中起着承上启下的功能,汇编完成的基本CPU工作寄存器、外设的初始化,MMU,堆栈的设置,电源管理等基本工作后,C语言还需要进行大量的Boot后续工作,包括OEM层的实现,串口调试,内核引导,FLASH操作,文件系统初始化等非常重要的工作。至于数据结构,其在WINCE甚至是Linux,ucOS等任何一个操作系统里面都是至关重要的——这样说吧,你能够在数据结构那门课里面看到的甚至很多你没有见过的数据结构都会在操作系统里面用到。不过,话又说回来,wince的BSP里面里面用的最多的还是指针、链表和结构体,所以需要特别注意以上的结构体。
3、对ARM体系十分熟悉。
包括ARM体系结构的存储器管理,中断控制器,各种外设,以及汇编ARM和thumb指令。其中尤为重要的是ARM的内存管理,寄存器操作,中断控制及汇编指令的掌握,至于外设,GPIO和UART是必须掌握的,否则你在Nboot和Eboot的调试之初会寸步难行的。
4、对ARM的编译软件的熟悉
ADS1.2和realview 3.x至少其中之一吧,这样不仅有利于你单独开发nboot,同样有利于你在PB下进行的其他BSP移植工作。当然,如果你是搞软件出生的,能够掌握一些其中的软件编译原理,那是最好不过的了,像BSP中的*.makefile,source,dir,*.bid,*.reg等文件的编写和阅读,*.dll,*.lib的生成和应用都是与编译原理相关。
好了,今天就写到这里,以后学习了更多再总结与大家分享。
胡恩伟
湖北·武汉
写于2010年8月18日
Baidu
map