cortex-a8 uboot系列:第十六章 uboot移植-从三星官方移植
0赞一、 移植前的准备工作
三星移植过的uboot源代码准备
Ubuntu14.04重启网卡命令, ifdown eth0, ifup eth0
安装openssh,通过ssh远程登录linux
二、 移植初体验
复制三星官方的uboot代码到linux下。
检查makefile中的交叉编译工具链是否正确
配置时使用:
make smdkv210_single_config
然后直接make, 得到u-boot.bin。
使用sd_fusing目录下的sd_fusing.sh脚本,将u-boot.bin烧录到SD中。因为sd_fusing目录下有两个文件是三星在64位系统上编译的,在32位机上是不能工作的。因此需要重新make以下生成32位下的这两个文件。
将SD卡插入到开发板中,启动电源。串口输出不正确。但是开发板供电锁存成功。
分析运行结果:
Uboot中串口最早的输出在”OK”,在lowlevel_init.S中初始化串口时打印出来的;串口无输出“OK”说明在打印“O”之前代码已经死掉了;开发板供电锁存在lowlevel_init.S中,开发板供电锁存成功说明这个代码之前的部分是没问题的。
因此,可以得出,错误是开发板供电锁存代码和串口初始化打印“O”代码之间
在lowlevel_init.S中,调用了PMIC_InitIp函数,这个函数是对外部的PMIC(电源管理芯片)进行设置,通过IIC接口。而开发板是没有PMIC的,因此这里要将这里的函数屏蔽掉。
修改为
修改后,重新编译,串口打印信息,uboot基本移植成功。但是有很多功能不能使用。
可以看到外部的SD/MMC卡初始化失败。因为没有识别到SD/MMC卡。还有DRAM的大小也不对。
三、 Uboot的配置文件smdkv210single.h修改
更改config的打印信息
这样,就修改了uboot的打印信息。
更改网络相关的信息。打印的信息也随之修改。
从uboot显示看出时钟配置是正确的时钟,因此不用去设置时钟。
四、 DRAM代码移植
DRAM显示信息不对,使用bdinfo打印具体信息。
看出DRAM0和DRAM1的size值不对,应该为0x1000_0000。
使用md命令进行内存数据查看。
看到0x2000_0000地址开始和0x3000_0000地址开始的数据是一样的。并且对0x20000000地址数据修改,0x30000000地址值也随之修改了。说明了地址0x30000000-0x3ffffff和0x20000000-0x2fffffff映射的DRAM区域是一样的。
修改SDRAM_BANK_SIZE为256, 表示每一块内存大小为256M。并修改SDRAM_1和SDRAM_2的基地址为对应的宏。
添加这两个宏。
这样,更改了DRAM的大小。重新编译烧录,从uboot中可以看出DRAM的设置正确了。
下面要更改DRAM1的首地址,将之设置为0x3000_0000,因为开发板的DRAM的连接是这样的。这样,DRMA1和DRAM2的地址就连接起来了。
首先修改内存首地址的宏:
修改DRAM的MEMCONFIG_0寄存器的值。将DMC0_MEMCONFIG_0配置值的高16位设置为0x30F0。表示将DRAM0的基地址映射到0x30000000上。并且可用的地址范围为
0x3000_0000 – 0x3fff_ffff
修改lowlevel_init.S的MMU映射表,将597行的设置的_base的值为0x300。
定义256M空间。循环256次,建立256个表项。
虚拟地址范围:0xC000_0000-0xCFFF_FFFF
映射的物理地址 : 0x3000_0000-0x3FFF_FFFF, (DMC0的有效区域,也就是外部DRAM1的区域)
开启cache,使用write buffer。
将内存的物理地址0x3000_0000-0x3FFF_FFFF映射到虚拟地址0xC000_0000-0xCFFF_FFFF
修改虚拟地址映射到物理地址的函数,将框中的数据修改为0x3000_0000。
编译下载,打印信息如下,将DRAM1的起始地址修改为0x30000000了。并且内存可以使用。
修改uboot打印的板子的信息。
五、 SD/MMC移植
Uboot打印SD/MMC的信息错误,说明对对外部的SD/MMC初始化失败。
先查看这几句信息在什么地方打印出来的。
在mmc_startup函数(drivers/mmc/mmc.c),SDMMC初始化的调用的最后一个大函数。
查看打印问题,发现打印问题和EXT_CSD有关,所以查看mmc_read_ext_csd函数(drivers/mmc/mmc.c)
原来的代码如下,当ext_csd_struct值大于6,打印错误信息。而从uboot打印信息看出,这个时候的值为6。
修改为:
但是发现这个错误信息打印了两次,因为在对mmc的初始化,如果第一次初始化失败,那就再初始化一次。而第二次也会初始化失败,所以又打印了一次。
修改后,uboot执行MMC初始化成功,可以打印卡的容量大小。
扩展寄存器EXT_CSD为高版本的SDMMC卡使用。
判断卡的版本,如果低于4版本,说明都没有EXT_CSD_寄存器,就不用执行这函数,直接返回。
发送EXT_CSD命令,并将响应保存到ext_csd中。
在ext_csd有几位是表示卡的版本。对于uboot不处理MMC卡的版本大于5的情况,所以要将版本设置为大于6。
通过EXT_CSD可以获取卡的一些信息。
查看iNand的数据手册。
查看EXT_CSD_的第192字节,表示卡的版本,默认值是0x5。
在mmc_initialize函数(drivers/mmc/mmc.c)添加上述代码,对外部的SD卡进行初始化,并打印容量信息。
Uboot的效果如下。
在smdkv210single.h中,有如下一个宏,表示命令的提示符。这里修改为如下,
在uboot中的效果就是:
六、 其他一些参数的修改
修改默认的串口端口。
Uboot默认使用的是串口2。可以修改为串口0。
将以下代码修改,即可将串口定向为串口0。
Uboot中定义了4个串口
CONFIG_SERIAL1 表示串口0
CONFIG_SERIAL2 表示串口1
CONFIG_SERIAL3 表示串口2
CONFIG_SERIAL4 表示串口3
配置这些宏,来配置串口的基地址是多少。
这样,就将uboot的串口定向为串口0。
将虚拟转物理地址函数修改为如下,当地址不需要转换时,不打印信息。
Uboot中有打印nand的信息,容量为0。但是开发板没有使用nand,所以要将这部分代码修改。
在start_armboot函数(lib_arm/board.c)中,初始化SDMMC后,就要去初始化NAND,可以看出NAND和宏CONFIG_CMD_NAND有关系的。
在smdkv210single.c中将宏CONFIG_CMD_NAND注释掉。表示对外部的NAND不配置。
但是编译会出错,提示和nand有关函数找不到,说明这个宏开关控制了一些nand函数的编译。
Uboot默认从nand启动,所以要将启动方式更改为SDMMC方式。
注释掉CFG_FASTBOOT_NANDBSP,表示启动介质不是nand,
定义CFG_FASTBOOT_SDMMCBSP宏,表示启动介质是SDMMC
编译成功,下载执行,打印如下信息,nand信息没有没有打印了,地址不需要虚拟转换的信息也不打印了。
以上就移植好了一个uboot。可以看出,从开发板的原厂商提供的uboot,进行移植,是相对比较容易的。
移植的关键,还是从打印信息入手。根据打印信息,去确认问题,然后解决问题。