DSP

DAVINCI DM365-DM368开发攻略——U-BOOT-2010.12及UBL的移植

2019-07-13 16:36发布

【原文: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