Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1502962
  • 博文数量: 213
  • 博客积分: 10418
  • 博客等级: 上将
  • 技术积分: 3358
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-09 23:49
文章分类

全部博文(213)

文章存档

2014年(1)

2013年(5)

2012年(11)

2011年(2)

2010年(8)

2009年(26)

2008年(160)

分类: LINUX

2008-04-10 20:59:20

前段时间移植了vivi-0.1.4,也对源代码进行了解析学习。原本的想法是给vivi增加tftp功能,那么就需要写cs8900a驱动(我用的网卡芯片是CS8900A-CQ3Z),然后呢实现tftp协议,最后添加到vivi支持的命令集中。这部分工作如果从头开发,没有必要,因为U-boot就提供了tftp功能,可以借鉴,把相关代码移植到vivi下,这样vivi就具备了tftp下载功能。所以,准备先移植uboot,学习一下。vivi和uboot互相利用,进行功能完善和理解的深入。
 
【备注: 2007年末就是专心研究bootloader相关技术,以vivi和U-boot进行对比研究,是一个很好的学习思路。两者可以同时进行,互相借鉴,有助于问题的解决。这仅仅是学习的方法,并不是工作开发的方法。毕竟工作中是没有太多的时间让你细致的研究相关的代码的。工作中就是要尽可能快的寻找一切可以有效利用的资源,然后整理吸收,在这个高度上完成自己的工作,绝对不能自大的一切从头做起。】
 
    下面只关注移植流程和解决方案,自己所作的工作量很少,结合的代码分析也比较少,主要解决出现的问题。后续的工作中,会结合uboot源代码分析学习。继续加深对bootloader技术的认识!
 
一、前言
 
    s3c2410在国内还是用的很广泛的,所以资料相对比较多。uboot对基于nand flash启动也提供了支持,相关的移植步骤和资料也比较多。我推荐的方法还是通过读patch来分析解决移植问题。这里主要提到几个参考资料:
 
1、openmoko
 
    网上原创性的解决方案,估计大多数源于openmoko。看看网上那些资料,所用的源代码和思路无一不是来自这里的patch,最多根据自己的开发板做了少许的改动。现在把openmoko的资源列表如下:
 
    wiki openmoko主页网址:
    wiki openmoko bootloader:
    wiki openmoko uboot patches:
 
    上面的资源非常丰富,只要有效的利用,能解决遇到大部分通常的问题。
 
2、嵌入式中国 
 
    北邮的hiboy在u-boot-1.2.0的移植上有不少独创性的工作。
 
 
    lufuchong也做了很多的工作,利用了hn的keety的补丁。不过我没有找到他的补丁,对其关于bootm的理解还是赞一个。
 
    其他的资料就不一一列出了,最有价值的就是上面三位的工作了。
 
    利用patch是很好的方法,当然我不是说直接打上补丁,而是阅读patch,通过patch把移植的思路和步骤理清理顺,然后形成自己的理解,最后可以深入源代码,增加自己的贡献。如果说我在s3c2410上做了些工作,那就是强调和利用patch,好的patch是最好的资源,即使没有详细的说明,有一定移植经验的人也很容易借鉴,并最终成功。如果对patch不了解,就先看一下我在去年暑假翻译的一篇文章:http://blog.chinaunix.net/u/21948/showart_157145.html《Linux下patch的制作和使用》。需要注意的是,在制作patch时,一定要用distclean清理一下源文件树,否则的话,制作的patch质量上可是不敢恭维。既然要做,就要做好一些。hiboy提供的patch中,就犯了这个错误,希望不是习惯问题。
 
二、准备工作
 
     1、选择版本
 
     版本虽然不是越新越好,但是新版本提供的特性较多,自己能够学习到的内容也比较多,所以还是选择最新版本。
 

[armlinux@lqm bootloader]$ ftp ftp.denx.de
Connected to
.

 
    还是从pub/u-boot下载最新版本,现在正式发布版是u-boot-1.2.0。以后就以此版本进行学习和开发。解压等工作不必细说。
 
    为了制作patch的方便,解压之后的u-boot-1.2.0命名为u-boot-1.2.0.orig,然后复制做一个开发版u-boot-1.2.0。为了在命令行下操作方便,可以使用软链接。如下:
 

