TI Davinci DM6441嵌入式Linux移植攻略——u-boot移植篇

2019-07-13 08:08发布

声明:本文参考网友zjb_integrated的网文《DavinciDM6446开发攻略——u-boot-1.3.4移植(1)》,内容有增删,特此声明。

一、UBOOT各版本简介

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的支持。

二、UBOOT移植

第一步:解压和简化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上的板子,你可以删掉,也可以参考。当然,还是在boarddavinci目录下,你可以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和这个源版本比较。

第二步:测试交叉编译环境

如果已经按《 TI Davinci DM6441嵌入式Linux移植攻略——开发环境搭建篇》里边描述的方法,对交叉编译环境进行搭建,那么下面编译工作就好进行了。
修改顶层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_dm6441_config : unconfig
    @$(MKCONFIG) $(@:_config=) arm arm926ejs dm6441 davinci davinci
然后在boarddavinci目录下,使用
mkdir dm6441
cp –f dv-evm/* dm6441/
同时进入include/configs/目录,使用cp –f davinci_dvevm.h davinci_dm6441.h
注:其实直接在TI  dv-evm上移植也可以,没必要定义自己的板子和配置。这里只不过给大家举个例子。
编译工作:
$make distclean
$make davinci_dm6441_config
$make
看是否编译全部通过,是否生成u-boot.bin和u-boot.img等文件,同时检查你的交叉编译环境是否建立好,没问题继续往下进行。

第三步:移植板子驱动和配置

1、  修改davinci_dm6441.h

首先说说本人板子的信息:DDR2——64M-Byte,NAND——512M-Byte——512Byte Page;没有NOR FLASH。 /*=======*/
/* Board */
/*=======*/
#define DV_EVM
#define CFG_NAND_SMALLPAGE//支持512 Byte Page的NAND
//#define CFG_NAND_LARGEPAGE //支持2K Page的NAND
//#define CFG_USE_NOR//modified by Dashon 2012.3.10
#define CFG_USE_NAND//added by Dashon 2012.3.10
/*===================*/
/* 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//added by Dashon 2012.3.10
/*====================================================*/
/* EEPROM definitions for Atmel 24C256BN SEEPROM chip */
/* on Sonata/DV_EVM board. No EEPROM on schmoogie.    */
/*====================================================*/
//板子没有I2C接口的EEPROM,modified by Dashon 2012.3.10
//#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

/*=============*/
/* 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 */
//modified by Dashon 2012.3.10,For K4T1G164QE
#define PHYS_SDRAM_1_SIZE0x04000000/* DDR size 64MB */
#define DDR_8BANKS /* 8-bank DDR2 (64MB) */

/*====================*/
/* Serial Driver info */
/*====================*/
//串口驱动不用改 /*===================*/
/* I2C Configuration */
/*===================*/
//没有用到,modified by Dashon 2012.3.10 
//#define CONFIG_HARD_I2C
//#define CONFIG_DRIVER_DAVINCI_I2C
//#define CFG_I2C_SPEED 80000/* 100Kbps won't work, silicon bug */
//#define CFG_I2C_SLAVE 10/* Bogus, master-only in U-Boot */

/*==================================*/
/* 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的命令)
/*=================*/
/* U-Boot commands */
/*=================*/
#include
#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_DIAG
//#define CONFIG_CMD_I2C//modified by Dashon 2012.3.11
#define CONFIG_CMD_MII
#define CONFIG_CMD_PING
#define CONFIG_CMD_SAVES
//#define CONFIG_CMD_EEPROM//modified by Dashon 2012.3.11
//#undef CONFIG_CMD_I2C
#undef CONFIG_CMD_BDI
#undef CONFIG_CMD_FPGA
#undef CONFIG_CMD_SETGETDCR
#ifdef CFG_USE_NAND
#undef CONFIG_CMD_FLASH
#undef CONFIG_CMD_IMLS
#define CONFIG_CMD_NAND
#elif defined(CFG_USE_NOR)
#define CONFIG_CMD_JFFS2
#else
#error "Either CFG_USE_NAND or CFG_USE_NOR _MUST_ be defined !!!"
#endif

2、修改board/davinci/dm6441/dv_board.c里的有关自己板子的配置

1)在int board_init(void)函数里,因为本人的板子使用/EM_CS2作为NAND FLASH的片选信号,故在PINMUX0寄存器里,有关AEAW必须关掉。
/* Enable EMAC and AEMIF pins */
//REG(PINMUX0) = 0x80000c1f;//modified by Dashon,2012.3.19
REG(PINMUX0) = 0x80000000;
只使用EMAC否则UBOOT 启动不起来。
2)在int misc_init_r (void)函数里,因为本人没有使用I2C EEPROM存储MAC 地址,所以要注释掉
//modified by Dashon 2012.3.10
#if 0
/* Set Ethernet MAC address from EEPROM */
if (i2c_read(CFG_I2C_EEPROM_ADDR, 0x7f00, CFG_I2C_EEPROM_ADDR_LEN, buf, 6)) {
printf(" EEPROM @ 0x%02x read FAILED!!! ", 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 (!eth_hw_init()) printf("ethernet init failed! ");
//modified by Dashon 2012.3.10
#if 0
i2c_read (0x39, 0x00, 1, (u_int8_t *)&i, 1);
setenv ("videostd", ((i  & 0x80) ? "pal" : "ntsc"));
#endif 如果你的板子没有TI 的视频采集芯片TVP5146之类的,上面的功能最好去掉。

3、网口驱动移植: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