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

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

一、移植总结

二、移植过程

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

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

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

2、删除无关的文件

移植之前我们首先把不相关的cpu、board、lib目录删除,然后用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”。

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# 
  • 生成的uboot.bin文件位于uboot源码的根目录下。

(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系统中搜索“NAND:”(利用grep "NAND:" -nr ./)得知其定位是/lib_arm/board.c文件的start_armboot函数中,其下一行是nand_init函数,猜想问题出现在这个函数。

(3)在/drivers/mtd/nand/nand.c、/lib_arm/board.c文件中都定义了nand_init函数,我们在函数开始位置,分别在添加代码“puts("this is nand.c !\n");”与“puts("this is board.c !\n");”,根据重新编译与运行的显示信息,得知其调用的是/drivers/mtd/nand/nand.c这个文件。

(4)这里做的移植实验,为何“NAND:   ”之后就没有后续的输出呢?在nand_init函数的下一行添加代码“puts("xjh is a handsome man! \n");”,如下所示。

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

(5)为什么会卡在这个函数呢?我一开始猜想这个函数写错了,但对比X210开发板的uboot的nand_init函数,发现两者是一样的,所以这个函数内部应该不会写错。其次想到X210开发板没有使用nand,因此uboot会卡在nand_init函数,于是我将nand_init函数注释掉,重新编译与运行,发现uboot显示完整的信息。

(6)为什么X210开发板的uboot不出现这个问题?这与是否定义了CONFIG_CMD_NAND这个宏有关。在X210开发板的uboot源码中搜索这个宏,在 ./include/configs/x210_nand.h 文件中定义了这个宏,而x210_sd.h文件中把这个宏注释掉了。由博文uboot源码——根目录下的mkconfig文件分析可知,X210开发板使用的是x210_sd.h文件,因此没有定义CONFIG_CMD_NAND这个宏,所以nand_init函数就不会执行。

(7)为什么移植的uboot出现了这个问题?因为在/include/configs/smdkv210single.h中定义了CONFIG_CMD_NAND这个宏。因此相比于注释掉nand_init函数,把这个宏注释掉是更加合乎规范的选择。但实际上把宏注释掉,执行make的时候有其他差错,因为别处用到这个宏。

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

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

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

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

(3) 由博文uboot源码——C阶段的start_armboot函数的第二节的第10点可知,“Board: SMDKV210”是/board/samsung/smdkc110/smdkc110.c文件中的checkboard函数打印的。

上述修改之后,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即可。 

上述修改之后,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卡版本号的问题。

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

8、网卡驱动的移植

注意到上图中也提示找不到网卡芯片DM9000,但X210开发板实际上有这个网卡。之所以找不到网卡DM9000,这是因为还没有移植网卡的驱动。

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

(2)网卡移植的关键或者说主要工作在于初始化网卡,只要将网卡芯片正确地初始化则网卡芯片就能工作。

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

(4)uboot在第二阶段init_sequences中进行了一系列的初始化,其中board_init函数通过调用/board/samsung/smdkc110/smdkc110.c文件中的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将镜像下载到开发板,在uboot的控制台上,利用tftp命令将内核镜像下载至开发板的内存中(tftp 0x30008000 zImage),然后利用bootm命令启动内核(bootm 0x30008000)。

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



 

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

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

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

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

三星内核中支持的smdkv210开发板,按理它对应着/arch/arm/mach-s5pv210/mach-smdkv210.c文件这个文件,但实际对应的是smdkc110.c这个文件。具体细节见kernel移植——从三星官方内核开始移植第二节的第1点。

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

3、查看/include/configs/smdkv210single.h文件中是否定义了bootm传参需要的宏,如CONFIG_CMDLINE_TAG等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop 文件命令

为什么80%的码农都做不了架构师?>>> * 文件操作 * 查看目录文件 * $ hadoop dfs -ls /user/cl * * 创建文件目录 * $ hadoop dfs -mkdir /user/cl/temp * * 删除文件 * $ hadoop dfs -rm /user/cl/temp/a.txt * * 删除目录与目录下所有文件 …

Swans and ducks, Piešťany, Slovakia

What Makes This a Photo of the Day? I love the slightly off-kilter composition here, with the cluster of birds near the bottom of the frame. This gives a sense of movement and allows the eye to take in the peripheral elements—the ripples of the water and…

python day15

今日内容 昨日内容补充: 对于两个文件中的互相导入md模块问题分析: x 1from md import xprint(x)# md中的xfrom md import xx 1000print(x)# 当前文件中的x __all__ 列表写什么,执行导入语句那个文件就能拿到什么; __all__不写的情况,默认是将所在文件所有的名字都暴露给导入…

如何有效抓取SQL Server的BLOCKING信息

2019独角兽企业重金招聘Python工程师标准>>> SQL Server允许并发操作,BLOCKING是指在某一操作没有完成之前,其他操作必须等待,以便于保证数据的完整性。BLOCKING的解决方法要查看BLOCKING的头是什么,为什么BLOCKING头上…

iOS开发篇——OC 协议和代理设计模式介绍

蓝鸥iOS培训讲师推荐:好久没和大家沟通了,没和大家沟通了,今天就和大家说说有关OC内容协议和代理设计模式。首先要讲的是协议一、协议OC中的协议和接口有些相似,协议中定义的方法,在类中实现。协议一般情况下是用来实现…

uboot的移植——移植uboot官方的uboot到x210开发板

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 参考内容 uboot——官网下载直接移植(一) - biaohc - 博客园 uboot——官网下载直接移植(二) - biaohc - 博客园 uboot移植(一)配置过程分析_LouisGou的博客-CSDN博客 获取…

[转载]使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)...

