引言

  U-Boot是用于初始化目标板硬件,为嵌入式操作系统提供目标板硬件配置信息,完成嵌入 式操作系统装载、引导和运行的固件程序。它能够将系统的软硬件紧密衔接在一起。S3C2410是三星公司的一款基于ARM920T核的嵌入式通用处理器。 本文将详细介绍U-Boot在S3C2410开发板上的移植与运行。

  U-BOOT简介 

U-Boot支持ARM、 PowerPC等多种架构的处理器,也支持Linux、NetBSD和VxWorks等多种操作系统。它提供启动加载和下载 两种工作模式。启动加载模式也称自主模式,一般是将存储在目标板Flash中的内核和文件系统的镜像装载到SDRAM中,整个过程无需用户的介入。在使用 嵌入式产品时,一般工作在该模式下。工作在下载模式时,目标板往往受外设(一般是PC机)的控制,从而将外设中调试好的内核和文件系统下载到目标板中去。 U-Boot允许用户在这两种工作模式间进行切换。通常目标板启动时,会延时等待一段时间,如果在设定的延时时间范围内,用户没有按键,U-Boot就进 入启动加载模式。

  开发板的主要配置包括三星ARM9处理器S3C2410、1个串口和JTAG接口,晶振为12MHz,系统主频 为200MHz。另外,开发板上还包括1片4M×16位数据宽度的Flash,地址范围为0x01000000~0x01800000和2片8M×16位 数据宽度的SDRAM,地址范围为0x30000000~0x32000000。Flash使用了2410处理器的BANK0单元,由于2410中地址是 循环映射的,因而0x01000000 和0x0地址等同。

  在本系统中,U-Boot的主要功能包括:建立和初始化RAM;初始化一个串口;检测机器的体系结构,传递MACH_TYPE_xxx的值(SMDK2410)给内核;建立内核的标记列表(tagged list);调用内核镜像。

  U-Boot移植步骤

  为了使U-Boot支持新的开发板,一种简便的做法是在U-Boot已经支持的开发板中选择一种和目标板接近的,并在其基础上进行修改。代码修改的步骤如下: 
  1)在board目录下创建smdk2410目录,添加smdk2410.c、flash.c、memsetup.s、u-boot.lds和config.mk等;
  2)在cpu目录下创建arm920t目录,主要包含start.s、interrupts.c、cpu.c、serial.c和speed.c等文件;
  3)在include/configs目录下添加smdk2410.h,它定义了全局的宏定义等;
  4)修改u-boot根目录下的Makefile文件:
  smdk2410_config : unconfig@./mkconfig $(@:_config=) arm arm920t smdk2410
  5)运行make smdk2410_config,如果没有错误,就可以开始进行与硬件相关的代码移植工作。由于这部分代码与硬件紧密相关,所以要熟悉开发板的硬件配置,可参考各芯片的用户手册。
     
  U-Boot启动过程 

U-Boot的启动过程可以分成3个阶段。首先在Flash中运行汇编程序,将Flash中的启动代码部分复制到SDRAM中,同时创造环境准备运行C 程序;然后在SDRAM中执行,对硬件进行初始化;最后设置内核参数的标记列表,复制镜像文件,进入内核的入口函数。 

  1) 程序首 先在Flash中运行CPU入口函数/cpu/arm920t/start.s。具体工作包括:设置异常的入口地址和异常处理函数;配置PLLCON寄存 器,确定系统的主频;屏蔽看门狗和中断;初始化I/O寄存器;关闭MMU功能;调用/board/smdk2410中的memsetup.s,初始化存储 器空间,设置刷新频率;将U-Boot的内容复制到SDRAM中;设置堆栈的大小,ldr pc, _start_armboot。

  board/s3c2410中config.mk文件(TEXT_BASE = 0x31F00000)用于设置程序编译连接的起始地址,在程序中要特别注意与地址相关指令的使用。

  当程序在Flash中运行时,执行程序跳转时必须要使用跳转指令,而不能使用绝对地址的跳转(即直接对PC操作)。如果使用绝对地址,那么,程序的取指是相对于当前PC位置向前或者向后的32MB空间内,而不会跳入SDRAM中。

  2) 程序跳转到SDRAM中执行/lib_arm/board.c中的start_armboot()函数。该函数将完成如下工作:
