uboot的移植——移植三星官方的uboot到X210开发板

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

目录

一、移植总结

二、移植过程

1、获取三星官方版本的uboot

2、删除无关的文件

3、直接编译三星移植版uboot尝试运行

4、解决“NAND:   ”后面没有显示信息的问题

5、uboot的版本号和时钟配置

6、DDR的配置

7、解决SD卡版本号问题

8、网卡驱动的移植

9、修改提示符“SMDKV210 #”

10、使用sd卡中的uboot启动内核


一、移植总结

二、移植过程

1、获取三星官方版本的uboot

(1)由于X210开发板使用S5PV210这款CPU,因此我们应该寻找一块使用相同CPU的开发板,然后以这块开发板的uboot为基础进行移植,这样可以大大减少移植的工作量。X210开发板是根据三星的smdkv210开发板进行裁剪设计的,两者使用相同的CPU,因此我们以这个开发板的uboot为基础进行移植工作。

(2)三星smdkv210开发板使用的uboot是uboot_smdkv210.tar

2、删除无关的文件

移植之前我们首先把无关的文件删掉,然后用sourceinsight生成project。

(1)/board目录:此目录下每个文件夹代表一个开发板。把不相关的开发板的文件全部删除,只保留samsung文件夹。而samsung文件夹里只保留common文件夹、smdkc110文件夹。

(2)/cpu目录:每一个文件夹就是一个SoC系列。这个目录下只保留s5pc11x文件夹,其他全部删除。

(3)/include目录:asm-开头的文件夹只保留asm-arm文件夹。asm-arm文件夹下arch-开头的文件夹只保留arch-s5pc11x。/include目录下的其他文件与文件夹保留。

(4)/include/configs目录:每一个开发板对应一个.h文件。只保留smdkv210single.h文件。

(5)/lib_ 开头的文件夹保留lib_arm、lib_generic 。

3、直接编译三星移植版uboot尝试运行

(1)检查与修改Makefile中的交叉编译工具链。

ifeq ($(ARCH),arm)
#CROSS_COMPILE = arm-linux-
#CROSS_COMPILE = /usr/local/arm/4.4.1-eabi-cortex-a8/usr/bin/arm-linux-
#CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

(2)先“make smdkv210single_config”进行配置,然后编译“make”,生成uboot.bin文件。

  • 配置操作对应着/include/configs/smdkv210single.h这个头文件。
  • 执行上述命令时可能遇到127权限问题,解决方法“chmod 777 -R uboot_smdkv210”。
  • 生成的uboot.bin文件位于uboot源码的根目录下。
root@ubuntu:/home/xjh/iot/embedded_basic/uboot/uboot_smdkv210# make smdkv210single_config
make: execvp: /home/xjh/iot/embedded_basic/uboot/uboot_smdkv210/mkconfig: 权限不够
make: *** [smdkv210single_config] 错误 127
root@ubuntu:/home/xjh/iot/embedded_basic/uboot# chmod 777 -R uboot_smdkv210
root@ubuntu:/home/xjh/iot/embedded_basic/uboot/uboot_smdkv210# make smdkv210single_config
Configuring for smdkv210single board...
root@ubuntu:/home/xjh/iot/embedded_basic/uboot/uboot_smdkv210# 

为什么知道进行配置是执行 “make smdkv210single_config” 呢?因为在/Makefile文件中,配置规则的目标一般是“开发板_config”这样的形式。这里的开发板名字是smdkv210,因此我们在/Makefile文件中搜寻这个名字,得到配置规则的目标是smdkv210single_config。

(3)将SD卡接入虚拟机linux系统,然后在uboot源码的sd_fusing目录下执行“./sd_fusing.sh /dev/sdb”命令,将刚才生成的uboot.bin文件烧录到sd卡中。

  • 注意sd_fusing.sh脚本中,烧写的内容是不是uboot.bin以及uboot.bin的路径对不对。
  • 利用“file mkbl1”查看mkbl1是不是32bit的,如果不是则需要在sd_fusing目录下执行make clean,然后再make。
  • sd_fusing.sh文件中,“/mkbl1 ../u-boot.bin SD-bl1-8k.bin 8192”表示将uboot的前8k复制到SD-bl1-8k.bin文件中。
  • 执行此sd_fusing.sh脚本即可把bl1、uboot.bin烧录到SD卡中。

(4)运行现象与分析移植

【1】现象

开发板启动时,电源置锁(表现为电源指示灯常亮),串口输出显示“SD checksum Error”,但没有输出显示“OK”。

【2】分析

