Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1484975
  • 博文数量: 610
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
文章分类

全部博文(610)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(297)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类: LINUX

2008-04-21 19:28:38



1 U-BOOT简介
  U-BOOT是由德国的工程师Wolfgang Denk从8XXROM代码发展而来的,它支持很多处理器,比如PowerPC、ARM、MIPS和x86。目前,U-BOOT源代码在sourceforge网站的社区服务器中,Internet上有一群自由开发人员对其进行维护和开发,它的项目主页是
[url=http://sourceforge.net/projects/U-BOOT]http://sourceforge.net/projects/U-BOOT[/url]
。U-BOOT的最新版本源代码可以在Sourceforge的CVS服务器中匿名获得。
#cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/U-BOOT login
#cvs -z6 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/U-BOOT \ co -P modulename
1.1 U-BOOT源代码目录结构
◆ board:和一些已有开发板有关的文件,比如Makefile和u-boot.lds等都和具体开发板的硬件和地址分配有关。
◆ common:与体系结构无关的文件,实现各种命令的C文件。
◆ cpu:CPU相关文件,其中的子目录都是以U-BOOT所支持的CPU为名,比如有子目录arm926ejs、mips、mpc8260和nios等,每个特定的子目录中都包括cpu.c和interrupt.c,start.S。其中cpu.c初始化CPU、设置指令Cache和数据Cache等;interrupt.c设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、预取中止和未定义指令等;start.S是U-BOOT启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为进入C程序奠定基础。
◆ disk:disk驱动的分区处理代码。
◆ doc:文档。
◆ drivers:通用设备驱动程序,比如各种网卡、支持CFI的Flash、串口和USB总线等。
◆fs:支持文件系统的文件,U-BOOT现在支持cramfs、fat、fdos、jffs2和registerfs。
◆ include:头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。
◆ net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
◆ lib_arm:与ARM体系结构相关的代码。
◆ tools:创建S-Record格式文件 和U-BOOT images的工具。
1.2 引导模式 : 1. bootstrap或download
1.6 关于u-boot的移植如下,由于u-boot的软件设计体系非常清晰,它的移植工作并不复杂,
相信各位的代码阅读功力不错的话,参照如下就可以完成。
If the system board that you have is not listed, then you will need
to port U-Boot to your hardware platform. To do this, follow these
steps:
1. Add a new configuration option for your board to the toplevel
"Makefile" and to the "MAKEALL" script, using the existing
entries as examples. Note that here and at many other places
boards and other names are listed in alphabetical sort order. Please
keep this order.
2. Create a new directory to hold your board specific code. Add any
files you need. In your board directory, you will need at least
the "Makefile", a ".c", "flash.c" and "u-boot.lds".
3. Create a new configuration file "include/configs/.h" for
your board
4. If you're porting U-Boot to a new CPU, then also create a new
directory to hold your CPU specific code. Add any files you need.
5. Run "make _config" with your new name.
6. Type "make", and you should get a working "u-boot.srec" file
7. Debug and solve any problems that might arise.
[Of course, this last step is much harder than it sounds.]
为了使u-boot-1.0.0支持新的开发板,一种简便的做法是在u-boot已经支持的开发板中参考选择一种较接近板的进行修改,
幸运的是在u-boot-1.0.0中已经有了at91rm9200的支持。
1.7 与at91rm9200相关的u-boot代码
在include/configs/at91rm9200dk.h 它包括开发板的CPU、系统时钟、RAM、Flash系统及其它相关的配置信息。
在include/asm-arm/AT91RM9200.h, 该文件描述了H9200寄存器的结构及若干宏定义。
具体内容要参考相关处理器手册。
在cpu/at91rm9200/目录下别为cpu.c、interrupts.c和serial.c等文件.
在board/at91rm9200dk/目录下分别为flash.c、at91rm9200dk.c, config.mk, Makefile,u-boot.lds
flash.c : u-boot读、写和删除Flash设备的源代码文件。由于不同开发板中Flash存储器的种类各不相同,
所以,修改flash.c时需参考相应的Flash芯片手册。它包括如下几个函数:
unsigned long flash_init (void ),Flash初始化;
void flash_print_info (flash_info_t *info),打印Flash信息;
int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除;
volatile static int write_dword (flash_info_t *info, ulong dest, ulong data),Flash写入;
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),从内存复制数据。
u-boot.lds :linker scripte, 设置u-boot中各个目标文件的连接地址.
网口设备控制程序
在drivers/目录中网口设备控制程序cs8900, bcm570x等, 还可以添加其他网卡驱动
int eth_init (bd_t *bd) : 初始化网络设备;
void eth_halt (void) : 关闭网络设备;
int eth_send (volatile void *packet,int len) : 发送数据包;
int eth_rx (void) : 接收数据包。
Makefile
在u-boot-1.0.0/Makefile中
at91rm9200dk_config : unconfig
./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk
1.8 编译u-boot
make at91rm9200_config
Configuring for at91rm9200 board...
make all
生成三个文件:u-boot.bin, u-boot, u-boot.srec
u-boot.bin is a raw binary image
u-boot is an image in ELF binary format
u-boot.srec is in Motorola S-Record format (objcopy -O srec -R.note -R.comment -S [inputfile] [outfile]
以上工作完成我们可以通过串口将u-boot.bin下载到主板的SDRAM中,它会自动执行, 并出现uboot>
这里我们可以通过串口把boot.bin, u-boot.bin.gz下载到主板,再用u-boot的提供的写flash功能分别
把boot.bin, u-boot.bin.gz写入到flash中,完成以上工作后,对主板跳线选择片外启动,
板子复位后会自动启动u-boot.


简单说说U-boot的修改
uboot是一个通用的免费开放源码的boot程序,支持很多的处理器。以下是现在网上下载一个u-boot-1.1.1版本,用于at91rm9200系统的修改的例子。最后在redhat8.0上,用gcc2.95编译通过。
在网上下载了uboot-1.1.1版本。要用于自己的at91rm9200的系统,这个系统的情况是:
SDRAM: 32Mbytes NCS1
FLASH: 8Mbytes NCS0
涉及到的文件有四个:
common.h
flash.c
flash.h
”./board/at91rm9200dk/config.mk”
以下简单的说说。
一、首先读读uboot自带的readme文件,了解了一个大概。
二、看看common.h,这个文件定义了一些基本的东西,并包含了一些必要的头文件。再看看flash.h,
这个文件里面定义了flash_info_t为一个struct。包含了flash的一些属性定义。
并且定义了所有的flash的属性,其中,AMD的有:AMD_ID_LV320B,定义为 “#define AMD_ID_LV320B 0x22F922F9”。
三、对于 “./borad/at91rm9200dk/flash.c”的修改,有以下的方面:“void flash_identification(flash_info_t *info)”
这个函数的目的是确认flash的型号。注意的是,这个函数里面有一些宏定义,直接读写了flash。并获得ID号。
四、修改:”./board/at91rm9200dk/config.mk”为TEXT_BASE=0x21f80000 为TEXT_BASE=0x21f00000
(当然,你应该根据自己的板子来修改,和一级boot的定义的一致即可)。
五、再修改”./include/configs/at91rm9200dk.h”为修改flash和SDRAM的大小。
六、另外一个要修改的文件是:./borad/at91rm9200dk/flash.c。这个文件修改的部分比较的多。
1. 首先是OrgDef的定义,加上目前的flash。
2. 接下来,修改”#define FLASH_BANK_SIZE 0x200000”为自己flash的容量
3. 在修改函数flash_identification(flash_info_t * info)里面的打印信息,这部分将在u-boot启动的时候显示。
4. 然后修改函数flash_init(void)里面对一些变量的赋值。
5. 最后修改的是函数flash_print_info(flash_info_t * info)里面实际打印的函数信息。
6. 还有一个函数需要修改,就是:“flash_erase”,这个函数要检测先前知道的flash类型是否匹配,否则,直接就返回了。把这里给注释掉。
七、接下来看看SDRAM的修改。这个里面对于“SIZE”的定义都是基于字节计算的。
只要改”. /include/configs/at91rm9200dk.h”里面的“#define PHYS_SDRAM_SIZE 0X200000”就可以了。注意,SIZE是以字节为单位的。
八、还有一个地方要注意,就是按照目前的设定,一级boot把u_boot加载到了SDRAM的空间为:21F00000 -> 21F16B10,
这恰好是SDRAM的高端部分。另外,BSS为21F1AE34。
九、编译后,可以写入flash了。
1. 压缩这个u-boot.bin“gzip –c u-boot.bin > u-boot.gz”压缩后的文件大小为:43Kbytes
2. 接着把boot.bin和u-boot.gz烧到flash里面去。Boot.bin大约11kBytes,在flash的0x1000 0000 ~ 0x1000 3fff


在AT91RM9200上移植u-boot
================== 准备工作=================
1.阅读at91rm9200 官方文档有关“引导程序”的章节
对at91rm9200的启动流程有个大概的了解。
at91rm9200引导流程图
Device Setup
|
|
Boot SPI DataFlash Boot --> Download from DataFlash --> run
|
|
TWI EEPROM Boot --> Download from EEPROM --> run
|
|
Parallel Boot --> Download from 8-bit Device -->run
|
|    Xmodem protocol
|    |---DBGU Serial Download ---------------------> run
|____|
|     DFU protocol
|-----USB download -----------------------> run
at91rm9200有片内引导和片外引导 2 种启动方式,由一根跳线控制。
1>    片外引导  执行烧在flash上的引导程序。
2>    片内引导  at91rm9200内部本身有128k的片内rom,其固化了一个bootloader和uploader,片内引导时启动uploader,uploader开启xmodem协议,等待用户上传程序,
上传的程序将载入片内SRAM,重映射,然后pc跳转到片内SRAM执行上传的用户程序。
注:片内SRAM只有16k,除去3-4k片内启动程序的占用的部分数据空间,因此下载的程序大小限制在12k内。
2.开发板硬件配置
这块开发板硬件           ATMEL推荐硬件
SDRAM   8MB             32MB
Flash      1MB             8MB      
注:Flash芯片也不一样,意味着驱动要重写。
3.移植思路
官方at91rm9200DK u-boot Flash Programming Solutions文档提供的解决方案如下。
开发板flash上没有引导程序,于是只能用片内引导方式,载入一个12k以内的小程序到内部SRAM运行,而这个小程序初始化SDRAM后,再把u-boot下载到SDRAM运行(u-boot大于12k),pc跳到SDRAM的u-boot位置运行u-boot,
u-boot启动后再用u-boot自己的flash烧写命令把自己烧到flash去,以后就可以片外flash启动了。
官方文档中并不是直接烧u-boot.bin,而是烧入了boot.bin和u-boot.gz2个文件。
原因后面将阐述。
===================移植====================
1.loader.bin的移植
官方提供的loader.bin在SRAM启动会又启动了xmodem接收u-boot,但是
xmodem接收数据出错。
查看其源码,发现它使用了固化的rom中的服务接口函数,没看出哪里出问题。
于是准备自己写loader.bin,在at91rm9200提供的开发包中有个AT91RM9200-GettingStarted-ADS1_2-1_1.zip,用的是Arm Developer Suite 1.2编译器,就是一个简单的hello world程序,试一试可以运行。
(注意:ADS编译的程序,定义变量要在main的开始出,后面定义将导致编译出错)
用AT91RM9200-GettingStarted-ADS1_2-1_1.zip作为起点开始写loader.bin
lader.bin主要有3个功能,初始化SDRAM,启动xmodem接收u-boot并写到SDRAM中,pc跳转到SDRAM运行。
AT91RM9200-GettingStarted-ADS1_2-1_1里面已经有了SDRAM和其他一次初始化,在init_ram.c中。
xmodem的实现
   只需要接收部分,发送部分用win下的”超级终端”等工具就可。
    先找来协议文档,熟悉协议,看看现有的xmodem协议源码。协议本身并不复杂,只是它的握手部分实现有点技巧。
    接收端要不停的发送字符“C”到串口(注意xmodem有3个版本,而超级终端对应的是xmodem-crc16),发送端收到“C”后发送数据SOH和第一个数据包。
接收端检测到SOH后停止发送“C”并开始处理数据。官方的loader启动了一个时间服务,每隔1s发送一个“C”,在这个我使用了偷懒的算法。
    while(Getchar()!=AT91C_XMODEM_SOH)
    {
        if (0xFFFF==++n )
        {
            SendChar(AT91C_XMODEM_CRCCHR);
            n=0;
        }
    }
Getchar()和GetWaitchar()是添加的,GetWaitchar等待直到从串口接收到数据。
显然不能用在上面的算法中,要导致忙等的。所以改了个Getchar()只用在这里。
握手解决了,后面的处理都没什么问题。
写SDRAM
    unsigned char *pSdram = (unsigned char *)AT91C_UBOOT_BASE_ADDRESS;
    for ( n = 0; n
PC跳转
    添加一个文件jump.S到工程
;------------------------------------------------------------------------------
;-      ATMEL Microcontroller Software Support  -   ROUSSET -
;------------------------------------------------------------------------------
;- File source          : remap.s
;- Librarian            : Not applicable
;- Translator           :
;-
;- Treatment            : Execute the remap and branch to 0
;-
;- 03/10/01   HI         : Creation
;------------------------------------------------------------------------------
                AREA    reset, CODE, READONLY
                EXPORT  Jump
Jump
        mov pc, r0               
               END
;---------------------------------------------------------------------------------
在main中使用下面的函数跳转
Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS);
loader的调试过程
    xmodem部分可以传一个调试文件,传进去后全部send回串口,看返回的信息就可以判断是否正常工作。
    写SDRAM,依然是写入后再读出来看看是否一致,在这里卡了很久,发现每隔2个地址就不能使用,后来发现是SDRAM没有初始化,也就是init_ram.c中的InitSDRAM()无效,重写后正常。
    Jump测试,得传入一个可以运行的程序到内存才能判断,用先前编译好的1.1.4的u-boot传入,没反应,可能是jump不对,也可能是u-boot不对,毕竟u-boot还未经过任何修改。灵光一闪,我换成u-boot-1.0.0试一试,出现u-boot的提示符了,?   也就是说jump没问题。
2.u-boot的移植
u-boot的编译需要ELDK(Embedded Linux Development Kit)
ELDK是linux下的交叉开发环境,所以需要安装linux,在这里使用的是虚拟机vmware安装linux(red hat 9.0),并安装了vmware tools,方便和windows交换数据。
Linux版本选择以及安装ELDK参见“The DENX U-Boot and Linux Guide (DULG) for TQM8xxL”
这里下载安装的是arm-2005-03-06.iso
注意正确设置ELDK的环境变量,要不编译会出错。
在编译u-boot前先仔细阅读README文档
at91rm9200已经被u-boot支持
编译如下
#cd u-boot.x.x.x       (x.x.x代表版本号)
#make at91rm9200dk_config
#make all
在map那里会很慢,我的AMD64 3000+,虚拟机里编译u-boot要3分钟?
u-boot版本选择
    从1.1.2开始,u-boot有初始化SDRAM并拷贝自己到SDRAM运行的代码,而之前的版本就没有这个功能,官方文档提供的解决方案是针对1.1.2之前的版本。事实上官方开发包中代的u-boot是0.3.1?。
在经过我的测试后,发现直接编译出来的u-boot1.0.0可以运行,而1.1.4没反应。
看来不一定最新的就是最好的。所以选择u-boot1.0.0移植。
u-boot修改
    u-boot同样是对ATMEL推荐配子写的,所以需要修改。
修改
Board/at91rm9200dk/config.mk
TEXT_BASE = 0x21f00000
改为
TEXT_BASE = 0x20700000 (u-boot将被载入SDRAM的高端部分)
修改
include/configs/at91rm9200dk.h
#define PHYS_SDRAM_SIZE 0x2000000  /* 32 megs */
改为
#define PHYS_SDRAM_SIZE 0x800000  /* 8 MB */
#define PHYS_FLASH_SIZE            0x200000  /* 2 megs main flash */
改为
#define PHYS_FLASH_SIZE            0x100000  /* 1MB main flash */
还有一个要修改的地方是Board/at91rm9200dk/flash.c
参见自己的flash芯片datasheet,修改驱动。
注意保持函数接口的一致性。其中外部会调用的几个函数是
unsigned long flash_init (void)
void flash_print_info  (flash_info_t *info)
int    flash_erase (flash_info_t *info, int s_first, int s_last)
int write_buff (flash_info_t *info, uchar *source, ulong Base, ulong nbytes)
只要保证这几个函数的接口一致性,其实现方法不一定要参照原来的模式。
flash_info_t *info其实不用也可以的。
还有就是flash芯片的自动识别函数去掉为好,在生产过程中很有可能采用同类型的其它FLASH代替。
重新编译u-boot,然后测试用u-boot的flinfo、md和cp.b命令测试flash驱动。
一切正常后u-boot部分完成
u-boot打包
#gzip –c u-boot.bin > u-boot.gz
3.boot.bin移植
先看看boot.bin的源码,它也是用的ELDK开发环境,我用先前安装的交叉开发环境编译,出错。。。提示ld命令错误。可能是与开发环境不兼容,换成官方包中的cross-2.95.3.zip,编译通过。
修改main.c中下面2项
#define SRC 0x10010000   (u-boot.gz将烧入flash的位置)
#define DST 0x20700000  (u-boot.gz被解压后载入SDRAM的位置,和loader中保持一直)
同样修改initboot.c中的AT91F_InitSDRAM(),和loader的修改一样。
编译
#make all

烧入flash测试
    片内启动,载入loader.bin
    再用loader.bin载入u-boot运行。
   
下面是在u-boot提示符下的操作
u-boot > loadb 20000000
--------------用kermit协议载入boot.bin文件到SDRAM的20000000地址-----
u-boot > cp.b 20000000 10000000 xxx  
(上一步文件载入完后会显示下载字节数,xxx就是字节数的16进制表示)
接下来烧入u-boot.gz
u-boot > loadb 20000000
u-boot > cp.b 20000000 10010000 xxx
断开板子上的跳线,片外启动开发板。等几秒后u-boot启动了。
到此u-boot移植结束。
阅读(1571) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~