*设置通用端口rGPxCON;rGPxUP;设置处理器类型gd->bd->bi_arch_number = 193;设置启动参数地址gd->bd->bi_boot_params = 0x30000100;
* env_init:设置环境变量,初始化环境;
* init_baudrate:设置串口的波特率;
* serial_init:设置串口的工作方式;
* flash_init:设置ID号、每个分页的起始地址等信息,将信息送到相应的结构体中;
* dram_init:设置SDRAM的起始地址和大小;
* env_relocate:将环境变量的地址送到全局变量结构体中(gd->env_addr = (ulong)&(env_ptr->data));
* enable_interrupts:开启中断;
* main_loop: 该函数主要用于设置延时等待,从而确定目标板是进入下载操作模式还是装载镜像文件启动内核。在设定的延时时间范围内,目标板将在串口等待输入命令,当目标 板接到正确的命令后,系统进入下载模式。在延时时间到达后,如果没有接收到相关命令,系统将自动进入装载模式,执行 bootm 30008000 30800000命令,程序进入do_bootm_linux()函数,调用内核启动函数; 

3) 装载模式下系统将执行do_bootm_linux()函数,0x30008000是内核在SDRAM中的起始地址;0x30800000是 ramdisk在SDRAM中的起始地址;0x40000是内核在Flash中的位置,0x100000是数据块的大小;0x140000是 ramdisk在FLASH中的位置,0x440000是数据块的大小。系统调用memcpy()函数将内核从flash和ramdisk复制到 SDRAM中,具体如下:
memcpy((void *)0x30008000, (void *)0x40000, 0x100000);//复制数据块
memcpy((void *)0x30800000, (void *)0x140000, 0x440000);//复制数据块 

  通常,将内核参数传递给Linux操作系统有两种方法:采用struct param_struct结构体或标记列表。本系统中采用了第二种方法。

一个合法的标记列表开始于ATAG_CORE,结束于ATAG_NONE。ATAG_CORE可以为空,一个空的ATAG_CORE的size字段设为 “2”(0x00000002)。ATAG_NONE 的size字段必须设为“0”。标记列表可以有任意多的标记(tag)。在嵌入式Linux系统 中,通常由U-Boot设置的启动参数有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、 ATAG_INITRD等。

  在本系统中,传递参数时分别调用了以下tag:
setup_start_tag(bd);   //标记列表开始
setup_memory_tags(bd); //设置内存的起始位置和大小
setup_commandline_tag (bd, commandline); /*Linux内核在启动时可以命令行参数的形式来接收信息,利用这一点可以向内核提供那些内核不能检测的硬件参 数信息,或者重载(override)内核检测到的信息,这里char *commandline "initrd= 0x30800000,0x440000  root=/dev/ram init=/linuxrc console=ttyS0";*/
setup_ramdisk_tag(bd);  //表示内核解压后ramdisk的大小
setup_initrd_tag(bd, initrd_start, initrd_end); //设置ramdisk的大小和物理起始地址
setup_end_tag(bd);    //标记列表结束

其中bd_t *bd = gd->bd是指向bd_t 结构体的指针,在该结构体中存放了关于开发板配置的基本信息。标记列表应该放在内核解压 和initrd的bootp程序都不会覆盖的内存区域,同时又不能和异常处理的入口地址相冲突。建议放在RAM起始的16K大小处,在本系统中即为 0x30000100处。

  U-BOOT调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START+0x8000地址处。在跳转时,要满足下列条件:
a) CPU寄存器的设置:R0=0;R1=机器类型 ID,本系统的机器类型ID=193。R2=启动参数标记列表在RAM中的起始基地址; 
b) CPU模式:必须禁止中断(IRQs和FIQs);CPU必须工作在SVC模式;
c) Cache和MMU的设置:MMU 必须关闭;指令Cache可以打开也可以关闭;数据Cache必须关闭。 

  系统采用下列代码来进入内核函数:
theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);
theKernel (0, bd->bi_arch_number);其中,hdr是image_header_t类型的结构体,hdr->ih_ep指向内核 的第一条指令地址,即Linux操作系统下的/kernel/arch/arm/boot/compressed/head.S汇编程序。 theKernel()函数调用应该不会返回,如果该调用返回,则说明出错。

  结语
  本文总结介绍了U-Boot在S3C2410上的移植,移植完成后,U-Boot能够稳定地运行在开发板上,为后续的软件开发打下较好的基础.

