【原文:
http://zjbintsystem.blog.51cto.com/964211/713240】
从盛夏走到深秋,我们继续DAVINCI DM365-DM368的开发。说来惭愧,人家51CTO热情支持本博客,而本人却一直没有像其他博客之星一样频繁更新博客,心里确实说不过去。管理公司确实很累,有更急的客户的项目要做,我们成功先推出了DM6446-810MHz的核心板(
http://www.tongyetech.com ),期间深圳安防展也接见了几个其他市的客户,然后继续我们的DM368开发。
一、DM36X的BOOT过程介绍
DM36x的BOOT过程和DM6446、DM6467完全是一样的,因为都是ARM926EJS架构,里边都有一个RBL,这RBL在芯片出厂的时候都烧写在ROM里,芯片上电复位后RBL在运行,然后读取BOOT MODE引脚的电平状态,决定是从NAND FLASH还是从 MMC/SD、UART 、USB、 SPI、 EMAC、HPI中之一的方式BOOT,具体见SPRS558A.pdf和SPRUSG5A.pdf的介绍,这两个文档对硬件工程师、软件驱动工程师来说非常重要。
本篇及以后的DM36X文章基本以DM368为主的介绍,因为DM365--- dvsdk_dm365_4_02_00_06和DM368----dvsdk_dm368_4_02_00_06的UBL,U-BOOT, KERNEL的源码完全是一样的,如果不考虑2A算法,DM368就是DM365的超频超出来的高清!
二、DM36X 的UBL移植
关于UBL的移植,本人打算单独写一篇文章的,但是UBL和UBOOT太紧密了,是TI davinci芯片的特点,所以放到一起讲。我们重点放在NAND BOOT的移植,这个UBL的版本是V1.50,在dvsdk_dm368_4_02_00_06pspflash-utilsDM36x和flash-utilsCommon目录下,Common目录里有非常多东西,包括UBL的驱动源码、工具、脚本等等。我们主要关注arch,drivers,src,ubl。UBL的main()函数在dvsdk_dm368_4_02_00_06pspflash-utilsCommonublsrcubl.c里,这几个文件夹打开看看就明白什么意思了,这里不罗嗦。
DM36x下有CCS、Common,GNU三个文件夹:
CCS文件夹:
这里边的程序需要在TI CCS下编译,通过仿真器和JTAG在DM36X的板子上调试和烧写NAND FLASH或NOR FLASH,有烧写Writer的应用程序,用CCS打开工程文件,会连接到dvsdk_dm368_4_02_00_06pspflash-utilsCommon drivers里。
Common文件夹:Common里有核心的文件device.c和device_nand.c。device.c是最重要的文件,这里初始化很多系统的东西,见DEVICE_init():
1、屏蔽所有中断;
2、清除中断标志;
3、DEVICE_PSCInit(),Power and Sleep Controller;
4、主芯片管脚复用的设置DEVICE_pinmuxControl(),DM36X的管脚复用很多,很复杂,一共5个PINMUX寄存器需配置;
5、DEVICE_PLL1Init(),PPL1配置,见SPRUSG5A.pdf的35页开始的介绍,使用不同的频率的DM36X,这些值都不同,不过TI已经提供参数参考,我们的DM365核心板是:ARM297_DDR243_OSC24,DM368核心板是:ARM432_DDR340_OSC24;
6、DEVICE_PLL2Init(),PPL2的配置,使用同上,不同频率的值不同;
7、DEVICE_DDR2Init()的配置,市场上不同的DDR2内存芯片需要不同的参数配置,就在这个函数内。
8、DEVICE_EMIFInit(),这个针对NAND FLASH接口或NOR FLASH接口的访问时序配置;
9、DEVICE_UART0Init()的配置,这个就是我们调试DM36X串口的设置,我们使用UART0来调试LINUX,这里配置不好,后面的开发不用调试了。
10、DEVICE_TIMER0Init()定时器TIMER0的设置;
11、DEVICE_I2C0Init()的设置;
GNU的文件夹:
这个就是在LINUX环境下编译UBL的环境,修改dvsdk_dm368_4_02_00_06pspflash-utilsDM36xGNUubl下的makefile,把
#$(MAKE) -C build TYPE=nor注释掉,只保留$(MAKE) -C build TYPE=nand,然后是make clean和 make生产ubl_DM36x_nand.bin的文件;
如果出现:device.c:(.text+0x2ec): undefined reference to `__aeabi_uidiv'和device.c:(.text+0x2e8): undefined reference to `__aeabi_uidivmod'的BUG,就是DDR_Get_Val()函数里边的除法和求余的语句和你的编译器不配置造成的。
result = ((parm * freq) / 10000) - 1;和if(((parm * freq) % 10000)),我们对参数的求值直接:
tRFC = xxx; //DDR_Get_Val(DDR_T_RFC, DDR_FREQ);
tRP = xxx; //DDR_Get_Val(DDR_T_RP, DDR_FREQ);
tRCD = xxx; //DDR_Get_Val(DDR_T_RCD, DDR_FREQ);
tWR = xxx; //DDR_Get_Val(DDR_T_WR, DDR_FREQ);
tRAS = xxx; //DDR_Get_Val(DDR_T_RAS, DDR_FREQ);
tRC = xxx; //DDR_Get_Val(DDR_T_RC, DDR_FREQ);
tRRD = xxx; //DDR_Get_Val(DDR_T_RRD, DDR_FREQ);
tWTR = xxx; //DDR_Get_Val(DDR_T_WTR, DDR_FREQ);
不用DDR_Get_Val()函数求值,这样就可以编译通过了。后来发觉TI的
http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/p/115574/425950.aspx里也有人这人解决,呵呵,没想到本人的解决办法和一个网友一样的。本人记得调试三星2440
UBOOT的时候,有人点到过,这里本人忘记在什么地方改了。
三、介绍u-boot-2010.12的特点
u-boot-2010.12的架构组织越来越向LINUX架构靠拢,这是U-BOOT的发展趋势。DM36x的UBOOT源码放在dvsdk_dm368_4_02_00_06psp的下面,文件夹叫u-boot-2010.12-rc2-psp03.01.01.39,太长了,我们直接u-boot-2010.12。这个u-boot-2010.12支持YAFFS2、UBI等文件系统,支持SD卡、USB、VIDEO等驱动,支持lzma和lzo的内核镜像压缩,还有经典的linux shell命令支持模式,就是tab等的妙用,就是在”U-boot
>”提示符下键入和LINUX 开发主机上一样的命令,当然这个命令很少,而且有些命令是用户自己加的。相对以前的u-boot-1.3.4版本等版本,这个新U-BOOT把很多平台的配置脚本给去掉了。
四、u-boot-2010.12的移植
DAVINCI芯片系列的UBOOT移植大同小异,比较简单。
1、首先修改:Makefile:
第140行:#examples/standalone
第141行:#examples/api
第246行: #LIBS += api/libapi.o
等一下我们就可以把一些不相关的文件夹给删除掉,给u-boot-2010.12瘦身。
第323行:ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)
u-boot.img
后面增加u-boot.img,这个u-boot.img就是我们要烧写到NAND里边的BIN文件,可以被UBL给BOOT起来的文件,因为u-boot.img是通过u-boot-2010.12 ools下的mkimage的工具生产的,带有头header的文件,这些头信息能被UBL给识别,所以才能烧写到NAND FLASH或NOR FLASH里边去。而u-boot.bin是没有增加文件头部信息的文件,不能被UBL直接给BOOT起来。u-boot.bin只能使用软件BOOT,比如: tftp 0x82080000
u-boot.bin ;go 0x82080000。
最重要的地方修改:
第350行:-a $(CONFIG_SYS_TEXT_BASE) -e 0x81080000
或者-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
刚开始这个-e 0是错误的,我们把U-BOOT-2010.12的entrypoint定义到0x81080000,这个DDR的地址是在u-boot-2010.12oarddavincidm365evmconfig.mk
CONFIG_SYS_TEXT_BASE = 0x81080000
这个-e(entrypoint)不能是0,否则无法被UBL给BOOT起来。
第953行是不需要改动的:
davinci_dm365evm_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm926ejs dm365evm davinci davinci
DM368也是使用同样的dm365evm名字。
2、开始删除一些不相关的文件夹
u-boot-2010.12api文件夹
u-boot-2010.12examples
u-boot-2010.12
and_spl
u-boot-2010.12onenand_ipl
u-boot-2010.12arch里的只保留arm文件夹
u-boot-2010.12 archarmcpu文件夹里,只保留arm926ejs
u-boot-2010.12 archarmcpuarm926ejs文件夹里,只保留davinci文件夹,我们只删除文件夹,旁边的cpu.c和Makefile不要删除,等等;
u-boot-2010.12oard里边,只保留davinci文件夹,其他统统删除掉;
u-boot-2010.12oarddavinci里,只保留dm365evm和common,其他删除;
u-boot-2010.12includeconfigs里,只保留davinci_dm365evm.h,其他文件和文件夹删除掉;
通过上面的操作,我们的u-boot-2010.12简化多了。
3、修改最重要的davinci_dm365evm.h
在u-boot-2010.12includeconfigs里,davinci_dm365evm.h
修改#define CONFIG_SYS_NAND_MAX_CHIPS
1,把以前的2改成1,表示本系统只支持1片NAND FLASH;
把#define CONFIG_BOOTCOMMAND
"if mmc rescan 0; then if fatload mmc 0 0x80600000 boot.scr; then source 0x80600000; else fatload mmc 0 0x80700000 uImage; bootm 80700000; fi; fi"给注释掉,我们不想用SD卡保存内核的BIN文件uImage;
然后定义#define CONFIG_BOOTCOMMAND "run nand_boot",表示从NAND FLASH 读取内核;
修改UBOOT的BOOTARGS参数:#define CONFIG_BOOTARGS
"console=ttyS0,115200n8 mem=60M noinitrd rw ip=192.168.1.188:192.168.1.252:192.168.1.1:255.255.255.0 root=/dev/nfs nfsroot=192.168.1.252:/home/davinci/dm368/dvsdk_dm368_4_02_00_06/filesystem/dm368rootfs,nolock"
我们这里提到mem=60M,是有根据的,我们板子是128M-BTYE,因为后面的DVSDK4.02里边的encodedecode等例子需要用到CMEM,这个和DM6446类似,所以定义为60M。
见dvsdk_dm368_4_02_00_06filesystemdvsdk-dm368-evm-rootfs解压后的etcinit.dloadmodule-rc文件:
# Default DM368 EVM Memory Map
#
# Start Addr Size Description
# -------------------------------------------
# 0x00001000 32K ARM TCM memory
# 0x80000000 48 MB Linux
# 0x83000000 12 MB Video driver memory (Linux)
# 0x83C00000 68 MB CMEM
# 0x88000000 BOTTOM ADDRESS
load () {
modprobe cmemk phys_start=0x83C00000 phys_end=0x88000000 allowOverlap=1 phys_start_1=0x00001000 phys_end_1=0x00008000 pools_1=1x28672 useHeapIfPoolUnavailable=1
modprobe irqk
modprobe edmak
modprobe dm365mmap
mknod /dev/dm365mmap c `awk "
\$2=="dm365mmap" {print
\$1}"
/proc/devices` 0
}
有些人定义CMEM共享内存小一点的话,那么这个值可以比60M大。后面的参数就是使用静态固定IP的NFS SERVER路径,进行NFS调试;
增加
#define CONFIG_IPADDR
192.168.1.188
#define CONFIG_SERVERIP
192.168.1.252
#define CONFIG_ETHADDR
00:03:55:88:00:00
定义板子自己的IP和MAC,这个MAC在保证和其他网络设备MAC不冲突的前提下,自己调试的时候顺便分配。SERVERIP就是我们LINUX开发环境的主机IP地址,主要用做TFTP和NFS调试。
#define CONFIG_EXTRA_ENV_SETTINGS
"eraseenv=nand erase 0x00060000 0x00020000