UBOOT的版本更新速度比较快,截止今天,稳定正式的版本是u-boot-2009.11-rc2,而TI最新的EVM开发包里的UBOOT是1.2.0版本,国内不少公司还一直使用u-boot-1.1.4和u-boot-1.1.6。其实,咱们也不必追风跟上最新版本,程序跑稳定才是最重要的。固然,有兴趣研究研究也不错,毕竟最新版本增长不少实用的功能。在移植以前,咱们简单介绍u-boot这些版本架构的变化。从u-boot-1.3.0到u-boot-1.3.2基本上架构是同样的,而从u-boot-1.3.3到u-boot-1.3.4,架构相对u-boot-1.3.2变化比较大。从u-boot-2008.10开始,nand flash驱动变化很是大,u-boot-2009.03增长强大的lzma压缩解压功能,fs支持yaffs2,u-boot-2009.06 nand flash变化更大。到u-boot-2009.11.1增长DM6467 DM365的支持。
关于u-boot-1.3.4的移植,本人的博客也介绍在三星s3c2440上移植过,咱们在这里主要针对davinci 平台。因为UBOOT功能不少,要所有把移植的东西马上写出来,对本人仍是有难度,因此中间会先发布有关montavista linux-2.6.18的移植,如何把DSP程序先跑起来,等等。因为本人的主要工做是开发产品,卖卖DM6446核心板、DM6437核心板,及相关开发板,智能视频监控IVR,推推DSP方案,因此博客更新速度比较慢,其实写博客的目的,有很大的部分就是想和全国各地朋友交流技术。同时这里要感谢51CTO的小松管理员,把本人的开发攻略改成推荐博文。回到移植正题,咱们一步一步把UBOOT跑起来,把内核也跑起来。鉴于学习的目的,本人这里不提供patch
。
< XMLNAMESPACE PREFIX ="O" />
第一步:解压和简化
UBOOT
从ftp.denx.de下载u-boot-1.3.4.tar.bz2或u-boot-1.3.4-rc2.tar.bz2,而后解压到你的工做目录,不少人解压完后,就立刻进入正题,修改makefile什么的,本人以为不用那么急。首先删除和平台不相关的文件和文件夹,目的让UBOOT更简化,好理解,减小虚拟机的存储空间,便于备份(每次有进展的修改后,备份和修改记录很重要,这是良好习惯):
在顶层目录:把文件avr32_config.mk,blackfin_config.mk,i386_config.mk,m68k_config.mk,microblaze_config.mk,mips_config.mk,nios2_config.mk,nios_config.mk,ppc_config.mk,sh_config.mk,sparc_config.mk删除;文件夹lib_avr32,lib_blackfin,lib_i386,lib_m68k,lib_microblaze,lib_mips,lib_nios,lib_nios2,lib_ppc,lib_sh,lib_sparc,nand_spl,onenand_ipl,其余就不要删了。
在board目录下:只保留davinci文件夹,其余平台板子所有干掉!男人就要狠一点。而davinci也只保留TI 本身的dv-evm文件夹,这也是咱们要修改的平台,schmoogie、sffsdr、sonata是其余公司基于davinci上的板子,你能够删掉,也能够参考。固然,仍是在board\davinci目录下,你能够COPY dv-evm并改为你公司的板子的名字,而后在顶层修改makefile支持你公司的板子,下一步再说。
在cpu的目录:只保留arm926ejs,其余CPU所有干掉。进入arm926ejs目录,同时把at91sam9、omap、versatile文件夹删除,保留davinci和其余文件。
在include目录:把文件夹asm-avr32、asm-blackfin、asm-i386、asm-m68k、asm-microblaze、asm-mips、asm-nios、asm-nios2、asm-ppc、asm-sh、asm-sparc删除掉。进入configs目录,只保留davinci_dvevm.h,其余*.h文件所有删除调!
作完以上的工做后,UBOOT至关简洁,其实还有一些文件和文件能够再删,不过已经不必,咱们删除的对象是其余不相关的平台。备份一下这个源版本,便于往后本身修改的UBOOT和这个源版本比较。
第二步:连接交叉编译环境
若是你已经看过本人有关《DAVINCI DM6446开发攻略——环境搭建篇》,按里边描述的方法,对交叉编译环境进行搭建,那么下面编译工做就好进行了。
修改顶层makefile:
在144行:把CROSS_COMPILE = arm-linux-改成CROSS_COMPILE = arm_v5t_le-
在282行:把ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND),改成ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) u-boot.img,就是后面添加u-boot.img
在308行:./tools/mkimage -A $(ARCH) -T firmware -C none \后面,添加和注销如下代码:
-a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
-e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
-n 'u-boot image' -d $< $@
# -a $(TEXT_BASE) -e 0 \
# -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
# sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
# -d $< $@
(注意要加tab键)
这里这样作的目的,生成的u-boot.img能够被上篇介绍的UBL给BOOT起来,而u-boot.bin能够被TI提供的uart_load.exe 和uartapp.bin 软件方式(soft boot)启动起来,便于生产和测试。
在源makefile文件2416行:就是davinci_dvevm_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm926ejs dv-evm davinci davinci
根据这一行,你能够参考TI 这个作法定义本身的板子,添加本身板子的config,好比加入:
davinci_dm6446_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm926ejs dm6446 davinci davinci
而后在board\davinci目录下,使用
mkdir dm6446
cp –f dv-evm/* dm6446/
同时进入include/configs/目录,使用cp –f davinci_dvevm.h davinci_dm6446.h
注:其实直接在TI dv-evm上移植也能够,不必定义本身的板子和配置。这里只不过给你们举个例子。
编译工做:
$make distclean
$make davinci_dm6446_config
$make
看是否编译所有经过,是否生成u-boot.bin和u-boot.img等文件,同时检查你的交叉编译环境是否创建好,没问题继续往下进行。
第三步:移植板子驱动和配置
一、
修改davinci_dm6446.h
首先说说本人板子的信息:DDR2——256M-Byte,NAND——128M-Byte——2K Page; 通用网口PHY芯片,没有NOR FLASH和ATA。
/*=======*/
/* Board */
/*=======*/
#define DV_EVM
#define CFG_USE_NAND(支持NAND)
#define CFG_NAND_LARGEPAGE (支持2K Page的NAND)
//#define CFG_NAND_SMALLPAGE(表示支持512 字节 Page)
//#define CFG_USE_NOR(表示支持NOR FLASH)
。。。。。。。
/*===================*/
/* SoC Configuration */
/*===================*/
#define CONFIG_ARM926EJS /* arm926ejs CPU core */
#define CONFIG_SYS_CLK_FREQ 297000000 /* Arm Clock frequency */
#define CFG_TIMERBASE 0x01c21400 /* use timer 0 */
#define CFG_HZ_CLOCK 27000000 /* Timer Input clock freq */
#define CFG_HZ 1000
#define CONFIG_SOC_DM644X (SOC为DM644X)
/*====================================================*/
/* EEPROM definitions for Atmel 24C256BN SEEPROM chip */
/* on Sonata/DV_EVM board. No EEPROM on schmoogie. */
/*====================================================*/
//#define CFG_I2C_EEPROM_ADDR_LEN 2
//#define CFG_I2C_EEPROM_ADDR 0x50
//#define CFG_EEPROM_PAGE_WRITE_BITS 6
//#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 20
(若是你的板子没有I2C接口的EEPROM,把上面的代码注释掉)
/*=============*/
/* Memory Info */
/*=============*/
#define CFG_MALLOC_LEN (0x10000 + 128*1024) /* malloc() len */
#define CFG_GBL_DATA_SIZE 128 /* reserved for initial data */
#define CFG_MEMTEST_START 0x80000000 /* memtest start address */
#define CFG_MEMTEST_END 0x81000000 /* 16MB RAM test */
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define CONFIG_STACKSIZE (256*1024) /* regular stack */
#define PHYS_SDRAM_1 0x80000000 /* DDR Start */
#define PHYS_SDRAM_1_SIZE 0x10000000 /* DDR size 256MB */
#define DDR_8BANKS /* 8-bank DDR2 (256MB) */
有关DDR Memory这里不须要修改,由于本人的板子是256M的。除非你的板子是128M才改成:SIZE 0x08000000 DDR_4BANKS。
/*====================*/
/* Serial Driver info */
/*====================*/
串口驱动不用改。
/*===================*/
/* I2C Configuration */
/*===================*/
I2C 驱动能够不用改。也能够注释掉,若是你不想在UBOOT操做任何I2C的动做。
/*==================================*/
/* Network & Ethernet Configuration */
/*==================================*/
网络配置也不须要修改
/*=====================*/
/* Flash & Environment */
/*=====================*/
因为最开始咱们已经定义好CFG_USE_NAND和CFG_NAND_LARGEPAGE的信息,因此这里也不须要修改;
/*==============================*/
/* U-Boot general configuration */
/*==============================*/
这里主要定义UBOOT的一些操做,好比命令行显示字符串,delay等待时间的长短,这些根据我的要求修改,不改也能够。
/*===================*/
/* Linux Information */
/*===================*/
UBOOT要把一些参数信息传给内核linux使用,linux内核运行的时候须要这些配置信息,内核可以识别这些字符串信息。先把如下两个定义注释掉,
//#define CONFIG_BOOTARGS xxxxxxxxxxxxxx
//#define CONFIG_BOOTCOMMAND xxxxxxxxxxxxxxx
若是你要从NAND FLASH启动:
#define CONFIG_BOOTARGS “mem=120M console=ttyS0,115200n8 noinitrd ip=off root=/dev/mtdblock3”(mtdblock3 表示文件系统放在LINUX内核分区)
#define CONFIG_BOOTCOMMAND " nboot 0x80008000 0x700000"(把linux 内核从FLASH BOOT起来,下面会介绍UBOOT的命令)
若是你还在调试阶段,建议你使用NFS文件系统:
#define CONFIG_BOOTARGS “mem=120M console=ttyS0,115200n8 noinitrd rw ip=dhcp root=/dev/nfs nfsroot=192.168.1.251:/home/<useraccount>/nfs/tirootfs,nolock”
#define CONFIG_BOOTCOMMAND " nboot 0x80008000 0x700000"
本人的redhat linux的主机地址是:192.168.1.251,即SERVER IP=192.168.1.251
板子的IP是:192.168.1.188
若是你没有路由器给你分配IP地址,参数行里使用:ip=off
mem=120M:本人定义前128M 给linux系统, 后128M 给DSP和图像缓冲区等;
nboot 0x80008000 0x700000:讲明本人把内核放在nand 地址为0x700000,经过nand boot的命令把内核从nand 0x700000地址导入DDR 0x80008000地址
/*=================*/
/* U-Boot commands */
/*=================*/
这里有不少功能的定义,包括#include <config_cmd_default.h>里边定义的,不须要的功能可使用#undef ,从而减少UBOOT 生成BIN文件的尺寸。好比
#undef CONFIG_CMD_DHCP
#undef CONFIG_CMD_DIAG
#undef CONFIG_CMD_EEPROM
#undef CONFIG_CMD_LOADB /* loadb */
#undef CONFIG_CMD_LOADS /* loads */
二、
修改board/davinci/dv-evm/dv_board.c里的有关本身板子的配置
在int board_init(void)函数里,由于本人的板子使用/EM_CS2做为NAND FLASH的片选信号,故在PINMUX0寄存器里,有关AEAW必须关掉。
/* Enable EMAC and AEMIF pins */
//REG(PINMUX0) = 0x80000c1f;
REG(PINMUX0) = 0x80000000;
只使用EMAC
不然UBOOT 启动不起来。
在int misc_init_r (void)函数里,由于本人没有使用I2C EEPROM存储MAC 地址,因此要注释掉
#if 0
/* Set Ethernet MAC address from EEPROM */
if (i2c_read(CFG_I2C_EEPROM_ADDR, 0x7f00, CFG_I2C_EEPROM_ADDR_LEN, buf, 6)) {
printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CFG_I2C_EEPROM_ADDR);
}
else
{
tmp[0] = 0xff;
for (i = 0; i < 6; i++)
tmp[0] &= buf[i];
if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) {
sprintf((char *)&tmp[0], "%02x:%02x:%02x:%02x:%02x:%02x",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
setenv("ethaddr", (char *)&tmp[0]);
}
}
#endif
通常MAC地址保存到NAND,下降成本。
………
#if 0
i2c_read (0x39, 0x00, 1, (u_int8_t *)&i, 1);
setenv ("videostd", ((i & 0x80) ? "pal" : "ntsc"));
#endif
若是你的板子没有TI 的视频采集芯片TVP5146之类的,上面的功能最好去掉。
三、
网口驱动移植:Cpu/arm926ejs/davinci/ ether.c
由于DM6446芯片上集成EMAC和MDIO,因此直接使用PHY芯片就能够了,驱动就使用UBOOT-1.3.4 TI 默认的驱动,而不是TI EVM使用的PHY_LXT972。直接使用GENERIC PHY,有个地方须要修改,不然网口工做不起来,本人也是从一个网友那里查到相似的信息,在static int dm644x_eth_phy_detect(void)函数里,改为:
#if 0
for (i = 0; i < 32; i++) {
if (phy_act_state & (1 << i)) {
if (phy_act_state & ~(1 << i))
return(0); /* More than one PHY */
else {
active_phy_addr = i;
return(1);
}
}
}
return(0); /* Just to make GCC happy */
#else
active_phy_addr = 1;
return(1);
#endif
因为本人的开发板使用GPIO对PHY芯片进行复位,因此在static int dm644x_eth_hw_init(void)函数里,加入GPIO复位的支持,同时文件头部加入#include <asm/arch/hardware.h>。
能够说, UBOOT移植到这里,基本上能够跑起网络了,TFTP应该没问题了,可是有关如何烧写UBL,烧写UBOOT,LINUX 内核等文件,之后再慢慢聊吧,一步一步来,《UBOOT移植(2)》之后会推出来,下一篇直接到MonaVista linux-2.6.18的移植(1),先让系统经过网络和串口跑起来,由简单到复杂。
继续make一下,生成u-boot.bin和u-boot.img,COPY u-boot.bin到WINDOWS底下,使用uart_load.exe和配套uart.bin文件,就能够把u-boot.bin给跑起来。若是有linux 内核编译出来并使用UBOOT tool目录下的mkimage工具生成 uImage,在UBOOT命令行下:
U-Boot > tftp 80008000 uImage
#######################################
U-Boot > bootm 80008000
## Booting kernel from Legacy Image at 80008000 ...
Image Name: linux-2.6.18
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1509948 Bytes = 1.4 MB
Load Address: 80008000
Entry Point: 80008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux...................................................................................................... done, booting the kernel.
Linux version 2.6.18_pro500-davinci_evm-arm_v5t_le (root@xxxxx.com) (gcc version 4.2.0 (MontaVista 4.2.0-16.0.32.0801914 2008-08-30)) #1 PREEMPT Sun Mar 7 01:07:16 CST 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
Machine: DaVinci EVM
……………………………………………………………
当出现上面的信息后,说明以上u-boot-1.3.4的移植是成功的。有兴趣的朋友能够参考以上作法移植u-boot-2009.11-rc2,也能够跑起来,只不过CROSS_COMPILE ?= arm-linux-不是放在顶层makefile了,而是放在lib_arm/config.mk里,改为CROSS_COMPILE = arm_v5t_le-就能够编译了。


补充有关DM6446 BOOT的一点知识:若是板子没有任何程序,RBL会经过串口0发送BOOTME命令上来,运行uart_load.exe,会接到RBL的命令,而后握手通讯,下载uart.bin到板子上,并运行起来,uart.bin程序就是小小的BOOT,经过串口0和PC通讯,下载u-boot.bin,并把u-boot.bin给运行起来。因此UBOOT移植到上面的步骤,能够进入linux 内核移植的工做了。
本文出自 “集成系统-踏上文明的征程” 博客,请务必保留此出处http://zjbintsystem.blog.51cto.com/964211/282387jquery