基于S3C2410处理器目标板的移植

本文描述了将Linux移植到基于S3C2410处理器目标板上的方法与过程。介绍了目标平台和Linux,并说明了如何搭建移植环境,着重介绍了 Bootloader的架构和功能以及Linux内核的移植。结果证明该方法是可行的。移植后Linux在嵌入式系统中运行良好。

引言

嵌人式系统就是以应用为中心、以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。 ARM嵌人式芯片是一种高性能、低功耗的RISC芯片。它由英国ARM公司设计,世界上几乎所有的主要半导体生产商都生产基于ARM体系机构的通用芯片, 或在其专用芯片中应用相关ARM技术。在2001年基于ARM内核的处理器占市场份额的75%,成为业界的龙头。

Linux是免费发行的、快速高效的操作系统 ,Linux的出现在计算机世界引发了一场革命。Linux操作系统以代码开放、功能强大又易于移植成为嵌入式操作新兴力量。嵌人式Linux是按照嵌人 式操作系统的要求设计的一种小型操作系统,由一个内核以及一些根据需要进行定制的系统模块组成。其内核很小 ,一般只有几百kb,即使加上其他必要的模块和应用程序,所需的存储空间也很小。它非常适合于移植到嵌入式系统中去 ,同时它具有多任务多进程的系统特征 ,有些还具有实时特征。

1 目标平台介绍

文中使用的目标平台S3C2410是SAMSUNG公司使用920T处理器内核开发的一款嵌入式处理器。S3C2410是Samsung公司专门为 PDA、Intenet设备和手持设备等专门开发的微处理器。该芯片还包含有16kB一体化的Cache/MMU,这一特性使开发人员能够将Linux和 VXwork移植到基于该处理器的目标系统中。该目标板的系统资源如下 :

(1)CPU:S3C2410微处理器,工作频率为200MHz。

(2)Flash:16MB。

(3)SDRAM:64MB SDRAM。

(4)UART:RS-232串行接口。

(5)其他 :14针ARM JTAG接口等。

2 交叉编译环境的建立

基于Linux操作系统的应用开发环境一般是由目标系统硬件(开发板)和宿主PC机所构成。目标硬件开发板用于运行操作系统和系统应用软件,而目标 板所用到的操作系统的内核编译、应用程序的开发和调试则需要通过宿主PC机来完成(所以称为交叉编译)。双方之间一般通过串口、并口或以太网接口建立连接 关系。单独拿出一台PC机,在该PC上安装桌面的Linux操作系统(如RedHatLinux9.0),可以采用默认的安装选项(注意要包含FTP服 务),这台PC作为Linux服务器,除管理员以外,一般不直接让其他人去操作。

将该Linux服务器接入局域网,并新建一些合法用户,以便其他的PC机(在此将其称为工作站)的合法用户能访问到Linux服务器。而其他的PC机(工作站)仍然使用Windows操作系统。

需要的软件工具包括 :

(1)ftp客户端程序。

(2)Telnet工具。

(3)移植到某一特定ARM平台的Linux操作系统内核源码。

(4)GNU编译工具,可由相关网站下载。

在某工作站PC上安装ftp客户端程序和Telnet工具 ,安装完毕后应该可以在该工站PC和Linux服务器之间进行文件的传输,并在工作站PC可以通过Telnet登陆到Linux服务器(可能需要将Linux服务器 的防火墙服务关闭才能完成)。

Linux 服务器的安装:将工作站PC上的Linux操作系统内核源码压缩包和GNU编译工具通过ftp传送到Linux服务器的某个目录(如合法的用户目录),然 后在该目录下解压,并将GNU编译工具安装到默认的工作目录即可,以上工作通过在工作站PC使用Telnet工具完成,而不需要在Linux服务器上进 行。Linux操作系统内核的编译一般有一个比较固定的步骤,会根据MakeFile文件的不同而略有差异,可参考相关文档,编译的工作在工作站PC使用 Telnet工具完成。按固定的步骤编译内核完成以后,会在相应目录生成可执行的二进制文件,通过ftp将该可执行的二进制文件传回工作站PC,然后通过 ADS或SDT下的烧写工具写入开发板的Flash即可。

3 Bootloader的架构和功能

