Chinaunix首页 | 论坛 | 博客
  • 博客访问: 212669
  • 博文数量: 30
  • 博客积分: 1308
  • 博客等级: 中尉
  • 技术积分: 279
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-20 22:12
文章分类

全部博文(30)

文章存档

2010年(1)

2008年(2)

2007年(8)

2006年(19)

分类: LINUX

2006-11-08 10:45:55

U-BOOT在PowerPC860上的移植

[转载请注明出处,未经作者同意,严禁用于商业用途]
作者联系方式:patrick_zhg@hotmail.com

PPCBOOT/U-BOOT简介
ppcboot的前身是8XXROM和FADSROM,其最高版本为2.0,版本2.0之后称为U-BOOT。本文结合u-boot-0.2.0来详细叙述移植的整个过程。u-boot-0.2.0支持BOOTP,TFTP,SERIAL代码下载;支持NetBSD,Linux,Vxworks和QNX;支持Alpha, ARM, Intel x86, IA64, MIPS, MIPS, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit等目标CPU架构。详细的说明可以参见U-BOOT的README文件。本文移植的目标板对象是参照FADS板设计的低成本开发板,主要用于网络通信控制。

U-BOOT源代码分析
首先来分析一下U-BOOT的源代码分布,然后再做分析。可惜不能贴图,不然会直观很多,下面只好一一介绍了。

1.头文件
头文件位于源码树下的include/下,其中各种主板的配置文件位于/include/configs/文件夹中,比如FADS860T主板的配置文件为/include/configs/FADS860T.h;目录/include/asm-ppc包括了一些比较底层的头文件,编译时会根据不同的配置与/include/configs/asm建立一个符号链接。

2.与目标板相关的代码
U-BOOT支持大多数比较常见的目标板,比如MOTOROLA的FADS板,一般来说,自己设计的主板和这些主板都是大同小异,差别不会太大。源代码树中board/下的每个文件夹对应一个或几个主板,例如,/board/fads目录对应的就是FADS板的源代码,主板上一些资源的初始化代码就在这个文件夹中(例如FLASH、SDRAM等)。

3.与CPU相关的代码
u-boot-0.2.0只支持PowerPC系列的主板,与CPU相关的代码位于源代码树下的CPU/下的各个目录中,例如ppc855、ppc860的代码就位于/cpu/mpc8xx/文件夹中。其中start.S是U-BOOT的入口代码,由汇编语言实现,是整个程序的入口。相应的,目录/cpu/mpc824x/对应的就是824x系列CPU的相关代码。

4.公共代码
除了与主板,CPU特性相关的代码外,剩下最主要的就是共用代码,位于/common/目录下面,U-BOOT的命令解析代码/common/command.c;U-BOOT环境变量处理代码environment.c等都位于该目录下。另外,PowerPC系列的主板初始化代码也是公用的,位于/lib_ppc/board.c中,在完成CPU的初始化之后,程序会跳到该文件执行主板的初始工作,与主板相关代码的执行都是在该文件中调用。

5.网络传输
网络传输代码位于/net/目录下面,arp.c ,bootp.c,eth.c,tftp.c等代码都在这里,以太网初始化、BOOTP和TFTP等功能的实现也是由该目录下的代码完成。

6.Makefile文件
Makefile文件位于U-BOOT的根目录下,是整个编译的控制主文件,后面小节会讲到如何修改该文件以实现针对自己主板的编译控制。

7.关键的驱动程序代码
U-BOOT中几个比较关键的外设驱动包括串口的初始化,以太网口驱动,SDRAM初始化,FLASH初始化,以FADS板为例,分别位于:
串口: /cpu/mpc8xx/serial.c
SDRAM: /board/fads/fads.c
FLASH: /board/fads/flash.c
ETHERNET: /cpu/mpc8xx/scc.c
FAST ETHERNET: /cpu/mpc8xx/fec.c
在移植的过程中这些都是需要修改的代码。

移植步骤
初步了解了U-BOOT的代码之后,下面开始具体的U-BOOT移植过程!