[armlinux@lqm bootloader]$ cp -rf u-boot-1.2.0.orig/ u-boot-1.2.0
[armlinux@lqm bootloader]$ ln -s u-boot-1.2.0.orig/ orig
[armlinux@lqm bootloader]$ ln -s u-boot-1.2.0 develop

 
     这样,使用TAB键就方便多了。关于要删除这些链接文件,可能会遇到一个小的bug。看一下我的解决方案:http://blog.chinaunix.net/u/21948/showart_385132.html
 
    2、交叉编译工具链
 
    u-boot-1.2.0的版本还是比较高的,去年暑假自己做过交叉编译工具链,耗费工作量太大。兴趣也不在那里,所以还是选择已有的质量较高的工具链。还是到ARM的官方网站上找,可以找到CODESOURCERY公司提供高质量的GNU Toolchain,你可以从这里下载:。最新版已经是arm-2007q1。我把交叉编译工具都放到/usr/local/arm/下面了,现在只有两个:
 

[armlinux@lqm arm]$ tree -L 1
.
|-- 2.95.3
`-- arm-2007q1

2 directories, 0 files

 
    大多数非最新版使用2.95.3可以解决了,新版本基本采用arm-2007q1。这两个工具都是比较成熟好用的,可以避免出现不少问题。
 
    3、硬件配置说明
 
    实验箱还是深圳Embest的EDUKIT-III,资源如下:
 
    ·SoC  : S3C2410A
    ·SDRAM: 两片HY57V561620CT-H(共64M)
    ·NOR Flash : AM29LV160DB-90EC(2M)
    ·NAND Flash: K9F5608UOC(32M)
    ·网络芯片: CS8900A-CQ3Z(接在nGCS3,也就是bank3,由此对应的基地址为0x19000300)
 
    可见大部分是smdk2410的标配,所以移植的工作量是很小的。只是在流程上弄清楚,在分析完源代码后,可以考虑增加或者改进功能。现在的想法是暂时不使用nor flash,直接使用nand flash,跟前面vivi的开发保持一致。
 
(备注:
    从U-boot-1.2.0可以看出,U-boot的开发已经不仅仅满足于作为一个bootloader,现在正在逐步在下面几个方面深入和完善:增加下载手段和对文件系统的支持度、增加内核调试功能(集成debugger)、完善对多architecture多硬件平台的支持。从这个角度上看,U-boot已经身兼bootloader、monitor、debugger多重功能,支持的力度也越来越广泛。这是bootloader技术发展的一个趋势,慢慢的庞大起来,如同Linux内核一样,不再小巧。与此同时,我们可以从中学习和认识的东西也在不断增多。
    我想现在bootloader的设计分成三种趋势。第一种是只要求具备基本的bootloader功能,对性能大小要求非常高,这样需要专门编写。归结为“微型化”。第二种是利用现成的通用的bootloader,移植到自己的开发板上,比如U-boot就是一个很好的选择。在这方面,U-boot已经从bootloader的基本功能向可能扩展的各个方向延伸,可归结为“大型化”。第三种,就是SoC厂商为了推广自己的产品,在推出时,可能会开发专用的bootloader,功能比较完善,但是对其他平台的支持并不好,如vivi、blob都在此范围内。它介于上述两者之间。
 
三、移植工作
 
(一)首先就是让U-boot能跑起来
 
    这部分的工作比较少,参考的主要是openmoko的uboot-s3c2410-nand.patch,通过读这个patch理顺移植的思路。因为前面做at91rm9200的时候用过uboot1.1.2,所以对uboot的整个结构和移植的思路还有一定了解的。假定我们的开发板命名为myboard,与smdk2410基本类似。往常我的做法也是修改uboot,使之支持myboard,而针对smdk2410是没有变化的。现在为了使patch更容易阅读,与源代码的修改更加明确,就默认smdk2410就是myboard,直接在上面动手术。这样,通过patch可以把修改的步骤看的一清二楚。
 
主要的步骤有这么几个:
 
    ·修改顶层Makefile,更改CROSS_COMPILE为你的交叉编译工具的路径。
 
    这步工作并非必须,你也可以在命令行中指定。不过那样就麻烦了些。
 
    ·修改board/{your board}/
 
    这是主要的工作量,board目录下是平台依赖,存放电路板相关的文件。重点是内存初始化和flash驱动、开发板初始化。
 
    ·修改cpu/arm920t/
 
    这里存放的是cpu相关的目录文件,启动的入口地址就是在start.S中。需要做适当的修改。
 
    ·修改include/configs下相关配置文件
 
    这里是修改配置文件,对smdk2410来说,就是smdk2410.h。主要是根据自己需要的功能进行定制customize,也可以称之为裁减。
 
    当然上面是基本的步骤,也仅仅能够完成基本的工作。真正原创性的移植工作需要完成大量的驱动编写工作,在我看来,那才是真正的移植,那样的人也是最为缺乏的人才。我现在只是在别人移植好的基础上进行二次移植,类似于二次开发,难度和工作量要小的多。不管怎么样,先按照这个基本的思路展开。关于uboot各个文件夹的存放内容,详细部分参考我移植到at91rm9200时的笔记http://blog.chinaunix.net/u/21948/showart_153570.html。就整体的架构而言,目录可以分为三种类型:
 
    1、与处理器架构或开发板硬件相关
    2、一些通用的函数或者驱动程序
    3、uboot的应用程序、工具或者文档
 
    下面开始移植。
 
    第一步工作,修改顶层目录下的Makefile。
 
    这里的基本工作就是修改CROSS_COMPILE,比较简单。网上通常的流程(以smdk2410为例)为:
 

make smdk2410_config
make

 
    为什么要这样做,还有什么可以执行的make命令。在这里还是简单的阅读一下Makefile,对整体规划有了初步的了解。其中第一条命令源于(以smdk2410为例),属于指定目标编译:
 

smdk2410_config : unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

 
    其中依赖部分unconfig的作用是清理一下垃圾文件。
 

unconfig:
        @rm -f $(obj)include/config.h $(obj)include/config.mk \
                $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp

 
    而MKCONFIG是一个脚本文件,可以从下看出:
 

MKCONFIG := $(SRCTREE)/mkconfig

 
    继续向上追SRCTREE:
 

SRCTREE := $(CURDIR)

 
    到此就是终结了。CURDIR这个变量是Makefile提供的,代表了make当前的工作路径。也就是说在顶层目录下有一个mkconfig脚本文件。如果不清楚变量到底是什么,提供的调试手段就是在Makefile的底部加入调试单元,比如:
 

#
# make debug
#
debug:
        @echo "CRUDIR: $(CURDIR)"
        @echo "SRCTREE: $(SRCTREE)"
        @echo "OBJTREE: $(OBJTREE)"

 
    这样就可以清楚的看到每个变量代表的内容了。追查到这里,就很清楚了,如果你的第一步工作是make smdk2410_config,那么所进行的工作就是清理一下临时文件,然后执行mkcofig这个shell脚本。脚本的内容就不具体分析了,比较简单,其实就是通过你的配置部分完成include/config.mk的生成,里面有四个宏,这是根据你的配置来的。例如:
 

ARCH = arm
CPU = arm920t
BOARD = smdk2410
SOC = s3c24x0

 
    具体的含义很明显了。这样第二步的工作是make,其实按照make的执行规则就是执行make all。如果你前面指定了CROSS_COMPILE,那么第二步工作只需要执行make就可以了,不需要在命令行指定ARCH=arm,也不需要在Makefile中指定ARCH。这些工作mkconfig会替你去做。你需要做的只是完成配置命令部分。
 
    为了是测试流程自动化,借鉴vivi的Makefile,我增加了一个make命令,这样只需要执行make smdk2410,就可以完成三步工作:一是make distclean,二是make smdk2410_config,三是make。第一部分patch如下:
 

[armlinux@lqm bootloader]$ cat uboot_topdir_makefile.patch
diff -urN u-boot-1.2.0.orig/Makefile u-boot-1.2.0/Makefile
--- u-boot-1.2.0.orig/Makefile 2007-01-07 07:13:11.000000000 +0800
+++ u-boot-1.2.0/Makefile 2007-09-19 12:09:20.000000000 +0800
@@ -125,7 +125,7 @@
 CROSS_COMPILE = powerpc-linux-
 endif
 ifeq ($(ARCH),arm)
-CROSS_COMPILE = arm-linux-
+CROSS_COMPILE = /usr/local/arm/arm-2007q1/bin/arm-none-linux-gnueabi-
 endif
 ifeq ($(ARCH),i386)
 ifeq ($(HOSTARCH),i386)
@@ -2350,3 +2350,10 @@
        gtar --force-local -zcvf `date "+$$F-%Y-%m-%d-%T.tar.gz"` $$F
 
 #########################################################################
+
+#
+# make {your board}
+#
+
+%: distclean %_config
+ $(MAKE) && echo "^_^ Succeed!"

 
    第二步工作:修改board的相关文件
 
    一是修改lowlevel_init.S,就是完成13个内存寄存器的配置。前面在vivi的基础实验中也做过了。这里最为关键的部分其实是BWSCON,要配置好BANK3的总线时序。如果此处的总线时序配置不好,那么CS8900A是无法正常工作的。因为EDUKIT-III完全按照smdk2410的配置,片选为nGCS3,也就是BANK3,基地址仍然为0x19000300。基本不需要修改,如果是其他的网络芯片,一定要注意设置此处的总线位宽和总线时序,否则,网络芯片无法正常工作。我在这里的工作是调整了sdram的刷新频率,具体为:
 

#define REFCNT 1268 /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */

 
    但是,这样的前提是HCLK必须为100MHz。这就需要修改smdk2410.c了,同时还要根据蜂鸣器等等,设置合适的GPIO的数值。可以参考patch。
 
    因为是从nand flash启动,需要用到nand read,可以直接把vivi中的nand_read.c复制过来,增加一个配置选项CONFIG_S3C2410_NAND_BOOT。按照uboot的配置参数的命名原则,CONFIG_和CFG_是不同的。需要注意一下。
 
    完成这些,修改一下Makefile就可以了。这里面最为困难的就是要配置好内存寄存器,设置好总线时序。网卡驱动的关键性工作也在这个地方,软硬件都理解才能顺利解决。
 
文件: uboot_board_s3c2410.patch.gz
大小: 1KB
下载: 下载
 
    第三步工作:修改cpu/arm920t相关文件
 
    主要就是修改start.S。而start.S的核心工作就是增加copy_myself。这个可以借鉴vivi的部分,不过需要根据uboot的一些特点做一些修改。也不用多说。补丁如下:
 
   
文件: uboot_cpu_s3c2410.patch.gz
大小: 3KB
下载: 下载
 
    第四步工作:修改配置文件
 
   
文件: uboot_include_s3c2410.patch.gz
大小: 3KB
下载: 下载
 
    注意,上述的每个补丁都包含前面所做的工作。也就是说,最后的补丁uboot_include_s3c2410.patch.gz是完成基本工作后的补丁。
 
    编译得到u-boot.bin,利用JTAG工具烧写nand flash,上电后从nand flash启动:
 
 


U-Boot 1.2.0 (Sep 19 2007 - 12:43:31)

DRAM: 64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
U-boot # printenv
bootdelay=3
baudrate=115200
ethaddr=08:00:3e:26:0a:5b
ipaddr=192.168.1.110
serverip=192.168.1.216
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial

Environment size: 161/65532 bytes
U-boot # ping 192.168.1.216
host 192.168.1.216 is alive

 
    测试了一下printenv命令和ping命令,都正常。然后又测试了date命令,如下,也正常:
 

U-boot # date 091916122007
Date: 2007-09-19 (Wednesday) Time: 16:12:00
U-boot # date
Date: 2007-09-19 (Wednesday) Time: 16:12:03

 
    但是不能读写nand flash。这是需要改进的地方。tftp是正常的,要想利用bootm来启动内核,需要在zImage来增加头信息。这个详细部分可以参考lufuchong的文章,写的简明准确:http://www.cnitblog.com/luofuchong/archive/2007/01/12/21834.html,我制作了一个uImage,测试如下:
 

U-boot # tftp 0x31000000 uImage
TFTP from server 192.168.1.216; our IP address is 192.168.1.110
Filename 'uImage'.
Load address: 0x31000000
Loading: #################################################################
         #################################################################
done
Bytes transferred = 662340 (a1b44 hex)
U-boot # bootm 0x31000000
## Booting image at 31000000 ...
   Image Name: linux-2.4.18
   Created: 2007-09-18 5:01:45 UTC
   Image Type: ARM Linux Kernel Image (uncompressed)
   Data Size: 662276 Bytes = 646.8 kB
   Load Address: 30008000
   Entry Point: 30008000
   Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux................................................ done, booting the kernel.
Linux version 2.4.18-rmk7-pxa1 (armlinux@lqm) (gcc version 2.95.3 20010315 (release)) #1 Tue Sep 18 12:59:07 CST 2007

//下面省略

 
    看来是成功的。
 
    注意到一个问题,原来用uboot1.1.2的时候,会打印U-Boot code: ,但是现在没有。使用source insight查看lib_arm中的board.c的init_sequence数组,经过查找,应该在display_banner里面:
 

/*
 * To match the U-Boot user interface on ARM platforms to the U-Boot
 * standard (as on PPC platforms), some messages with debug character
 * are removed from the default U-Boot build.
 *
 * Define DEBUG here if you want additional info as shown below
 * printed upon startup:
 *
 * U-Boot code: 00F00000 -> 00F3C774 BSS: -> 00FC3274
 * IRQ Stack: 00ebff7c
 * FIQ Stack: 00ebef7c
 */

 
    通过debug可以知道,uboot取消了额外的调试信息,追查到【include/common.h】中,看看这个部分的定义:
 

#ifdef DEBUG
#define debug(fmt,args...) printf (fmt ,##args)
#define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);
#else
#define debug(fmt,args...)
#define debugX(level,fmt,args...)
#endif /* DEBUG */

 
    也就是说,你只要在这里定义一下DEBUG,把开关打开就可以看到调试信息了,上面的注释解释的也非常明确。我想打印调试信息,所以增加了DEBUG,并且修正了patch(当然你也可以不要这个debug信息)。注意,要在include 前增加DEBUG的定义,原因很简单。于是现在的补丁如下:
 
文件: uboot-s3c2410-nand.patch.gz
大小: 3KB
下载: 下载
 
    uboot.bin下载后,上电启动打印信息如下:
 

U-Boot 1.2.0 (Sep 19 2007 - 13:07:41)

U-Boot code: 33F80000 -> 33F96C74 BSS: -> 33F9B3A4
RAM Configuration:
Bank #0: 30000000 64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
U-boot #

 
    比较好用了。
 
(二)下面的工作就是去掉flash配置部分,然后增加nand读写部分。这里需要参考hiboy的patch和openmoko的default-env.patch,另外需要关注的就是uboot自带的文档,在doc中,关于nand部分有两篇有价值的参考。
 
文件: uboot-s3c2410-nand.patch.gz
大小: 6KB
下载: 下载
 
    先给出patch,明天再总结吧。主要就是关于legacy的使用方法、nand的底层驱动、default env的修正三个方面。现在的启动信息如下:
 

U-Boot 1.2.0 (Sep 19 2007 - 13:54:19)

U-Boot code: 33F80000 -> 33F97950 BSS: -> 33F9C200
RAM Configuration:
Bank #0: 30000000 64 MB
NAND: 32 MB
In: serial
Out: serial
Err: serial
U-boot #

 
    测试了nand部分,效果还可以,一切正常。用bootm引导内核也没有问题,还不能挂载文件系统。如果把文件系统挂载弄好,那bootloader就算是彻底移植好了。争取把tftp部分移植到vivi上面。
 

U-boot # nand info

Device 0: Samsung KM29U256T at 0x4e000000 (32 MB, 16 kB sector)
U-boot # printenv
baudrate=115200
ethaddr=08:00:3e:26:0a:5b
netmask=255.255.255.0
ipaddr=192.168.1.110
serverip=192.168.1.216
bootargs=noinitrd root=/dev/bon/2 console=ttyS0
bootdelay=5
stdin=serial
stdout=serial
stderr=serial

Environment size: 209/131068 bytes
U-boot # setenv bootargs 6
U-boot # saveenv
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
?boot # reset
U-Boot 1.2.0 (Sep 19 2007 - 13:54:19)

U-Boot code: 33F80000 -> 33F97950 BSS: -> 33F9C200
RAM Configuration:
Bank #0: 30000000 64 MB
NAND: 32 MB
In: serial
Out: serial
Err: serial
U-boot # printenv
baudrate=115200
ethaddr=08:00:3e:26:0a:5b
netmask=255.255.255.0
ipaddr=192.168.1.110
serverip=192.168.1.216
bootdelay=5
bootargs=6
stdin=serial
stdout=serial
stderr=serial

Environment size: 172/131068 bytes
U-boot #

阅读(2013) | 评论(0) | 转发(0) |
0

上一篇:Linux下使用QQ的三个方法

下一篇:jffs2

给主人留下些什么吧!~~