三星官方smdkv210 uboot移植到我的s5pv210开发板
北京 2020-7-26 19:44 周日 昨天外面闷热 今日凉快。空调一开啥事没有!O(∩_∩)O
用了差不多两个周末蹲家里移植的。进度比较慢,算是把uboot相关的一些东西基本了解了。
uboot相关的暂时告一段落。之后对linux内核相关的进行整理。
------------------------------------------------------------------------
代码路径:https://github.com/1301876780/-SMDKV210-uboot-s5pv210 每遇到一个问题,解决后我都会上传到我的github
网上找了一张uboot启动流程图。在移植的时候,对照这张图来看看移植时问题出现在了哪个阶段
目标:从三星官方smdkv210的uboot移植到我的s5pv210开发板中能够正常引导内核启动。 这个是我s5pv210正常启动时的打印信息
一.环境配置及编译
- 检查Makefile中的交叉编译工具链
- 配置make smdkv210single_config,对应include/configs/smdkv210single.h头文件,相当于配置文件,包含各种配置
- 配置编译 make distclean/make smdkv210single_config/make
- 下载 uboot/sd_fusing目录下有sd_fusing.sh脚本,用来烧录。
二.uboot移植修改(我们用通道2启动,SD卡方式来烧录)
确认时钟部分的配置
(1)时钟部分的运行结果本来就是对的,时钟部分的代码在lowlevel_init.S中的bl system_clock_init调用的这个函数中。函数的代码部分是没任何问题的,根本不需要改动,要改动的是寄存器写入的值,这些值都在配置头文件(smdkv210single.h)中用宏定义定义出来了。如果时钟部分要更改,关键是去更改头文件中的宏定义。
(2)三星移植时已经把210常用的各种时钟配置全都计算好用宏开关来控制了。只要打开相应的宏开关就能将系统配置为各种不同的频率。
问题1: UBOOT无打印问题
1)uboot无串口打印。这个打印是在INand启动失败时打印的(默认优先从通道0,INand启动),不是uboot中打印的。说明启动方式选择正常。
2)power灯正常亮了,说明开发板的供电锁存正常。
分析:开发板第一次打印的是OK,说明问题出现在了供电锁存之后,打印“O”之前。这一段的代码处理包括:
开发板供电锁存>>>比较运行地址和链接地址决定是否需要beq 1f>>> PMIC_InitIp>> system_clock_init>> mem_ctrl_asm_init>>1:
我们开发板没有集成”PMIC 电源管理集成电路(Power Management IC)”模块。把这个去掉试试
验证后打印如下:
我们一步步解决打印的这几个问题
-------------------------------------------------------------
问题2:DRAM的大小不对,我们只用了两片都是256M的内存,总共只有512M。但是却显示了1G(三星原厂用的是1G
1)在boot下查看信息。通过md/mm/mw命令能读能写,说明内存起始是正常初始化的,只是size错误。
2)修改思路
我们开发板dram0和dram1分别只有256M. 先修改正确的大小。DRAM0起始地址和DRAM1起始地址开始分别都是256M.
启动后DRAM显示总大小512M. 命令行下两片DRAM起始地址没变,大小都为256M。
3)两片DRAM起始地址不连续。 将两片DRAM起始地址变为0x30000000和0x40000000。也就是主要修改DRAM0的各种参数
include/configs/smdkv210single.h
DDR初始化参数更改
(1) DDR的初始化代码部分是在lowlevel_init.S中写的,是不动的。代码部分就是对相应寄存器做相应值的初始化;要动的是值,而uboot为了具有可移植性把值都宏定义在include/configs/xxx.h中了。因此我们只需要去这个配置头文件中更改配置值即可。
DDR初始化硬件配置修改,参数更改
相关宏定义修改:在1)2)中已修改
虚拟地址映射表中相应修改
Uboot第一阶段初始化最后几个阶段,会初始化SDRAM,将uboot剩余代码(负责uboot第二阶段初始化)搬运到到内存中执行,之后需要开启MMU, 再真正的到SDRAM中去执行uboot第二阶段初始化。 也就是在内存中运行的uboot代码是在mmu下执行的。 同时,只有SDRAM正常时才会进入第二阶段执行代码。
验证效果:内存初始化还是有问题
根据板子手册描述(取值范围取反就是chip_mask需要写入的数值)没有对chip_mask进行修改。寻址范围是256M: 0x0---0x0FFFFFFF。 取反得到0xF0
上述修改后启动测试结果:
说明代码已经成功进入到SDRAM中运行uboot初始化第二阶段,但是在初始化外部SD/MMC设备时失败了,
总结:修改DDR片子起始地址修改点:
DRAM修改(都在include/configs/smdkv210single.h配置文件中):
-
- 硬件配置修改:主要是对应dram的chip_base/chip_mask
- 软件配置:基地址,size等
MMU修改:
-
- 映射配置修改(uboot第一阶段中):第二阶段(在dram中)uboot初始化前(sram中),需要设置MMU。由于我们修改了内存起始物理地址,所以虚拟地址映射也需要修改
- 软件层面修改(在include/configs/smdkv210single.h配置文件中宏定义包含了):应用层软件虚拟地址到物理地址函数转换修改
失败的原因就是没有设置应用层软件虚拟地址到物理地址函数转换修改。配置文件include/configs/smdkv210single.h中有对应宏定义
我们修改:将虚拟地址0xc0000000—0xd0000000映射到物理地址0x20000000的256M,修改为映射到0x30000000的256M
启动后显示如下:
EXT_CSD是扩展的卡特殊寄存器,是因为SD控制器和SD卡版本不匹配,低版本的SD控制器是无法操作高版本SD卡。
修改后:
启动基本正常,而且此时也可以直接启动内核了。
-------------------------------------------------------------
问题3:网卡移植
虽然可以启动内核了,但是uboot下网络不可用。开始对DM9000网卡进行修改以适应我们的开发板
一.网卡芯片与开发板的连接方式
(1)SoC的SROM bank和网卡芯片的CS引脚(SROM就是SRAM/ROM)。SoC的SROMController其实就是SoC提供的对外总线式连接SRAM/ROM的接口。如果SoC要外部外接一些SRAM/ROM类的存储芯片(或者伪装成SROM接口的芯片,譬如网卡芯片)就要通过SROM Controller来连接。网卡接在SROM中好处就是网卡芯片好像一个存储芯片一样被扩展在SoC的一个地址空间中,主机SoC可以直接用一个地址来访问网卡芯片内部寄存器。
(2)网卡芯片内部寄存器使用相对地址访问。网卡芯片内部很多寄存器有一个地址,这个地址是从00开始的,但是实际上我们SoC不能用0地址去访问这个网卡的芯片内部寄存器。SoC访问网卡芯片00寄存器时的地址应该是:起始地址+00这里的起始地址就是网卡芯片对应接在SROM bankn中的bankn对应的基地址。
(3)主机SoC上网,其实就是通过操控网卡芯片内部的寄存器、缓冲区等资源来上网的。也就是说其实SoC是通过网卡芯片来间接上网的。
(4)总结:实际上也是一种总线式连接方式。优势是SoC内部不需要内置网卡控制器,所有的SFR全都在外部网卡芯片中,而且还可以通过地址直接访问(IO与内存统一编址),不用像Nand/SD接口一样使用时序来访问。
(5)从逻辑上来看,网卡更像是串口,而不像是SD/Nand。
连接: SOC-------DM9000-----网口
二.原理图浏览
(1)210的SROM控制器允许8/16bit的接口,我们实际使用的是16位接口。
(2)网线有8根线,但是实际只有4根有效通信线,另外4根都是GND,用来抗干扰的。4根通信线中管发送的有2根(Tx-和Tx+),管接收的有2根(Rx+和Rx-)。因为网线上传输的是差分信号。
(3)网卡芯片有个CS引脚,(CS就是chip select,片选信号,主机向CS发送有效信号则从机芯片工作,主机向CS发送无效信号则从机芯片不工作。),这个引脚要接主机SoC的片选信号引脚,主机S5PV210的每一个SROM bank中有一个片选信号CSn(n=0-5),从原理图可以看出,我们X210上将DM9000的CS引脚接到了CSn1上,对应SROM bank1(推断出DM9000的总线地址基地址是0x88000000)。
下面两张图可知: 访问dm9000某个寄存器地址: 0x88000000+DM9000各个寄存器偏移地址
(4)DM9000的CMD引脚接到了S5PV210的ADDR2引脚上。DM9000为了减少芯片引脚数,数据线和地址线是复用的(DATA0到DATA15这16根线是有时候做数据线传输数据,有时候做地址线传输地址的。什么时候做什么用就由CMD引脚决定。)通过查询数据手册知道:当CMD为高电平时对应传输是DATA,当CMD为低电平时对应传输为INDEX(offset,寄存器地址)。
注明:这些引脚上的电平变化都是控制器自动的,不需要程序员手工干预。程序员所需要做的就是在配置寄存器值时充分考虑到硬件电路的接法,然后给相应寄存器配置正确的数值即可。
三.修改及移植:
一个硬件相关芯片的驱动,需soc侧初始化(soc与硬件接线初始化)------ -----------硬件侧相关初始化
由分层和分离思想,分层分出的是驱动(linux内核移植而来,无需修改),分离分出的是数据配置(在配置文件中smdkc110single_config.h中)
所以应该: ①修改soc与dm9000间连线初始化②修改dm9000软件层面配置
uboot在第二阶段init_sequences中进行了一系列的初始化,其中就有网卡芯片的初始化。这个初始化就是关键,在这里的初始化中只要将网卡芯片正确的初始化了,则网卡芯片就能工作(意思是网卡驱动dm9000x.c和dm9000x.h依赖于这里的初始化而工作)。
①:修改soc与dm9000间连线初始化
2.4.1.1 SROM Bus Width & Wait Control Register (SROM_BW, R/W, Address = 0x0000_0000)
2.4.1.2 SROM Bank Control Register (SROM_BC: XrCSn0 ~ XrCSn2)
时钟相关的,暂不改变
2.2.25.1 Port Group MP0_1 Control Register (MP0_1CON, R/W, Address = 0xE020_02E0)
修改后再次测试发现依然打印错误:dm9000 not found at 0x80000000->not responding。 这个地址是SROMnx地址,由内存图可知我们接到了srom_bank1。
- 修改dm9000软件层面配置(smdkc110single_config.h主要是网卡相关配置)
问题4: 现在我们用的是soc内置默认串口2打印输出。SOC总共支持4个串口,仅引出来了串口0和串口2。那如何将串口2换成串口0输出?
还是去配置文件smdkc110single_config.h找一下串口相关:
实际是在s5pc110.h中定义的
那我们只需要在配置文件中修改估计就可以了
验证: 将soc上的串口线从SD2换到SD0口(PC串口号不变),成功打印各种信息
问题5:用我们当前移植的uboot引导内核启动
设置虚拟机桥接模式,与开发板同一网段。从虚拟机tftp服务器中下载内核到内存,从内存中直接启动,显示如下
下载内核成功,但是启动时貌似是卡住了,串口没有任何打印。(检查内核镜像正确性,下载及启动内核地址正确性)
当前uboot不能启动内核
(1)用同样的方法(使用tftp 0x30008000 zImage-qt; 然后bootm 0x30008000),分别使用我们自己移植的uboot和使用九鼎移植版本的uboot去启动内核,发现九鼎移植版本的可以启动,但是我们自己移植的不可以启动。到此我们就断定我们的uboot有问题,不能启动内核。
(2)做基本检查:
首先怀疑是机器码不对。经过和九鼎移植版本的uboot对比发现machid都是2456,说明机器码没错。
参数不正常。 我们把串口改为了串口0,而内核zImage-qt的串口输出在串口2.怀疑可能的问题是uboot使用了串口0而内核使用了串口2所以在uboot后看不到内核的启动信息。
我把环境变量中bootargs中串口由ttySAC2改为ttySAC0,一样没效果。 把配置文件中的串口0改回串口2。发现可以启动内核了,但是启动阶段没什么打印
感觉bootargs中的设置串口数仅仅影响内核启动阶段??
我把bootargs中串口由ttySAC0再改为初始时的ttySAC2。发现启动内核时的各种打印都出现了
问题6:其他一些小修改: The input address don’t need a virtual-to-physical translate: 0x33E9C008
Uboot启动第一阶段可知 我们的虚拟地址映射表可知: 虚拟地址0xc0000000-0xd0000000映射到了0x30000000开始的256M。其他虚拟地址和物理地址的映射都是一一对应的。
0x33E9C008这个虚拟地址在执行时不在虚拟地址0xc0000000-0xd0000000范围内,其按照其本身地址执行即可。
将对应打印去掉即可,不会有任何影响。
Uboot到现在就可以很好的启动内核。