1.安装交叉编译环境
从下载ELDK(Embedded Linux Development Kit),这是一个针对PowerPC的交叉编译工具,体积比较庞大,下载后参考README进行安装,安装成功后需设置系统路径,或者在 /root/.bash_profile下设置path。完成后,如果在shell提示符(#)下输入: ppc_8xx-gcc –v 有版本信息输出,即表明已建立交叉编译环境,

2.编译测试
在主机上进入U-BOOT的目录中,#cd /opt/u-boot-0.2.0 , 在进行编译之前设置目标板配置,U-BOOT支持的主板种类在其目录中的README中可以查到,以下操作针对FADS860T主板:

#make FADS860T_config
如果屏幕出现两行信息:
rm –f include/config.h include/config.mk
Configuring for FADS860T board…
表明配置成功,然后运行命令:

#make
进行编译,如果编译能正常执行,并且最终产生目标代码u-boot.srec u-boot.bin u-boot,说明U-BOOT和交叉编译环境都可以正常使用。下面开始针对自己主板的U-BOOT移植。

3.U-BOOT启动过程
从哪里入手呢?先了解U-BOOT的启动过程,这样就能知道从哪里入手了!
CPU入口函数(FLASH中运行): /cpu/mpc8xx/start.S
CPU初始化(FLASH中运行): /cpu/mpc8xx/cpu_init.c
主板初始化(FLASH中运行): /lib_ppc/board.c
串口初始化: /cpu/mpc8xx/serial.c
sdram初始化: /board/fads/fads.c
主板初始化(RAM中运行):  /lib_ppc/board.c
初始化过程是这样的:首先,U-BOOT程序在Flash中运行,执行必要的代码,如CPU初始化、串口初始化和内存初始化(此时仅仅是初始化了部分内存,保证u-boot的程序能在内存中装的下即可)。然后,程序拷贝u-boot到内存中,并跳转到内存执行,并且再执行一次的初始化,这次除了最基本的初始化如CPU初始化、串口初始化和内存初始化(整个内存),还有网络和其它外设的初始化。

4.添加自己的配置文件
参照Makefile文件,选择一个与自己目标板最为相近的一个主板,因为根据FADS860T板设计的,所以选择FADS860T板,在Makefile文件中找到如下代码:
FADS860T_config: unconfig
@./mkconfig $(@:_config=) ppc mpc8xx fads
在该配置后添加如下两行:
NEW860T_config: unconfig
@./mkconfig $(@:_config=) ppc mpc8xx fads
其中ppc是CPU的架构, mpc8xx是CPU对应的目录,fads是主板对应的目录,也可以新建一个目录,然后指向新的目录。
Makefile修改完毕还要在/include/configs/下添加对应的头文件,NEW860T_config对应的头文件是NEW860T.h,也可以将FADS860T拷贝一份,命名为NEW860T.h:

#cd /opt/u-boot-0.2.0/include/configs
#cp FADS860T.h NEW860T.h

完成之后,测试一下配置:
#make NEW860T_config
#make
如果能编译成功!说明这种配置可行,当然这时编译出来的目标代码和FADS860T是一模一样的。还需要根据自己的目标板进行修改。

5.目标板系统参数配置
目标板系统参数在/include/configs/NEW860T.h中配置,如果对自己的主板有足够的了解,做简单修改就可以了(因参照FADS板做的设计,在修改时我们参照了FADS板的设置),下面是针对我们开发板修改的参数以及一些比较关键的配置说明:

#define CONFIG_MPC860 1 (这个是必须的)

#define CONFIG_MPC860T 1 (MPC860的家族有好几种CPU,他们之间有一些差别)

#define CONFIG_FADS 1
(FADS用的是SDRAM,如果把这个也定义上,到时把相关代码和自己的主板对应起来也可以用了)

#define CONFIG_8xx_CONS_SMC1 1 (用SMC1当串口使用,作为CONSOLE)

#define CONFIG_BAUDRATE 115200
(串口的波特率,移植到主板后主机系统的超级终端设置要和该参数对应,不然会有一堆乱码出现)

#define MPC8XX_FACT 1 (晶阵倍频,FADS是12,我们的主板设为1)

#define MPC8XX_XIN 50000000 /* 4 MHz in */
(晶阵频率,FADS860T是4MHz的,我们的主板是50MHz)

#define MPC8XX_HZ ((MPC8XX_XIN) * (MPC8XX_FACT)) (工作频率)

#undef CONFIG_WATCHDOG /* watchdog disabled */ (WATCHDOG先关掉)

#define CFG_SDRAM_BASE 0x00000000 (SDRAM起始地址,不能错!)

#define CFG_FLASH_BASE 0x02800000
(FLASH的起始地址,分配的基地址为0x2800000)

#define CFG_FLASH_SIZE ((uint)(2 * 1024 * 1024)) (FLASH的大小)

#define CFG_ENV_IS_IN_FLASH 1 (U-BOOT的环境变量参数保存在FLASH中)

#define CFG_ENV_OFFSET 0x1fc000
FLASH有TOP-BOOT-SECTOR和BOTTOM-BOOT-SECTOR之分,我们用的是TOP-BOOT-SECTOR,U-BOOT的环境变量存在FLASH的最后一个SECTOR中,这是它在FLASH中的偏移地址。

#define CFG_ENV_SIZE 0x4000 (U-BOOT环境变量所占空间大小)

#define CFG_ENV_SECT_SIZE 0x4000 /*see README–env sector total size */
U-BOOT环境变量所在FLASH SECTOR的空间大小。

#define CFG_IMMR 0xff000000
找个没有用到的地址空间分配,这是内部寄存器的基地址,保证这个基地址要有64K大小的访问空间,这个地址范围不能和其它外设的地址范围有冲突
还有一些寄存器的初始值设置,一般不用做修改,但和内存控制有关的寄存器需要根据自己的主板特性进行修改!主要涉及以下寄存器:
OR0—OR7 BR0-BR7 MAMR/MBMR等。
其中,OR、BR寄存器的设置是与目标系统的地址划分相对应的,可以通过编程来确定每一个片选CS0—CS7所对应的地址空间。

通过以上修改,目标板的配置文件也完成的差不多了,下面进行代码修改!

6.串口初始化
因为参照FADS板进行的设计,CPU的入口函数/cpu/mpc8xx/start.S未做修改,程序在进行完CPU的上电初始化之后就跳入/cpu/mpc8xx/cpu_init.c进行一些寄存器的初始化。CPU初始化完成后调用/lib_ppc/board.c中的board_init_r(),进行串口初始化,因为串口正常工作之后就可以从超级终端上看到调试信息,可以大大方便调试。
串口初始化代码位于/cpu/mpc8xx/serial.c,FADS板上有一个CPLD的逻辑,我们的目标板上没有,所以对应于BCSR的设置改为自己相应管脚配置,其它未做修改。
另外,串口初始化完成之后要调用check_cpu(), check_board(), 在check_board()中FADS板会有一些访问BCSR地址的代码,也需要屏蔽掉。

7.SDRAM初始化
上面的工作全部是在FLASH中进行的,程序的限制很多,U-BOOT仅仅是在MPC860T内部的一小片RAM中开了一个小小的堆栈用于程序使用,不能定义大变量。接下来,程序进行32MB SDRAM的初始化。
SDRAM的初始化代码位于/board/fads/fads.c中,对应不同的SDRAM,UPM表是不一样的。UPM表说白了就是一些总线时序抽象为十六进制数字的产物,用数字来表示SDRAM的读写,刷新等时序。UPM表通常可以根据内存资料或者直接向设计开发板的硬件工程师讨教,密密麻麻一堆数字。另外,还有一个SDRAM上电的初始化时序,叫SDRAM POWERUP UPM表。 这两个UPM都需要改动,修改时要非常细心。
SDRAM的初始化是/lib_ppc/board.c中的board_init_f()调用的,入口为intidram()。

8.FLASH驱动
进行完SDRAM的初始化之后,U-BOOT会将代码拷贝到SDRAM中,在SDRAM中再次对CPU和CONSOLE进行一次初始化(参阅函数/lib_ppc/board.c中的board_init_r()函数),这部分代码不用做修改。但FLASH的初始化代码需要做修改。
FLASH的驱动位于/board/fads/flash.c,涉及FLASH型号的探测,擦除,编程,扇区保护和取消保护等操作。其中有一个公共结构体flash_info_t flash_info[CFG_MAX_FLASH_BANKS]用于保存FLASH的参数。需要根据目标系统所用的FLASH型号进行修改,需要提醒的是FLASH的数据总线宽度,要正确区分是8bit,16bit还是32bit,其它代码按照FLASH的编程手册修改即可。
建议把代码中FLASH的探测去掉,因为在生产中,由于采购渠道等种种原因,往往会以同类型的其它FLASH代替,如果此时再回头修改Flash部分代码,非常不合时宜。

9.FEC快速以太网初始化
FEC快速以太网的初始化也是在/lib_ppc/board.c中的board_init_r()函数中完成的,调用eth_initialize(),该函数位于/net/eth.c中,其中调用fec_initialize()注册快速以太网设备FEC。
FEC的驱动程序位于/cpu/mpc8xx/fec.c文件中,我们目标系统用的PHY为LX970A,除了将FADS中涉及到BCSR控制管脚的地方改为目标系统对应的管脚,未做其它修改。

至此,代码修改基本完成。最后,比如打开调试信息等在/include/common.h中定义
可根据实际需要进行设置,也可以在比较关注的地方添加调试信息。

编译&调试
1.编译
代码修改完毕,开始进行编译!编译之前要根据目标系统程序入口修改程序代码地址(位于/board/fads/config.mk中),我们的目标系统和FADS一样为0x2800000,没有进行修改。然后在U-BOOT的目录下运行如下命令:
#make NEW860T_config
#make
如果编译中遇到问题,按照打印信息做修改,然后再编译。

2.目标代码烧写
对于生成的三个目标文件,u-boot.srec是MOTOROLA S-Recoder格式的,u-boot.bin是二进制的,u-boot是ELF(Executable and Link Format)二进制格式的。
用WindRiver 的vision probe BDM仿真器或者其它的仿真器,将目标文件烧写到FLASH中的偏移地址0x100处。

3.调试
调试过程涉及到BDM仿真器的单步跟踪、察看寄存器等操作,需要熟悉仿真环境。调试中的难题主要出现在console口没有输出调试信息之前,因为一旦console可以输出调试信息了,所有的问题都变的简单很多,可以通过添加printf()语句来查看想观察的信息。在console没有输出信息前,可以通过在板子上焊接发光二极管等方式进行判断,以确定程序是在何处发生问题。
调试的过程可划分为以下三个阶段:
 a) 程序代码可以在目标系统上运行
 b) console可以输出调试信息
 c) 可以在SDRAM中运行了

