u-boot-2010.06在unsp2440上的移植3

    技术2022-05-19  21

    一、 步骤五:U-boot支持TFTP、nfs网络下载

    前面我们实现了使用串口下载并更新系统的功能,但是嵌入式系统的内核跟根文件系统都比较大,使用串口下载速度太慢,u-boot提供了通过TFTP、nfs等网络下载的功能支持,本节我们完成此项功能的移植与修改。

    1) u-boot默认支持的是cs8900网卡,我们的开发板使用的是DM9000网卡,所以要做相应的修改。

    首先要修改include/configs/unsp2440.h中的相关代码:

    #define CONFIG_NET_MULTI

    //#define CONFIG_CS8900 /* we have a CS8900 on-board */

    //#define CONFIG_CS8900_BASE 0x19000300

    //#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */

    //屏蔽掉与cs8900有关的宏定义

    #define CONFIG_DRIVER_DM9000 1

    #define CONFIG_DM9000_NO_SROM 1

    #define CONFIG_DM9000_BASE 0x18000300 //网卡片选地址

    //网卡地址的选择:S3C2440片外寻址分成8个BLANK,每个BLANK的大小为128M,

    //我们的开发板的网卡接在了BLANK3上,因此地址等于:128M*3*1024*1024=0x18000000,由于DM9000网卡本身的特性,IO地址需要从0x18000300开始,数据地址需要从0x18000304开始。

    #define DM9000_IO 0x18000300

    #define DM9000_DATA (0x18000300 + 4) //网卡数据地址

    #define CONFIG_DM9000_USE_16BIT 1

    2) 使用TFTP、NFS等服务必须配置相应的IP地址、网关等信息,我们同样需要修改include/congifs/unsp2440.h文件相应内容:

    //给u-boot加上ping命令,用来测试网络通不通

    #define CONFIG_CMD_PING

    / /恢复被注释掉的网卡MAC地址和修改你合适的开发板IP地址

    #define CONFIG_ETHADDR   08:00:3e:26:0a:5b  //开发板MAC地址

    #define CONFIG_NETMASK   255.255.255.0

    #define CONFIG_IPADDR    192.168.1.105       //开发板IP地址

    #define CONFIG_SERVERIP  192.168.1.103      //Linux主机IP地址

    下面需要修改u-boot的源码以完成对unsp2440的支持:

    3) 首先要修改dm9000网卡的总线宽度:board/samsung/unsp2440/lowlevel_init.S

    将56行左右的

    #define B3_BWSCON (DW16 + WAIT + UBLB)修改为:

    #define B3_BWSCON (DW16)

    4) 编译下载u-boot已测试网络情况

    #ping 192.168.220.103

    dm9000 i/o: 0x18000300, id: 0x90000a46

    DM9000: running in 16 bit mode

    MAC: 08:31:22:22:02:51

    operating at 100M full duplex mode

    Using dm9000 device

    host 192.168.220.103 is alive

    代表网络连接正确,为了验证TFTP是否可以使用,我们使用tftp更新u-boot.bin

    首先在PC机上开启一个TFTP服务器,这里我们选取tftpd32.exe这款小软件作为TFTP服务器,首先双击打开此软件,显示以下界面,将要下载的文件u-boot.bin文件拷到与tftpd32.exe同一个目录下。

    打开开发板终端:

    #tftp 0x33000000 172.20.223.63:u-boot.bin

    tftp:采用tftp协议0x33000000:下载到内存的地址172.20.223.63:服务器的地址,这里如果不填默认是:

    #define CONFIG_SERVERIP  192.168.1.103      //unsp2440.h中此宏所定义的地址

    终端中有如下显示:

    dm9000 i/o: 0x18000300, id: 0x90000a46

    DM9000: running in 16 bit mode

    MAC: 08:31:22:22:02:51

    operating at 100M full duplex mode

    Using dm9000 device

    TFTP from server 172.20.223.63; our IP address is 172.20.223.22

    Filename 'u-boot.bin'.

    Load address: 0x33000000

    Loading: T ##########

    done

    Bytes transferred = 144644 (23504 hex)

    表示下载成功。

    二、 步骤六:U-boot支持TFTP下载启动linux内核、根文件系统

    Linux内核的下载过程跟上节下载u-boot.bin基本一致,但是启动linux需要一些其他知识,下面我们来分析一下。

    1) 首先是准备uzImage镜像

    u-boot采用的linux镜像与我们使用make zImage编译出的镜像稍有不同,u-boot采用uzImage格式的镜像,uzImage是由zImage + 0x40字节的文件头组成。

    经过编译后的u-boot在根目录下的tools目录中,会有个叫做mkimage的工具,他可以给zImage添加一个header,也就是说使得通常我们编译的内核zImage添加一个数据头信息部分。

    使用: 中括号括起来的是可选的

    mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image

    选项:

    -A:set architecture to 'arch'        //用于指定CPU类型,比如ARM

    -O:set operating system to 'os'     //用于指定操作系统,比如Linux

    -T:set image type to 'type'           //用于指定image类型,比如Kernel

    -C:set compression type 'comp'    //指定压缩类型

    -a:set load address to 'addr' (hex) //指定image的载入地址

    -e:set entry point to 'ep' (hex)     //内核的入口地址,一般为image的载入地址+0x40(信息头的大小)

    -n:set image name to 'name'         //image在头结构中的命名

    -d:use image data from 'datafile'   //无头信息的image文件名

    -x:set XIP (execute in place)       //设置执行位置

    先将u-boot下的tools中的mkimage复制到主机的/usr/local/bin目录下,这样就可以在主机的任何目录下使用该工具了。

    现在我们进入kernel生成目录(一般是arch/arm/boot目录),然后执行如下命令,就会在该目录下生成 一个uImage.img的镜像文件,把他复制到tftp目录下,这就是我们所说的uImage

    mkimage  -n 'linux-2.6.34'  -A arm  -O linux  -T kernel  -C none  -a 0x30008000  -e 0x30008000  -d zImage uImage.img

    2) linux内核启动参数

    前一节我们已经得到了u-boot所需要的linux镜像,下面我们设置linux启动所需要的参数,首先u-boot中机器号(match type)与内核必须统一,linux内核中的机器号为:

    在kernel的arch/arm/tools/mach-types文件中针对不同的CPU定义了非常多的MACH_TYPE,我们找到379行左右:

         s3c2440 ARCH_S3C2440 S3C2440 362

    同时arch/arm/mach-s3c2440/mach-smdk2440.c文件中smdk2440_machine_init函数

           MACHINE_START(S3C2440, "SMDK2440")    决定了当前内核的match type是362.

    下面我们修改u-boot中的match-types与之匹配

    在u-boot的include/asm-arm/mach-types.h文件中针对不同的CPU定义了非常多的MACH_TYPE,可以找到下面这个定义:

    #define MACH_TYPE_S3C2440 362

    我们增加以下定义:

    #define MACH_TYPE_UNSP2440 362

    修改 board/samsung/unsp2440/unsp2440.c文件中board_init函数

    gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

    为:

    gd->bd->bi_arch_number = MACH_TYPE_UNSP2440;

    重新编译,我们就能得到支持我们开发板内核的u-boot了。

    3) 下载uzImage镜像:

    下载linux内核到NAND FLASH中的具体地址,由内核中的FLASH分区表决定:

    在arch/arm/plat-s3c24xx/common-smdk.c文件中可找到以下信息:

    static struct mtd_partition smdk_default_nand_part[] =

    {

           [0] =  {

                            .name = "bootloader",

                             .offset = 0, //boorloade分区起始地址

                             .size = 0x30000, //bootloader分区的大小

                   },

                  //bootloader分区与kernel分区之间0x30000---0x50000的地址用作存放linux参数分区

                   //这个地址范围要与前面我们移植NAND驱动时定义的CONFIG_ENV_OFFSET保持统一

                   [1] = {

                                 .name = "kernel",

                                 .offset = 0x50000, //kernel分区起始地址

                                 .size = 0x300000, //kernel分区的大小

                              },

                  [2] = {

                                  .name = "root",

                                  .offset = 0x350000, //root分区起始地址

                                  .size = 0x3cac000, //root分区起始地址

                             },

    };

    下面我们使用命令行更新并下载内核:

    #tftp 0x33000000 172.20.223.63:uImage.img

    #nand erase 0x50000 0x300000                                //注意这两个数据的大小一定要跟上述表中的 kernel分区保持一致

    #nand write 0x33000000 0x50000 0x300000         //将0x33000000中数据写入NAND FLASH中

    启动内核:

    #从ram中启动kernel

                    #bootm 0x33000000

    #从NAND FLASH中启动

                    #nand read 0x33000000 0x50000 0x300000

                    # bootm 0x33000000

    #u-boot提供了另一个命令用来启动内核

              #nboot 0x33000000 0 0x50000        //nboot代表从nand中启动内核,0x33000000表示内核拷贝的地址,0 代表第一块FLASH,0x50000代表kernel镜像的起始位置,不用指定大小,这个命令会自动判断内核镜像的大小

               # bootm 0x33000000

    如果没有问题的话,在终端中可以看到内核启动信息。

    4)下载linux根文件系统

    Linux根文件系统有各种各样的格式,有基于norFLASH的jffs2,基于NAND的cramfs与yaffs,基于网络的nfs等。

    a) 这里首先我们先使用nfs根文件系统来启动我们的系统。

    需要修改u-boot传递给linux 内核的启动参数,我们可以修改include/configs/unsp2440.h文件中的宏:

    #define CONFIG_BOOTARGS "noinitrd root=/dev/nfs nfsroot=/home/dengwei/linux_system/root_src/rootfs_test/,rsize=1024,wsize=1024 ip=172.20.223.118:172.20.223.151:172.20.223.254:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0"

    或者直接在终端下通过命令行完成:

    setenv bootargs noinitrd root=/dev/nfs nfsroot=/home/dengwei/linux_system/root_src/rootfs_test/,rsize=1024,wsize=1024 ip=172.20.223.118:172.20.223.151:172.20.223.254:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0

    b) 下面我们启动NAND FLASH中的根文件系统

    NAND FLASH中常用两种格式的根文件系统:cramfs、yaffs

    cramfs是压缩的只读根文件系统,u-boot直接支持

    yaffs/yaffs2是未压缩的可读可写的文件系统,u-boot需要修改之后才能支持。

    这里我们先烧写cramfs格式的根文件系统,下节再修改、移植支持yaffs格式根文件系统的u-boot。

    cramfs格式的根文件系统制作请参考其它相关文章,假设我们现在已经有了此格式的根文件系统,并且名字为:rootfs.cramfs。

    #tftp 0x33000000 172.20.223.63:rootfs.cramfs

    #nand erase 0x350000 0x3cac000                                   //注意这两个数据的大小一定要跟上述表中的 root分区保持一致

    #nand write 0x33000000 0x350000 0x3cac000            //将0x33000000中数据写入NAND FLASH中

    启动内核,如果顺利的话可以观察到我们的根文件系统也顺利的启动起来了。


    最新回复(0)