uboot中串口最早的输出“OK”,是在lowlevel_init.S中初始化串口时打印出来的,而现在串口没有输出"O"则说明在打印"O"之前代码已经死掉了。开发板供电锁存操作在lowlevel_init.S文件中完成,而现在开发板供电锁存成功,说明这个代码之前的部分是没问题的。错误发生在开发板供电锁存代码和串口初始化打印"O"代码之间。

【3】移植

在/board/samsung/smdkc110/lowlevel_init.S文件的lowlevel_init函数中,PMIC_InitIp函数是用来管理电源的。由于X210开发板没有PMIC模块,这个函数内部向PMIC模块发送I2C接口的命令时,会一直等待模块的响应,导致后面的代码不能运行。只要把此函数注释掉即可。

4、解决“NAND:   ”后面没有显示信息的问题

(1)将PMIC_InitIp函数屏蔽后,重新执行make进行编译,然后将镜像文件烧写至SD卡,将SD卡插入开发板,然后重新启动。此时uboot输出如下:

朱有鹏的教程视频在这步显示的内容如下:

对比可知启动信息与朱有鹏的教程视频不同,我这里的“NAND:   ”之后就没有后续的输出。

(2)在Linux系统中uboot源码目录下搜索“NAND:”(利用grep "NAND:" -nr ./),得知这几个字符位于/lib_arm/board.c文件的start_armboot函数中,如下所示:

由于其下一行是nand_init函数,我猜想问题出现在这个nand_init函数。 

但是在 /drivers/mtd/nand/nand.c、/lib_arm/board.c 文件中都定义了nand_init函数,那上面到底调用哪个文件中的nand_init函数呢?我们可以在这两个文件的nand_init函数内部的开始位置,分别添加代码 “puts("this is nand.c !\n");” 与 “puts("this is board.c !\n");”。然后根据重新编译与运行的显示信息,得知上面调用的是/drivers/mtd/nand/nand.c这个文件中的nand_init函数。

(3)这里为何“NAND:   ”之后就没有后续的输出呢?如下所示,我们在nand_init函数的下一行添加代码“puts("xjh is a handsome man! \n");”,然后重新编译与运行,发现没有输出这个信息,这说明uboot卡在nand_init函数中。

然后重新编译与运行,发现没有输出这个信息,这说明uboot卡在了nand_init函数中。

为什么会卡在这个函数呢?我一开始猜想这个函数写错了,但对比X210开发板的uboot的nand_init函数,发现两者是一样的,所以这个函数应该不会写错。其次想到X210开发板没有使用Nand,因此uboot会卡在nand_init函数,于是我将nand_init函数注释掉,重新编译与运行,发现uboot可以显示“xjh is a handsome man!”这个信息。

(4)为什么X210开发板的uboot不出现这个问题?这是因为X210开发板的uboot根本就没有定义这个宏CONFIG_CMD_NAND宏,因此X210开发板的uboot就不会执行nand_init函数有关。(这个宏在 /include/configs/x210_nand.h 文件中定义,但X210开发板的配置文件是x210_sd.h文件。)

(5)为什么移植的uboot出现了这个问题?这是因为在/include/configs/smdkv210single.h文件中定义了CONFIG_CMD_NAND这个宏,所以会执行nand_init函数,而执行这个函数时会一直等待Nand的响应,但X210开发板根本就没有Nand,所以会卡在这个函数中。

(6)解决方法:注释掉nand_init函数,或者注释掉这个CONFIG_CMD_NAND宏(但实际上把宏注释掉,执行make的时候有其他差错,这是为何)。

5、uboot的版本号和时钟配置

上面的问题解决后,uboot启动的信息如下:

(1)由博文C阶段的start_armboot函数的3.8节可知,uboot的版本号信息是由函数display_banner打印的。如果要修改其中的“for SMDKV210”这个信息,只需在/include/configs/smdkv210single.h文件中修改CONFIG_IDENT_STRING这个宏的值即可。

(2)由博文C阶段的start_armboot函数的3.9节可知,时钟信息是在print_cpuinfo这个函数中打印出来的。lowlevel_init.S文件中通过“bl system_clock_init”调用system_clock_init函数来完成时钟的初始化。如果想要更改时钟部分的信息,完全不需要改动system_clock_init这个函数,只有修改这个函数中有关的宏的宏定义即可。这是因为三星移植时已经把smdkv210常用的各种时钟的配置计算好,并且用宏来表示其中的参数,只要打开相应的宏开关就能将系统配置为各种不同的频率。注意,这里显示的时钟信息是对的,因此不需要任何修改。

