2、U-Boot 移植
从网上下载源码 u-boot-2010.12,实现如下功能:
1)支持S3C2440;
2)支持串口协议;
3)支持网卡芯片DM9000;
4)支持不同Nand Flash 的读写
5)支持IIC 接口EEPROM 的操作,并可保存ENV;
6)支持烧写yaffs/yaffs2 文件系统映象;
7)支持使用DNW工具,通过USB device 口进行文件传输。
a、U-Boot 的启动过程分为Stage1 和Stage 2 两个阶段。
U-Boot 的Stage 1 位于start.S 文件,使用汇编语言编写。针对ARM920T 体系的start.S 文件,流程如下:
硬件初始化,如CPU寄存器SDRAM等;为加载Stage2 准备内存空间;设置好栈堆指针sp,并跳转到Stage2的C函数入口点:
(1) 设置异常向量表。ARM 处理器包括复位、未定义指令、SWI、预取终止、数据终止、IRQ、FIQ 七种异常。异常向量从地址0 开始, 每个向量是一条 4 字节的跳转语句。
(2) 设置 CPSR 寄存器的模式位域,设置 CPU 模式为 SVC 模式
(3) 关闭看门狗
(4) 设置 CPU 工作频率,高速总线频率,外围总线频率
(5) 设置 CP15 协处理器。CP15 是系统控制和内存管理协处理器。U-Boot 设置 CP15 的目的是声明 ICach(e指令 Cache)和 DCache
(数据 Cache)失效,然后禁止 MMU 和 Cache。
(6) 配置储存区控制寄存器 BWSCON、BANKCON1-7。
(7) 配置堆栈空间。配置代码段的开始地址、动态内存区长度、全局数据的大小以及分配 IRQ 和 FIQ 的栈空间。
(8) 初始化 RO、RW、ZI 段。
(9) 进入 C 代码。利用 LDR 伪操作将 C 语言的入口地址装入 PC(程序指针寄存器),从而跳转到 C 代码去运行。
Stage 2 用C语言实现。主要工作是:(1)命令行模式处理串口输入的命令(2)引导Linux内核。
1)初始化本阶段使用到的硬件设备,如USB,声卡等;
2)将内核映像和根文件系统映像从flash上读到内存中;
3)设置好系统的启动参数后调用内核。
b、移植U-Boot
从ftp://ftp.denx.de/pub/u-boot/下载 U-Boot 源码;先删除与我们硬件无关的文件。
board:以Samsung 的smdk2410 为模板,其他的都删了。
arm:即CPU,我们的CPU 为arm920t,其余的删了。
(1)修改Makefile。
主要是针对 ARCH(CPU 体系架构) 和CROSS_COMPILE 变量(定义交叉编译器的前缀名)。
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
(2)增加目标板的编译选项。
EmbedSky_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t EmbedSky NULL s3c24x0
EmbedSky_config 表示增加名为EmbedSky_config 的编译目标;arm 指 arm 体系结构; arm920t 表示编译cpu/arm920t 子目录;EmbedSky 表示编译 board/EmbedSky子目录;s3c24x0 表示编译 cpu/arm920t/s3c24x0 子目录。
(3)参考 smdk2410 建立 EmbedSky 目标板目录
cp -fr board/smdk2410 board/EmbedSky
cd board/EmbedSky
mv smdk2410.c EmbedSky .c
(4)修改 EmbedSky 目录的Makefile
vim Makefile
遵守 make 编译规则,将
COBJS := smdk2410.o flash.o
改为COBJS := EmbedSky.o flash.o boot_init.o
(5)建立目标板头文件
cd include/configs
cp -fr smdk2410.h EmbedSky.h
vim EmbedSky.h
加入如下语句使 U-Boot 支持 USB 烧写和 DM9000 网卡:
#define CONFIG_USB_DEVICE 1
#ifdef CONFIG_USB_DEVICE
#define CONFIG_USE_IRQ 1
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_USE_16BIT 1
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO 0x20000000
#define DM9000_DATA 0x20000004
(6)编译
cd ${U-ROOT}
make mini2440_config
make
编译完成后在${U-ROOT}目录生成如下映像文件:
u-boot.bin:原始二进制文件,下载到 ROM 运行
u-boot:ELF 格式映像文件,可加载到 SDRAM 调试
u-boot.srec:Motorola S-Record 格式映像
System map:U-Boot 映像符号表,各符号的链接地址
c、改写U-Boot编译成功表示初步移植无误,但是这个 u-boot.bin 在改写之前还不能用于本硬件系统。
上面移植的 U-Boot 只能从Nor Flash 启动。但我们的 MP3 制作好之后是从 NAND Flash 启动的,所以必需改写 U-Boot 代码使其具有从 Nand Flash 启动的功能。
S3C2440 的引脚 OM[1:0]控制系统的启动方式:
(1)上电时如果 OM=10,处理器就从 BANK 0 的 NOR Flash 读取代码;
(2)如果 OM=00,处理器把 NAND Flash 的前4KB 内容读取到内部的启动 RAM 中,然后将该启动 RAM 映射到地址 0 处并开始运行。启动代码一般是 100KB 以上,远大于启动 RAM 的容量,所以如果要从Nand Flash 启动,需要在 Boot 代码开始不久后,将代码从 NAND Flash 搬运到SDRAM 中,在 SDRAM 中继续运行。
改写 U-Boot ,使其具备从 NAND Flash 启动:
(1)系统启动时会自动判断
系统判断:无论从NOR Flash 启动还是从 NAND Flash 启动,地址 0x0 处始终为指令"b Reset", 机器码为 0xEA00000B。
对于从 NAND Flash 启动的情况,其开始 4KB 的代码会复制到 CPU内部 4KB 的启动 RAM 中
对于从 NOR Flash 启动的情况,NOR Flash 的开始地址即为 0,因为 NOR Flash 必须通过一定的命令序列才能写入数据,所以可以根据这点差别来分辨是从 NAND Flash 还是 NOR Flash 启动。分辨方法是向地址 0x0 写入一个数据,然后读出来,如果没有改变的话就是 NOR Flash 启动,否则就是 从 NAND Flash 启动,将这个功能包装在 bBootFrmNORFlash()函数中。然后将启动方式判断、拷贝代码到 SDRAM 系列功能包装在 CopyCode2Ram()函数当中。
增加读取 Nand Flash 的函数 nand_read()。 读取的的方法是依次向 IO端口写命令、地址,然后从IO 端口读出数据。
修改 start.S 文件。让代码调用CopyCodeRam()函数,不执行原来的指令。
调试U-Boot :调试使用 JTAG 硬件调试器和 ADX Debugger 软件,可实现对照源代码调试。先用 objdump 生成反汇编代码:
将 u-boot 目录拷贝到 Windows 中,选择 ADX 的 Load Image 加载 u-boot 到内存,然后加载 u-boot.S 反汇编文件即可调试 U-Boot。 使用 JTAG 连线连接主机和目标板,使用 Windows 下的 Jtag 工具将其烧 写到 NAND Flash 的地址 0 处。使用串口连线连接好主机和目标板,打开 SecureCRT 看到 U-Boot 的输出文字,即 表示 U-Boot 移植成功。arm-softfloat-linux-gnu-objdump –S u-boot >u-boot.S