Bootloader引导程序是嵌入式开发很重要的组成部分。它是嵌入式系统上电后执行的第一个程序,并由它最终将操作系统启动起来并将控制权交给 操作系统。Bootloader引导程序最基本的功能是对硬件系统的初始化和内核启动参数设置并启动内核。Bootloader的主要功能有:

(1)初始化CPU 的主频、SDRAM、中断、串口等硬件;

(2)启动Linux内核并提供一个RAMDISK;

(3)通过串口下载内核或RAMDISK到目标板上;

(4)将修改过的内核或RAMDISK写入到Flash内;

(5)为用户提供一个命令接口。

在嵌入式系统开发过程中,Bootloader还与主机通信,不断检测从主机传来的控制信息和数据信息,完成相应的操作。

Linux运行在保护模式下,但是当机器启动复位的时候却处于实模式下。所以写Bootloader的工作也是在实模式之下的。

Botloader的实现除了依赖于CPU的体系结构,还依赖于目标板的设置,本系统的Bootloader引导程序分为stagel和 stage2两个阶段。依赖于CPU的体系机构的代码 ,比如设备初始化等,放在stagel中,采用ARM汇编语言来实现,这样可以达到短小精悍的目的。stage2用C语言来实现,可以实现复杂的功能,同 时代码具有更好的可读性和可移植性。

●Bootloader的stage1

stage1是Bootloader一开始就执行的操作,其目的是为了stage2的执行以及随后的内核的执行,设置好一些基本的硬件环境。

包括以下步骤 :

①屏蔽所有的中断 。为中断提供服务的通常是操作系统,因此在执行Bootloader的过程中可以不响应任何中断。中断屏蔽通过写CPU的中断屏蔽寄存器来完成。

②设置CPU的时钟频率和速度。

③初始化RAM设置系统的内存控制器的功能寄存器和各内存库控制寄存器等。

④为加载stage2准备RAM空间。

⑤拷贝stage2到RAM中。

⑥跳转到stage2的入口点。

●Bootloader的stage2

stage2的主要的功能是通过串口下载Linux内核到目标板上。

包括以下几个步骤:

①初始化本阶段要使用到的硬件设备。这通常包括:初始化至少一个串口,以便和终端用户进行I/O输出信息;初始化计时器等。

②检测系统的内存映射。所谓内存映射就是指在整个4GB物理地址空间中有哪些地址范围被分配用来寻址系统的RAM单元。

③加载内核映像和根文件系统从Flash读入到Rom中。这里包括两个方面:a.内核映像所占用的内存范围;b.根文件系统所占用的内存范围。在规划内存占用的布局时,主要考虑基地址和映像的大小两个方面。

④设置内核的启动参数。

⑤调用内核。Bootloader调用Linux内核的方法是直接跳转到内核的第一条指令处。


4 Linux内核的构建和移植

1)设置软件开发环境。

为了和目标板进行通讯,必须要在主机上终端运行仿真程序DNW。建议在宿主机上安装REDHATLinux9.0版本。以下以在SHELL模式下安装编译器和源代码为例介绍安装过程 :

首先以ROOT身份进入系统。把REDHATLinux90的安装光盘放入光驱中,执行装载光驱命令:


moumt/dev/cdrom /nmt/cdrom

如果系统不能识别/mnt/cdrom,可以使用如下命令(假设cdrom为/dev/had),则用mount -t iso9660 /dev/hdb/mnt。

如果在安装REDHATLinux9.0的时候已经默认安装了CDROM,以上命令不需执行,直接进入CDROM所在目录。


mkdir /usr/local/arm
mount /dev/cdrom /mnt/cdrom
cd/
cp /mnt/cdrom/bin/cross-2.95.3.tar.bz2 /usr/local/arm/
cp /mnt/cdrom/bin/Linux_for_s3c2410.gz
tar zxvf Linux_for_s3c2410.gz
cd /usr/local/arm/
tar -jxvf cross-2.95.3.tar.bz2

程序执行完后,Linux源代码和编译环境都已建立起来了。

2)Linux内核编译。

首先以ROOT身份进入系统。然后完成下列步骤,就可以在/Linux/arch/arm/boot/得到内核的映像文件zImage。

在shell命令下输入命令进行内核配置:

make menuconfig

该命令执行之后生成文件.config。它保存这个配置信息,下一次再执行make menuconfig的时候将生成新的.config文件。