(3)由博文C阶段的start_armboot函数的3.10节可知,“Board: SMDKV210”这个信息是通过/board/samsung/smdkc110/smdkc110.c文件中的checkboard函数打印的。我们可以将它修改为“Board: X210”,如下所示。

(4)经过上述的修改之后,uboot启动时显示的信息如下:

6、DDR的配置

uboot打印的这个信息“DRAM:  1GB”是错误的,移植时要根据实际情况进行修改。

(1)在/include/configs/smdkv210single.h中定义了DRAM中的配置信息,移植前的内容如下图。由此可知开发板有两块DRAM,大小均为512M,所以显示总的内容大小为1GB。

但是X210开发板实际只有512M内存,每块DRAM大小都是256M,因此上面圈出来的地方要修改为“#define SDRAM_BANK_SIZE 0x10000000 ”,表示256M大小。

(2)上图中的MEMORY_BASE_ADDRESS这个宏表示DRAM0的物理地址,它的值为0x20000000。而SDRAM_BANK_SIZE这个宏表示DRAM0或DRAM1的大小,修改后的值为0x10000000。这意味着DRAM0的物理地址范围是0x20000000~0x2FFFFFFF(256MB),DRAM1的物理地址范围是0x40000000~0x4FFFFFFF(256MB)。

但我们希望内存地址是连续的,为0x30000000~0x4FFFFFFF,因此需要配置DDR的地址。

移植步骤1:更改寄存器的值

DDR的初始化,是lowlevel_init.S文件中通过“bl mem_ctrl_asm_init”调用mem_ctrl_asm_init函数来完成的。

这个函数的内部通过一些宏对相应的寄存器做了相应的初始化,当我们需要更改寄存器的内容时,修改这些宏的值即可。

为了让uboot具有可移植性,这些宏都定义在/include/configs/smdkv210single.h文件中,我们需要根据实际情况来修改这个文件中有关的宏。

这里修改DMC0_MEMCONFIG_0这个宏的值为0x30F01323(具体原因要看mem_ctrl_asm_init函数代码),如下所示。

步骤2:软件配置值更改

更改寄存器的值只是相当于更改了硬件配置部分,还需要更改uboot中与DDR相关的一些软件配置值还需要更改。

在/include/configs/smdkv210single.h文件中,将MEMORY_BASE_ADDRESS这个宏的值由0x20000000更改为0x30000000。

移植步骤3:虚拟地址映射表中进行相应修改

uboot中开启MMU对内存进行了段式映射,其中有一张内存映射表,即/board/samsung/smdkc110/lowlevel_init.S文件中标签mmu_table下面的代码。

经过分析得知,这个内存映射只是把20000000开始的256MB映射到C0000000开头的256MB。

这里将“.set __base,0x200”修改成“.set __base,0x300”,如下图所示。

移植步骤4:修改虚拟地址到物理地址的映射函数

修改/board/samsung/smdkc110/smdkc110.c中的virt_to_phy_smdkc110函数,将其中的20000000改为30000000即可。 

(3)上述修改之后,uboot启动时显示的信息如下:

7、解决SD卡版本号问题

(1)SD/MMC提示错误如下:

在uboot源码目录下输入“grep "unrecognised EXT_CSD structure" -nr ./”,得知问题定位在/drivers/mmc/mmc.c文件的818行,mmc_read_ext_csd函数中。

(2)X210开发板有一个iNand接在SD0通道上,有一个外置SD卡接在SD2通道上。在uboot源码/drivers/mmc/mmc.c文件中的mmc_initialize函数中,有一行代码“mmc=find_mmc_device(0);”,参数0表示SD0(当然也可以改为1,则此时表示SD2),所以uboot中初始化的是iNand而不是SD卡,也就是说uboot中实际用的是SD0而不是SD2。

(3)mmc_read_ext_csd这个函数是在读取SD或者iNand的ext_csd寄存器的值。通过浏览代码结合出错地方,可知从SD卡或者iNand中读取ext_csd寄存器是成功的,并且得到了SD 卡或者iNand的版本号信息,否则不会在比较版本号后输出错误提示。因为SD卡的版本号一般比较低而不会大于5,所以使用外置SD卡时不会提示这个错误;而iNand的版本号比较高而可能出现大于5的情形。又从(2)中得知uboot中初始化的是iNand,所以会出现这个错误提示。

(4)这里只要把 if 判断语句中的5修改为8,就能解决SD卡版本号的问题。

(5)上述修改之后,uboot启动时显示的信息如下:

8、网卡驱动的移植

上图提示找不到网卡芯片DM9000(如下所示)。

X210开发板配置有DM9000网卡,但之所以找不到它,是因为还没有移植网卡的驱动。 