前言 本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术,还需思考产品的设计,如何将新加的功能更好的融入到现有的产品中,并不是简单的加一个界面就行了,欢迎大家交流产品设计和技术细节实现&#xff01…

Hibernate上路_16-继承关系映射

2019独角兽企业重金招聘Python工程师标准>>> 例:员工Employee分为正式工SalaryEmployee和临时工HourEmployee。子类表的字段都不能使用非空约束。 1.三种继承关系的建表方式: 1)父类、子类在同一张表,表中有“辨别者…

C++起航篇——bool类型,输入输出,命名空间

以下内容源于慕课网http://www.imooc.com/course/list?ccplusplus的学习整理,如有侵权,请告知删除。 慕课网学习内容 一、起航 二、离航 三、远征 封装继承多态模板 1、c的新特征 (1)新数据类型 bool (true和fals…

C++离航篇——引用,const

以下内容源于http://www.imooc.com/learn/381的学习整理,如有侵权,请告知删除。 一、引用 (1)引用即定义别名 对引用进行操作即对本身操作;int a10; int &ba; //定义了a的别名b;注意别名是不包括&…

【广搜】棋盘游戏

题目描述 在一个4*4的棋盘上有8个黑棋和8个白棋,当且仅当两个格子有公共边,这两个格子上的棋是相邻的。移动棋子的规则是交换相邻两个棋子。现在给出一个初始棋盘和一个最终棋盘,要求你找出一个最短的移动序列使初始棋盘变为最终棋盘。Klux说…

C++离航篇——函数默认参数、函数重载、内敛函数

1、函数的默认参数 2、函数的重载 (1)在相同的作用域内,用同一个函数名定义的多个函数,其中每个函数的参数个数、参数类型不同。 3、内联函数 (1)编译的时候,将函数体代码和相应的实参直接在函…

C++离航篇——内存的申请释放

1、内存的申请和释放 使用关键字new,紧接申请的类型,以及用中括号标明申请多大的内存空间。 2、内存的初始化 注意和块内存申请不同,初始化是(),块内存是[ ]。

C++远征之封装篇——类和封装、实例化和对象成员访问

一、封装篇的学习内容数据成员 成员函数构造函数 析构函数对象复制 对象赋值对象数组 对象指针this指针二、类与封装三、实例化和对象成员访问(1)从栈中实例化对象(2)从堆中实例化对象 (3)对象成员的访…

C++远征之封装篇——字符串类型

一、c中的字符串操作函数 二、字符串类型string 1、c中没有字符串类型,只有字符类型 因此对于字符串的操作,一般是用上面的函数来操作。 2、字符串的初始化 3、字符串相关的操作

C++远航之封装篇——数据的封装

以对象为中心,具体来说,以谁做什么来代表程序的逻辑。所有操作都通过调用自己的函数来完成。 数据成员暴露了,不好的设计: 数据的封装:

游戏大厅 从基础开始(7)--绕回来细说聊天室(中间偏下)之女仆编年史2

老少爷们儿反击战 上一篇中 我们的女仆终于可以做一些像阳光下其他人一样的事情了,少爷们可以和女仆酱一起参加下午茶~ 难得的上流社会啊 这是永远1v1被人私有的女奴 和 喝茶时被人共有的女仆酱最明显的差异~ 明媚的午后阳光下,庭院里白色长餐桌两旁&am…

【转载】App.config/Web.config 中特殊字符的处理

写一个网站,遇到一个问题,发布以后,提示错误,但是即使打开错误提示(在web.config中打开),还是只提示错误,没提示什么地方错误,这让我知道了:是webconfig本身的…

C++远航之封装篇——类外定义和::

1、类内定义是把函数的具体实现写在类内部,默认是inline函数。 2、类外定义包含两种情况: (1)同文件类外定义 (2)不同文件类外定义