输入命令 :make dep

输入命令 :make clean

输入命令 :make zImage

通过各个目录的Makefile进行,将会在各个目录下生成一系列目标文件,上述步骤完成后,就完成了对Linux的编译工作。

Linux内核的编译、修改、移植实际上与上层的应用程序,如命令解释器shell、登陆程序login相关。这些程序应根据需要重新定制。

利用终端仿真程序DNW和Bootloader引导程序通过串口就可以把Linux内核移植到目标系统板。移植完成后,Linux就可以在目标系统板上运行了。

5 结束语

讨论了Linux向目标系统S3C2410移植的过程中的关键技术及其实现。移植后的Linux保留了原有的工作稳定的特点。并可以根据需要,在该系统中编写应用程序和运行应用程序。


U-Boot在S3C2410上的移植分析

摘 要:介绍了一款优秀的嵌入式BootLoader—U-Boot,详细讲解了它的运行原理,着重讨论了其在S3C2410上的移植过程,并对移植结果进行了测试。

关键词:U-Boot;S3C2410;移植;BootLoader 

        引 言 

        BootLoader 是嵌入式系统软件开发的第一个环节,它紧密地将软硬件衔接在一起,对于一个嵌入式设备后续的软件开发至关重要。BootLoader还涉及到许多硬件相关 的知识,对于普通的嵌入式开发板,它又是不可跳过的步骤,所以做好它的移植工作是必须的,对于后续的开发工作也是有益的。U-Boot是当前比较流行、功 能强大的BootLoader,它操作简便,可以支持多种体系结构的处理器,同时提供了完备的命令体系。 S3C2410是三星公司一款基于ARM920T的嵌入式通用处理器。本文的移植平台就是以S3C2410 为核心的HHARM9-EDU-R2开发板,这块开发板的硬件资源配置较为完善。主要硬件资源有:S3C2410处理器;1片Intel TE28f128FLASH ( 16M);2片Hynix HY57V561620 SDRAM(64M);10/100M自适应网络芯片DM9000; USBHost/Device;RS232×2/RS485×1串口;LQ035FLM08L 256K色TFT真彩LCD显示屏;全功能JTAG调试口等。 

        U-Boot简介 

        U -Boot是Das U-Boot的简称,是由denx软件中心依照GPL 发布的公共软件,作为系统启动的引导模块,U-Boot支持多种处理器架构,比如Power-PC、ARM、MIPS和x86等。 目前,U-Boot源代码在sourceforge网站的社区服务器中, Internet上有一群自由开发人员对其进行维护和开发,它的项目主页是http://sourceforge.net/ projects/ u-boot。当下载并解压U-Boot 源码包后,会形成如下的目录结构:board,和一些已有开发板有关的文件;common,实现各种U-Boot 命令的C 文件;cpu,CPU相关文件,其中的子目录都是以U-Boot 所支持的CPU命名的;disk,disk驱动的分区处理代码;doc,文档;drivers,通用设备驱动程序;fs,支持文件系统的文件; include,头文件,对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件;net:与网络有关的代码; lib-arm,与ARM体系结构相关的代码;tools,创建S-Record 格式文件和U-Boot Images的工具。 

        本文中U-Boot的移植就是根据HHARM9-EDU-R2开发板的硬件资源在以上的目录中修改或者添加相关源文件,并且重新编译的过程。移植工作开始之前,了解U-Boot的运行过程是十分必要的。 

        U- Boot 运行过程分析 

        U -Boot编译后的代码定义一般不超过100kB,并且这100 kB又分成两个阶段来执行。第一阶段的代码在start.s中定义,大小不超过10 kB,它包括从系统上电后在0x00000000 地址开始执行的部分。这部分代码运行在Flash中,它包括对S3C2410的一些寄存器的初始化和将U-Boot的第二阶段代码从Flash拷贝到 SDRAM中。除去第一阶段的代码,剩下的部分都是第二阶段的代码。 第二阶段的起始地址是在第一阶段代码中指定的,被复制到SDRAM后,就从第一阶段跳到这个入口地址开始执行剩余部分代码。 第二阶段主要是进行一些BSS 段设置,堆栈的初始化等工作,最后会跳转到main-loop函数中,接受命令并进行命令处理。图1 给出了U-Boot的详细的运行过程包括对内核的设置、装载及调用过程。 

        图1 U-Boot运行过程

        了解了U-Boot 的运行过程以后,我们还必须确定开发板的地址空间分布,才可以进行源码的修改和移植工作。 地址空间的分布部分依赖于开发板的硬件配置及CPU 的复位地址。 本文中开发板的地址空间如图2 所示。 

        图2  开发板地址空间分布 

        U-Boot的移植与测试 

         为了使移植工作更加快捷,应当选择U-Boot当前发布的最新版本1.1.2 (尽管通过CVS可以得到U-Boot1.1.3,但其正在开发,尚未发布,不宜使用) 。 因为最新的版本可以提供尽可能多的处理器核及开发板的支持。 对于U-Boot-1.1.2 而言,它不仅提供对ARM- 920T内核的支持,而且直接提供了对于S3C2410 的板级支持,这使移植工作量相对减少。 

        支持ARM- 920T内核的代码修改 

        由于U-Boot-1.1.2 提供对ARM-920T 内核的直接支持,所以本步骤不需要做任何工作,本文为了让读者了解BootLoder 移植的通用模式,在此只是稍加提示。 

        配置自己的开发板 

        建立自己开发板的目录和相关文件。 

        1) 在include/ configs目录中以smdk2410.h为模板添加头文件S3C2410. h(cp smdk2410.h S3C2410.h) 。 这个文件是开发板的配置文件,它包括开发板的CPU、系统时钟、RAM、Flash系统及其它相关的配置信息。 

        2) 在board/目录下创建S3C2410目录。拷贝smdk2410目录下所有文件到S3C2410目录下,共有如下六个文件:flash.c、 memsetup.c、S3C2410.c、Makefile、U-Boot .lds 和config.mk,根据开发板实际情况对各个文件进行修改。 

        ◆flash.c.U-Boot读、写和删除Flash 设备的源代码文件。由于不同开发板中Flash 存储器的种类各不相同,所以,修改flash.c时需参考相应的Flash 芯片手册。它包括如下几个函数: 

        unsigned long flash-init (void ),Flash初始化;
  int flash-erase (flash-info-t *info,ints-first,ints -last),Flash擦除;
  volatile static int write- hword (flash-info-t *info,ulong dest , ulong data) ,Flash 写入;
  int write-buff (flash-info-t *info,uchar *src ,ulong addr,ulong cnt),从内存复制数据。 

        由于本文开发板所用flash芯片为IntelTE28f128,在board/ cmi目录中有此flash.c,只需对其稍加修改即可使用。 

        ◆memsetup.c.初始化时钟、SMC控制器和SDRAM控制器。为了以后能用U-Boot的GO命令执行修改过的用loadb或tftp下载的U-Boot.在标记符“0:”上加入五句:
   
        mov r3,pc
  ldr r4,= 0x3FFF0000
  and r3,r3,r4 / /以上三句得到实际起动的内存地址
  aad r0,r0,r3 / /用GO 命令调试uboot时,启动地址在RAM
  add r2,r2,r3 / /把初始化内存信息的地址,加上实际起动地址 

        ◆S3C2410.C.设置各种总线时钟,打开数据Cache和指令Cache,并设置相关内存参数。 

        ◆Makefile.修改:OBJS := S3C2410.o flash.omemsetup.o 

        ◆U-Boot.lds.作如下修改: 

        .text 
        { 
        cpu/ arm920t/ start.o ( .text) 
* (.text) 
        } 

        ◆config.mk.用于设置程序连接的起始地址,因为会在U-Boot 中增加功能,所以留下6M 的空间,修改33F80000 为33A00000。 

        实现网卡的驱动程序 
        在drivers/目录中以dm9000x.c和dm9000x.h为模板添加网口设备控制程序dm9000.c和dm9000.h,其中dm9000.c主要包括以下函数: 

        int eth-init (bd-t *bd),初始化网络设备; 
        int eth-send(volatile void *,int),发送数据包; 
        int eth-rx(void),接收数据包。 
        void eth-halt (void),关闭网络设备; 

        为了方便网络设备的数据读写操作,还定义了如下函数: 

        static int dm9000-probe (void),搜索DM9000芯片,分配空间并登记之; 
        static u16 phy-read(int),从Phyxcer寄存器读取一个字; 
        static void phy-write ( int,u16),写一个字到Phyxcer 寄存器; 
        static u16 read-srom-word (int),从SROM 读取一个字数据; 
        static u8 DM9000-ior (int),从I/ O 口读取一个字节; 
        static void DM9000-iow(int reg,u8 value),写一个字节到I/ O 口; 
        最后在drivers/Makefile中加入dm9000.o。 

        修改Makefile 文件     
        在U-Boot-1.1.2/Makefile中ARM92xT Systems注释下面加入以下两行: 
        S3C2410-config :unconfig
  @./ mkconfig $( @:-config = ) arm arm920tS3C2410     

        其中“arm”是CPU的种类,arm920t是ARM CPU对应的代码目录,S3C2410是自己开发板对应的目录。 

        交叉编译器安装在:/ path/ armv4l-unknown -linux-目录下,所以把CROSS-COMPILE 设置成相应的路径: CROSS-COMPILE = / path/ arm4l-unknown-linux - 

        生成目标文件并进行测试 
        依次运行以下命令:     

        # make clean 
        # make S3C2410-config 
        # make 

        之后会生成三个文件: 

        U-Boot ——ELF 格式的文件, 可以被大多数Debug 程序识别; 
        U-Boot.bin ——二进制文件,纯粹的U-Boot 

        二进制执行代码,不保存ELF 格式和调试信息。 这个文件一般用于烧录到用户开发板中;U-Boot .srec ——Motorola S-Record格式,可以通过串行口下载到开发板中。 

        测试与应用 
        1) 测试 
        利用编制好的Flash烧写程序,通过JTAG口将生成的二进制文件U-Boot。bin烧入Flash的零地址。 烧录成功后,拔掉JTAG调试线并复位开发板,从Minicom终端输出如下信息: 

        U-Boot 1.1.2 (Jul 20 2005-09 :34 :21) 
        U-Boot code : 33F00000-> 33F1952C BSS:-> 33F1D870         
        RAM Configuration : 
        Bank # 0 : 30000000 64 MB 
        Flash Memory Start 0x0000000 
        Device ID of the Flash is 18 
        Flash : 16 MB 
        Write 18 to Watchdog and it is 18 now 
        In : serial 
        Out : serial 
        Err : serial 
        SMDK2410 # 

         串口输出的以上信息表明,CPU和串口已正常工作。通过U-Boot提供的命令flinfo和mtest可以测试Flash和RAM。经过测试,可以正确 地读出Flash信息及读写RAM,表明Flash 和DRAM 已正确初始化。 用tftp命令传输宿主机tftpboot目录下任一小文件到RAM成功,说明网卡芯片也成功驱动。 

        2) 简单应用 
        U -Boot的主要作用是用来引导内核。因此,通过U-Boot引导一个特定的内核,可以进一步测试其移植的稳定性。 而使用U-Boot引导内核有两种不同的方法。第一种方法是直接将内核映象文件和根文件系统烧写入Flash,使用此方法,U-Boot在启动时将 Flash中的内核映象及根文件系统读入RAM指定位置并从同一位置启动内核。 第二种方法是将内核映象文件和根文件系统下载至RAM中直接启动(而不是从Flash中读入RAM) ,此种方法不需要烧写Flash。笔者为了减少烧写Flash的次数,在本文中采用第二种方法,其步骤如下: 

        SMDK2410 # tftp 30008000 zImage 
        SMDK2410 # tftp 30800000 ramdisk.Image.gz         
        SMDK2410 # go 30008000 

         上述指令执行的过程中,未出现异常,内核成功启动,并最终进入Shell提示符“ # ”。在Shell提示符下输入内核编译时定制的各个命令,均可以正常运行。另外编写简单C程序,并用交叉编译器编译之,最终生成的可执行文件能够在开发板 上正常运行。上述事实说明内核经过U-Boot引导已稳定运行在开发板上。此次应用,进一步验证了U-Boot移植的稳定性。至此,移植工作告一段落。 

        结 语 

         目前,笔者移植的U-Boot已经能稳定地运行在开发板上,这使得Linux内核的调试脱离了BDM调试器,节约了大量的开发时间,大大提高了效率,是对 后续嵌入式开发的有力支持。 当然,U-Boot只是一款好用的BootLoader,嵌入式Linux的开发存在很多技术细节,只有根据实际情况不断修改、调试、总结,才能获得更大 的成功。