(1)DM9000的网卡驱动主要体现在/drivers/net/dm9000x.c和dm9000x.h这两个文件,它们来源于Linux内核,可以在uboot中直接使用,我们不需要改动。

(2)由于DM9000网卡的驱动文件已经位于/driver目录下(如果不在则需要添加),因此网卡移植的关键或者说主要工作,就在于初始化网卡,只要将网卡芯片正确地初始化则网卡芯片就能工作。

(3)注意“网卡的初始化”与“网卡驱动”不是同一个概念,网卡驱动dm9000x.c和dm9000x.h的工作依赖于网卡的初始化。

(4)uboot第二阶段进行一系列的初始化,其中board_init函数(见C阶段的start_armboot函数中的3.2节)通过调用dm9000_pre_init函数对网卡芯片进行了初始化。

(5)三星版本的uboot中的dm9000_pre_init函数内容如下,对网卡的GPIO和端口进行了配置。

从中可知它操作的是bit20-bit23,再对照数据手册中寄存器定义,可以得知三星的开发板DM9000是接在Bank5上的。而X210开发板网卡DM9000是接在bank1上的,因此我们需要操作的bit位是bit4-bit7,将dm9000_pre_init函数修改如下(修改三个寄存器的内容)。

(6)在/include/configs/smdkv210single.h文件中,关于网卡部分的宏定义如下。

【1】CONFIG_DM9000_BASE这个宏的值,是DM9000网卡通过SROM bank映射到SoC中地址空间中的地址。这个地址取决于网卡接到哪个bank。每个bank的基地址是SoC已经定义好而且不能更改的。由于X210开发板的网卡接到了bank1,而bank1的基地址是0x88000000,所以需要将CONFIG_DM9000_BASE修改成0x88000000。但实际要改为0x88000300,0x300跟DM9000网卡芯片型号版本有关,是DM9000网卡本身的问题,其内部寄存器就有一个0x300的一个偏移量。

【2】DM9000_IO这个宏表示访问网卡芯片IO的基地址(网卡芯片中与IO有关的寄存器的开始地址),直接就是CONFIG_DM9000_BASE,不用修改。

【3】DM9000_DATA这个表示我们访问数据时的基地址(网卡芯片中与数据有关的寄存器的开始地址),因为DM9000芯片的CMD引脚接到了ADDR2,因此这里要+4(0b100对应着ADDR2)。

更多原理性的说明,见博客uboot移植——DM9000的移植_天糊土的博客-CSDN博客 。

(7)如何验证网卡驱动已经正确移植呢?

如果能够使用ping命令ping通虚拟机的linux系统,则说明网卡驱动已经正确移植。

9、修改提示符“SMDKV210 #”

这个很简单,修改/include/configs/smdkv210single.h文件中的CFG_PROMPT这个宏即可。

修改之后的效果如下所示: 

 

10、使用sd卡中的uboot启动内核

 uboot的意义在于启动内核,在完成前面的移植工作后,是时候检验uboot能否启动内核了。

(1)将移植后的uboot编译得到的镜像烧写至SD卡。

(2)参考博客利用tftp将镜像下载到开发板,将内核镜像下载到开发板内存中并启动。

(3)成功启动内核之后,打印内容如下:



(4)如果没有成功启动内核(直观表现为:串口没有输出内核启动信息,或者启动打印的信息不对),则需要仔细检查以下几个内容:

【1】uboot使用的输出串口与内核使用的输出串口是否一致。

如果不一致,比如uboot使用串口0打印启动信息,而内核使用串口2打印启动信息,则uboot就算正确引导内核启动,SCRT也不会打印内核启动的信息。

【2】uboot给开发板设定的机器码,是否与内核支持的机器码匹配。

uboot给开发板设定机器码,是在/board/samsung/smdkc110/smdkc110.c文件中的board_init函数中。如下所示,给X210开发板赋予的机器码是2456。

smdkv210开发板,按理对应着uboot源码/arch/arm/mach-s5pv210/mach-smdkv210.c这个文件,但实际对应smdkc110.c这个文件(见kernel移植——从三星官方内核开始移植第二节的第1点)。

在smdkc110.c这个文件中,给smdkv210开发板合成的机器码是“MACH_TYPE_SMDKV210”,值是2456。这个宏在内核源码/include/generated/mach-types.h中也有定义,而这个mach-types.h文件是在内核配置的时候生成的,它维护着该版本内核所支持的全部机器码。在mach-types.h文件中搜索“MACH_TYPE_SMDKV210”得知其值为2456。

【3】查看/include/configs/smdkv210single.h文件中是否定义了bootm传参需要的宏。

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值