U-BOOT命令
U-BOOT运行稳定后,可以用它的内部命令来查看目标系统的信息,设置环境变量等,这里就几个比较常用的命令做简单叙述,详细说明可参考U-BOOT帮助文档。

help/?帮助命令
用于查询U-BOOT支持的命令,并列出简单说明,help和?是同一命令。

bdinfo查看目标系统参数和变量
查看目标板的硬件配置,各种变量参数

setenv设置环境变量
比较常用的有:
setenv ipaddr *.*.*.*
setenv serverip *.*.*.*
setenv gatewayip *.*.*.*
setenv ethaddr *.*.*.*.*.*

printenv 查看环境变量

saveenv 保存设置的环境变量到FLASH

mw md mm -内存的写,查看,修改

flinfo 查看flash的信息

erase【startaddr endaddr】 擦除flash,只能进行一个或多个完整sector的擦

cp 【sourceaddr targetaddr size】 内存复制,可以在RAM和FLASH中交换数据

imi 【startaddr】 查看内核映象文件

bootm 【startaddr】 从某个地址启动内核

tftpboot 【startaddr imagename】 通过tftp从主机系统下载内核映象文件

reset 系统复位


小结
u-boot的移植过程基本如上所述,不同的目标系统会出现不同的问题,但只要抓住移植过程的主线,遇到问题时详细分析可能的原因,通过网上的讨论区、别人的移植经验,还是比较容易完成的。移植的过程基本上如下:

1:获取源代码
2:了解源代码分布情况
3:掌握关键代码
4:添加新的配置文件
5:根据目标板设置新的配置
6:编译&调试


在移植过程中参照了internet上的大量文档和说明,对移植过程有很大的帮助。遇到问题时先用google狗几下,可以从一些论坛上、别人的移植经验中获得不少启发,一般来说国内的论坛问的多,解决问题的少,建议直接用英文google。以下是一些很好的入门文档:


阅读(4843) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

woshihaoge2016-06-14 20:43:18

推荐第三方软件烧写uboot等bootloader,尤其推荐yaJFPb http://www.zhefar.com/services-ee.htm#JTAG_Flash
 比CodeWarrior更好用!无需初始化时钟/内存/内部寄存器。焊接没有问题,基本上就可以对Flash编程烧写。
 即使复位配置字(RCW, Reset Configuration Word)有错,只要JTAG可用,就可以连上。
 自动计算编程区域相应的扇区/块并可以自动在编程前擦除。

woshihaoge2016-06-14 20:43:16

推荐第三方软件烧写uboot等bootloader,尤其推荐yaJFPb http://www.zhefar.com/services-ee.htm#JTAG_Flash
 比CodeWarrior更好用!无需初始化时钟/内存/内部寄存器。焊接没有问题,基本上就可以对Flash编程烧写。
 即使复位配置字(RCW, Reset Configuration Word)有错,只要JTAG可用,就可以连上。
 自动计算编程区域相应的扇区/块并可以自动在编程前擦除。