嵌入式系统设计实验三
合肥学院
嵌入式系统设计实验报告
(20 13- 2014第2学期)
专 业: 11级自动化卓越班 实验项目: BootLoader 移植实验
实验成员:
指导老师: 实验时间: 2014 年 5 月 14 日
电子信息与电气工程系
2014年4月制
目录
一、实验目的 ............................................................................................................... 3
二、实验内容 ............................................................................................................... 3
三、实验步骤 ............................................................................................................... 3
3.1、u-boot 简介 ................................................................................................... 3
3.2、移植环境....................................................................................................... 4
2.3、u-boot 移植要点 ........................................................................................... 4
2.4、光盘自带源码移植....................................................................................... 4
四、思考题 ................................................................................................................... 4
4.1、Bootloader 的结构分两部分,简述各部分的功能。 . ............................. 42
4.2、ARM 常用的Bootloader 程序有哪些?简要说明。 . .............................. 42
4.3、简述uboot 的启动的两部分流程。 ......................................................... 44
4.3.1、U-Boot 第一阶段............................................................................. 44
4.3.2、U-Boot 第二阶段............................................................................. 44
五、实验总结 ............................................................................................................. 45
实验三 BootLoader 移植实验
一、实验目的
1、熟悉Bootloader 工作原理。 2、了解U-Boot 的代码结构。 3、掌握U-Boot 移植过程。
二、实验内容
本实验熟悉Bootloader 工作原理,了解U-Boot 源码结构,基于S3C2440处理器,完成U-Boot 移植,并在目标开发板上测试通过。
三、实验步骤
3.1、u-boot 简介
u-boot 是德国DENX 小组的开发用于多种嵌入式CPU 的bootloader 程序, u-boot不仅仅支持嵌入式Linux 系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS,
LynxOS 嵌入式操作系统。u-boot 除了支持PowerPC 系列的处理器外,还能支持MIPS 、 x86、ARM 、NIOS 、XScale 等诸多常用系列的处理器。
3.2、移植环境
Linux 平台:ubuntu10.04
交叉编译工具:arm-linux-gcc-4.3.3 arm 开发板:micro2440 CPU :S3C2440 SDRAM :64M Nor Flash:2M Nand Flash:256M 网卡:DM9000EP
3.3
、u-boot 移植要点
(1)获取源码
(2)建立自己的硬件平台配置。 (3)实现bootloader 的相关功能。 (4)编译调试和功能测试。
3.4、光盘自带源码移植
(1)拷贝源码,建立工作目录 这里使用的是u-boot-1.1.6.tar.bz2 (2)建立工作目录: #mkdir /home/uboot #cd /home/uboot
把下载的源码拷贝到该目录, 解压; #tar jxvf u-boot-1.1.6.tar.bz2
(3)配置和编译 U-Boot
本实验用的U-Boot 已配置好, 具有以下功能特性: 同时支持S3C2410 和S3C2440 支持串口xmodem 协议
支持USB 下载,可以在 PC 上使用 dnw 传数据 支持网卡芯片CS8900 支持NAND Flash 读写
支持从Nor/Nand Flash 启动 支持烧写yaffs 文件系统映象 可以直接下载到内存运行 编译:
#make open24x0_config ;配置 U-Boot #make
就可以开始编译了,编译完毕,如图所示生成u-boot.bin 。
uboot.bin 下载成功后的界面,把开发板启动模式改为Nand Flash 启动,重新复位或者重启开机电源开关,在SuperVivi-USB-Transfer-Tool 上可以看到如图信息。
使用u-boot 常用命令 (1)打印环境变量
(2)设置环境变量
(3)保存设定的环境变量
(4)擦除nand flash中数据块
(5)把RAM 中的数据写到Nand Flash中
(6)从nand flash中读取数据到
RAM
(7)直接跳转到可执行文件的入口地址,执行可执行文件
5、官网下载u-boot 移植实现 (1)下载源码,建立工作目录
uboot 的源码可以从官网下载,这里下载的是u-boot-2011.03.tar.bz2 (2)建立工作目录: #mkdir /home/uboot
#cd /home/uboot
把下载的源码拷贝到该目录, 解压; #tar jxvf u-boot-2011.03.tar.bz2
解压完成后想要进入目录但是有问题,在查阅相关资料后成功进入相应的目录
(3)建立自己平台Micro2440 配置 1)[u-boot-2011.03]$ vim boards.cfg
在执行本条指令时显示相应的安装包没有安装,联网后再次执行就下载相应的安装包同时执行相应指令
添加一行 micro2440 arm arm920t - samsung s3c24x0
先点击ESC 退出编辑格式到命令格式再点击两次Z 即可保存并退出vim 。 2)创建板级支持文件
[u-boot-2011.03]$ cp -r board/samsung/smdk2410 board/samsung/micro2440
[u-boot-2011.03]$ cd board/samsung/micro2440/ [micro2440]$ mv smdk2410.c micro2440.c [micro2440]$ vim Makefile
COBJS := smdk2410.o flash.o 改为COBJS := micro2440.o flash.o
先点击ESC 退出编辑格式到命令格式再点击两次Z 即可保存并退出vim 。
[u-boot-2011.03]$ cd ../../..
[u-boot-2011.03]$ cp include/configs/smdk2410.h include/configs/micro2440.h [u-boot-2011.03]$ vim include/configs/micro2440.h
修改一:
#define CONFIG_SYS_PROMPT "[Micro2440]# " /* Monitor Command Prompt */
修改二:
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
(4)测试编译 [u-boot-2011.03]$ make micro2440_config
[u-boot-2011.03]$ make
执行后出现如下错误,从中可知,在micro2440.h 中的130行多了“[”
再次执行vim micro2440.h 删除多余的“[”,再次执行make micro2440_config和make
开始编译了,编译完毕,生成u-boot.bin 。
(5)按照移植目标逐个移植编译调试并测试功能。 移植目标
支持Nand 启动 支持Nand 读写 支持yaffs 写入 支持tftp 下载
6、烧写U-Boot 到开发板
要烧写 U-Boot ,需要把开发板拨动开关S2 设置为Nor Flash启动,连接好串口和USB 线,打开超级终端,打开电源,串口显示如图:
选择功能号 “d ”,打开DNW(修改下载地址为:33f80000) ,确认USB 连接正常OK ,点 UsbPortÆTransmit/Restore,选择刚才所编译的 u-boot.bin ,下载和烧写很快就会结束。 把开发板启动模式改为Nand Flash 启动,重新复位或者重启开机电源开关,在串口终端可以看到如图信息,如果开发板中已经安装了 linux 系统,U-Boot 将会自动启动它,否则会进入 U-Boot 的功能菜单(也可以根据提示,在开机后 3 秒中内按任意键进入) :
7、在RAM 中运行
(1)
include/configs/micro2440.h
删除
#define CONFIG_S3C2410 1 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */ 未删除前的界面
将相应的两条指令删除。 删除后的界面
添加 #define CONFIG_S3C2440 1 /* specifically a SAMSUNG S3C2440 SoC */ #define CONFIG_MICRO2440
#define CONFIG_SKIP_LOWLEVEL_INIT 添加后的界面
保存后退出。
(2)
arch/arm/cpu/arm920t/start.S
更改前
更改后(部分截图)
(3)board/samsung/micro2440/micro2440.c #define FCLK_SPEED 2
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */ #define M_MDIV 0xC3 #define M_PDIV 0x4
#define M_SDIV 0x1 #elif FCLK_SPEED==1 /* Fout = 202.8MHz */ #define M_MDIV 0xA1 #define M_PDIV 0x3 #define M_SDIV 0x1
#elif FCLK_SPEED==2 /* Fout = 405MHz */
#define M_MDIV 0x7F#define M_PDIV 0x2 #define M_SDIV 0x1 #endif
#define USB_CLOCK 2
#if USB_CLOCK==0 #define U_M_MDIV 0xA1 #define U_M_PDIV 0x3 #define U_M_SDIV 0x1 #elif USB_CLOCK==1 #define U_M_MDIV 0x48 #define U_M_PDIV 0x3 #define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38 #define U_M_PDIV 0x2 #define U_M_SDIV 0x2 #endif int board_init (void) { ......
gd->bd->bi_arch_number = MACH_TYPE_MINI2440; ...... }
int dram_init (void) {
......
gd->ram_size = PHYS_SDRAM_1_SIZE; return 0; }
更改前
更改后
(4)测试编译环境
[www.linuxidc.com@linuxidc u-boot-2011.03]$ make micro2440_config
从图中可以看出在编译环境存在两个错误,根据相关提示找到相应的错误发现在start.S 文件中存在两个#endif,注释一个后重新编译即可成功
输入make 指令后发现micro2440.c 文件中依然存在两个错误
更改指令到相应目录中去
查阅micro2440.c 中的相应指令可以看出自己修改过程中有部分错误,重新修改后保存再次执行make
即生成相应的uboot.bin 文件
8、支持DM9000
(1)include/configs/micro2440.h 执行相关指令进入到文件中
删除
#define CONFIG_CS8900 /* we have a CS8900 on-board */ #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 10.0.0.110
#define CONFIG_SERVERIP 10.0.0.1
添加
#define CONFIG_CMD_NET
#define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_NO_SROM 1
#define CONFIG_DM9000_BASE 0x20000300 #define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4) #define CONFIG_CMD_PING
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b //开发板MAC 地址 #define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.10.126 //开发板IP 地址 #define CONFIG_SERVERIP 192.168.10.124 //主机IP 地址
(2)board/samsung/micro2440/micro2440.c int board_eth_init(bd_t *bis) { int rc = 0;
#ifdef CONFIG_CS8900 rc = cs8900_initialize(0, CONFIG_CS8900_BASE); #endif
//new for DM9000
#ifdef CONFIG_DRIVER_DM9000 rc = dm9000_initialize(bis); #endif return rc; }
#endif
(3) arch/arm/lib/eabi_compat.c int raise (int signum) {
//new for DM9000
#ifndef CONFIG_MICRO2440 printf("raise: Signal # %d caught\n", signum);
//new for DM9000 #endif return 0;
}
(4)
drivers/net/dm9000x.c
执行
root@ubuntu:/home/uboot/u-boot-2011.03# make micro2440_config
再执行root@ubuntu:/home/uboot/u-boot-2011.03# make
即可生成相应uboot.bin 文件
9、支持内核启动
(1)include/conskfigs/micro2440.h 添加
#define CONFIG_SETUP_MEMORY_TAGS 1 //如果没有定义这个参数,则uboot 参数必须加入men=内存大小
#define CONFIG_INITRD_TAG 1
#define CONFIG_CMDLINE_TAG 1 //设置bootargs 出入内核必须
#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
(2)
arch/arm/lib/bootm.c
(3)自动启动内核(此步未做)
如果要自动启动内核,需要在include/conskfigs/micro2440.h定义CONFIG_BOOTCOMMAND,类似如下内容:
#define CONFIG_BOOTCOMMAND "nand read 0x30008000 0x60000 0x300000;bootm 0x30008000"
执行
root@ubuntu:/home/uboot/u-boot-2011.03# make micro2440_config
再执行make
即可生成相应的uboot.bin 文件
10、支持Nand Flash
(1)添加s3c2440_nand.c(部分截图)
(2)drivers/mtd/nand/Makefile 添加
#define CONFIG_MTD_DEVICE #define CONFIG_NAND_S3C2440
#define CONFIG_CMD_NAND #if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4E000000 //Nand配置寄存器基地址 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #endif
#define CONFIG_ENV_IS_IN_NAND 1
#define CONFIG_ENV_OFFSET 0x40000 //将环境变量保存到nand 中的0x40000位置
#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
执行make micro2440_config
再执行make 出现以下问题
按照相关说明去重后,又出现了新的问题
在老师的指导和同学的帮助下更改后即成功编译了并生成了相应的bin 文件
11、支持yaffs 下载
(1)在include/conskfigs/micro2440.h中添加相应宏定义
添加后的图形如下所示
(2)在drivers/mtd/nand/nand_util.c做相应的更改(部分截图)
(3)按照相应参考做更改后即执行make 指令
在drivers/mtd/nand/nand_util.c中添加关于withoob 之后再进行编译即可生成相应的bin 文件
12、支持Nand Flash启动 (1)创建
nand_read.c
(2)更改
board/samsung/micro2440/Makefile
(3)更改
arch/arm/cpu/arm920t/u-boot.lds
(4)更改arch/arm/cpu/arm920t/start.S(部分截图)
(5)更改
include/configs/micro2440.h
(6)更改
arch/arm/lib/board.c
全部更改后执行make
出现相应的错误,再查阅资料和老师的指导下成功编译
13、测试阶段
首先选择v 下载编译成功的u-boot.bin 文件
然后按b
启动内核
将开发板从Nor 打到Nand Flash,关闭电源后重启
说明已经可以支持Nand Flash启动了。
四、思考题
4.1、Bootloader 的结构分两部分,简述各部分的功能。 分为stage1和stage2两个阶段。
stage1完成的工作:
硬件设备初始化。
为加载Bootloader 的stage2准备RAM 空间。
拷贝Bootloader 的stage2到RAM 空间中。
设置堆栈。
跳转到stage2的C 入口点。
stage2完成的工作:
初始化本阶段要使用到的硬件设备。
监测系统内存映射。
将内核映像和根文件系统映像从Flash 设备上复制到RAM 空间中。
设置内核启动参数。
调用启动内核。
4.2、ARM 常用的Bootloader 程序有哪些?简要说明。
1.U-BOOT 介绍
uboot 是一个庞大的公开源码的软件。他支持一些系列的arm 体系,包含常见的外设的驱
动,是一个功能强大的板极支持包。其代码可以从http://sourceforge.net/projects/u-boot下载 U-BOOT 是由PPCBOOT 发展起来的,是PowerPC 、ARM9、Xscale 、X86等系统通用的Boot 方案,从官方版本 0.3.2开始全面支持SC 系列单板机。u-boot 是一个open source 的bootloader ,目前版本是0.4.0。u-boot 是在ppcboot 以及armboot 的基础上发展而来,虽然宣称是0.4.0版本,却相当的成熟和稳定,已经在许多嵌入式系统开发过程中被采用。由于其开发源代码,其支持的开发板众多。唯一遗憾的是并不支持我们现在学习所用samsung 44B0X 的开发板。
为什么我们需要u-boot ?显然可以将ucLinux 直接烧入flash ,从而不需要额外的引导装载程序(bootloader )。但是从软件升级的角度以及程序修补的来说,软件的自动更新非常重要。事实上,引导装载程序(bootloader )的用途不仅如此,但仅从软件的自动更新的需要就说明我们的开发是必要的。
同时,u-boot 移植的过程也是一个对嵌入式系统包括软硬件以及操作系统加深理解的一个过程。
2.vivi 介绍(下载地址)
vivi 是韩国mizi 公司开发的bootloader, 适用于ARM9处理器。 Vivi 有两种工作模式:启动加载模式和下载模式。启动加载模式可以在一段时间后(这个时间可更改)自行启动linux 内核,这时vivi 的默认模式。在下载模式下,vivi 为用户提供一个命令行接口,通过接口可以使用vivi 提供的一些命令,如下:
命令
功能
Load
把二进制文件载入Flash 或RAM
Part
操作MTD 分区信息。显示、增加、删除、复位、保存MTD 分区
Param
设置参数
Boot
启动系统
Flash
管理Flash ,如删除Flash 的数据
vivi 代码分析
vivi 的代码包括arch ,init ,lib ,drivers 和include 等几个目录,共200多条文件。 Vivi 主要包括下面几个目录:
arch :此目录包括了所有vivi 支持的目标板的子目录,例如s3c2410目录。
drivers :其中包括了引导内核需要的设备的驱动程序(MTD 和串口)。MTD 目录下分map 、nand 和nor 三个目录。
init :这个目录只有main.c 和version.c 两个文件。和普通的C 程序一样,vivi 将从main 函数开始执行。
lib :一些平台公共的接口代码,比如time.c 里的udelay()和mdelay()。
include :头文件的公共目录,其中的s3c2410.h 定义了这块处理器的一些寄存器。Platform/smdk2410.h定义了与开发板相关的资源配置参数,我们往往只需要修改这个文件就可以配置目标板的参数,如波特率、引导参数、物理内存映射等。
4.3、简述uboot 的启动的两部分流程。
4.3.1、U-Boot 第一阶段 u-boot 的启动过程是多阶段实现的,分了两个阶段。
依赖于cpu 体系结构的代码(如设备初始化代码等)通常都放在stage1中,而且通常都是用汇编语言来实现,以达到短小精悍的目的。而stage2则通常是用C 语言来实现的,这样可以实现复杂的功能,而且代码具有更好的可读性和可移植性。代码真正开始是在_start,设置异常向量表,这样在cpu 发生异常时就跳转到/cpu/arm7tdmi/interrupts中去执行相应得中断代码。在interrupts 文件中大部分的异常代码都没有实现具体的功能,只是打印一些异常消息,其中关键的是reset 中断代码,跳到reset 入口地址。
reset 复位入口之前有一些段的声明。
1. 在reset 中,首先是将cpu 设置为svc32模式下,并屏蔽所有irq 和fiq 。
2. 在u-boot 中除了定时器使用了中断外,其他的基本上都不需要使用中断,比如串口通信和网络等通信等,在u-boot 中只要完成一些简单的通信就可以了,所以在这里屏蔽掉了所有的中断响应。
3. 初始化外部总线。这部分首先设置了I/O口功能,包括串口、网络接口等的设置,其他I/O口都设置为GPIO 。然后设置BCFG0~BCFG3,即外部总线控制器。这里bank0对应Flash ,设置为16位宽度,总线速度设为最慢,以实现稳定的操作;Bank1对应DRAM ,设置和Flash 相同;Bank2对应RTL8019。
4. 接下来是cpu 关键设置,包括系统重映射(告诉处理器在系统发生中断的时候到外部存储器中去读取中断向量表)和系统频率。
5.lowlevel_init,设定RAM 的时序,并将中断控制器清零。这些部分和特定的平台有关,但大致的流程都是一样的。
下面就是代码的搬移阶段了。为了获得更快的执行速度,通常把stage2加载到RAM 空间中来执行,因此必须为加载Boot Loader的stage2准备好一段可用的RAM 空间范围。空间大小最好是memory page大小(通常是4KB) 的倍数。一般而言,1M 的RAM 空间已经足够了。
flash 中存储的u-boot 可执行文件中,代码段、数据段以及BSS 段都是首尾相连存储的,所以在计算搬移大小的时候就是利用了用BSS 段的首地址减去代码的首地址,这样算出来的就是实际使用的空间。
程序用一个循环将代码搬移到0x81180000,即RAM 底端1M 空间用来存储代码。
然后程序继续将中断向量表搬到RAM 的顶端。由于stage2通常是C 语言执行代码,所以还要建立堆栈去。在堆栈区之前还要将malloc 分配的空间以及全局数据所需的空间空下来,他们的大小是由宏定义给出的,可以在相应位置修改。
4.3.2、U-Boot 第二阶段
下来是u-boot 启动的第二个阶段,是用c 代码写的,这部分是一些相对变化不大的部分,我们针对不同的板子改变它调用的一些初始化函数,并且通过设置一些宏定义来改变初始化的流程,所以这些代码在移植的过程中并不需要修改,也是错误相对较少出现的文件。在文件的开始先是定义了一个函数指针数组,通过这个数组,程序通过一个循环来按顺序进行常规的初始化,并在其后通过一些宏定义来初始化一些特定的设备。在最后程序进入一个循环,main_loop。这个循环接收用户输入的命令,以设置参数或者进行启动引导。
五、实验总结
通过本次实验本我们熟悉了Bootloader 的工作原理,了解了U-Boot 源码结构,基于S3C2440处理器,完成U-Boot 移植,并在目标开发板上通过了测试。 我们小组通过团结合作、合理分工最终成功完成了实验的所有内容。通过实验,我们学习到合作的力量是无穷的,我们深刻感受到学习的无穷魅力,深深的被折服了。感叹嵌入式系统开发的无穷快乐。 在此要非常非常感谢干老师的细心指导,是您的辛勤付出才换回来我们满满的收获,谢谢老师!