11、1、uboot移植前的准备工作
1、三星移植过的uboot源代码准备
(1)三星对于S5PV210的官方开发板为SMDKV210,对应移植过的uboot是android_uboot_smdkv210.tar.bz2在资源下载中
(2)这个源代码网上是下载不到的,刚开始是下载不到的,三星官方是不会把这些东西放在官网上下载的。这些东西最初都是随着官方的开发板一起流出的。
2、SI的准备
(1)移植的时候,最重要的工作就是看代码,改代码,编译运行测试
(2)编译代码必须在Linux中进行编译(因为要创建符号链接,Windows共享文件夹中配置uboot是不行的),看代码和改代码可以在Linux中(vim)也可以在windows中(SI)。
(3)正确的方法,应该是,在windows中解压一份uboot源代码,在Linux也解压一份源代码,这两分开始时是一模一样的,然后我们移植的时候,是在windows中的这一份去看代码,改代码,然后在Linux中这一份去编译烧写。这种做法需要在windows中和Linux中两分代码之间保持一个同步,就是你windows中改过了后,要把改过后的源代码复制到Linux中那一份去覆盖Linux里面的同目录通文件
(4)问题来了,怎么在windows中和Linux中去同步代码?通过共享文件夹在Linux中进行复制,也可以通过一些专用的工具sshsecureshell
11、2、便捷文件传输工具sshsecureshell
1、windows中安装sshsecureshell客户端
在Ubuntu10.04版本中,重启网卡的命令是 /etc/init.d/networking/ restart
在Ubuntu14.04版本中,重启网卡的命令是 ifdown eth0 ifup eth0 校园网时发现NAT模式下好使
11、3、Ubuntu14.04上网及安装openssh
1、虚拟机上网要注意,你是用桥接上网的,还是NAT模式上网的。第二个要注意,Ubuntu中网络的配置文件中的,/etc/network/interfaces 这个文件中是配置网卡信息的,是静态IP还是dhcp静态IP是多少。第三个如果是桥接模式要注意,要注意桥接到哪个网卡上,一般笔记本有两个网卡,有限网卡和无线网卡。如果是NAT模式是没有关系的。
Ubuntu14.04中重启网卡的命令变了,ifdown eth0 ifup eth0。
如果用的校园网的话,你要想上网只能通过NAT模式,因为我们的电脑要连到校园网的dhcp服务器上,会自动给我们电脑和ubunut分配一个ip地址,所以/etc/network/interfaces 这个文件中的内容,要设置成dhcp自动获取IP地址的方式,同时网络中心中的虚拟机获取方式也要设置成自动获取ip地址的方式。
如果用wife的话,NAT模式也好时,桥接模式也好时。
如果你想让虚拟机Ping通windows,首先虚拟机要选择桥接模式上网,要桥接到有线网卡上,同时由于windows有bug,所以widows的网上口,必须用网线连接到一个有上网能力的地方。之后将,Ubuntu中的/etc/network/interfaces 文件中改成static静态模式,因为这样在每次开机的时候ip地址就不会变了。将里面的ip地址设置成和我们主机windows在同一个网段上。之后重启网卡ifdown eth0 ifup eth0 ,在Ubuntu终端下,ping主机,如果ping通了,就OK了,这时你的SSH通信就可以了。openssh类似的工具就可以使用了
2、搭建openssh环境
(1)、ubuntu上网
(2)、安装openssh-server。如果报错提示依赖错误,可以参考:http://www.cnblogs.com/mliudong/p/4094519.html
(3)securecrt登录
(4)sshsecretshell登录 两者都可以
如果ssh登录不上,要修改/etc/ssh/sshd_config,参考:http://blog.sina.com.cn/s/blog_5f435c130102v6pv.html。 修改完重启时如果/etc/init.d/ssh restart不起作用,可以使用:ps -e | grep ssh,看sshd的进程号,然后kill -9 进程号杀死ssh进程以达到重启的目的,或者直接重启ubuntu系统。
11、4、三星的uboot移植
0、先直接用三星移植过的uboot,看什么情况
1、将uboot复制到Linux的源生目录下,解压。
2、检查makefile中的交叉编译工具链
3、配置,我们配置的时候,因为三星的是smdkv210xxxx,所以我们先重第一个开始试,先用smdkv210single_config来配置一下试试,用这个的话,我们配置头文件是在include/config/smdkv210single.h
4、配置完成后,直接make编译,完了之后直接烧录到SD卡上,启动下试试。
5、在uboot/sd_fusing/sd_fusing.sh 这个脚本是用来烧录的。但有时这个脚本需要修改一些的东西,看脚本中的BL1的位置在哪里,还有整个uboot的大小分别放在了SD的哪个扇区。多少个扇区。应该是1和49,可以从uboot的源代码中找到那个计算公式,自己推到出来。在烧录的过程要看烧录运行时的打印出来的信息,分析看烧录没烧录成功,注意mkdbl1 和sd_fisk文件的属性位数是否和我们当前Ubuntu的位数一致。
6、烧录成功后,插到开发板上试一下。
11、5、 1、代码分析,问题查找
1、插到开发板上启动后,发现打印出来SD 检查错误(这个信息是IROM中做的)。但是电源自锁是工作的。
回想,uboot串口打印信息时,最早打印的是OK,是在start.S中的lowlevel_init中初始化时打印的。串口没有输出O,说明代码在没有执行到O之前,代码就已经死掉了。但是开发板的供电锁存是成功的,供电锁存也是在start.S中的lowlevel_init中,所以说在供电锁存的前面一部分代码是没有问题的。所以可以初步判断,错误在供电锁存之后和串口打印出来O之前这一段代码就有问题了。
2、接着就需要代码的分析了,在windows下建立SI工程。发现可能是lowlevel_init.S中调用PMIC的问题,因为我们开发板并没有这个电源管理芯片,所以当我们调用这个函数的时候,I2C向PMIC发送信息是得不到PMIC电源管理芯片的应答的,所以程序死在了这里。
将上面这个调用PMIC的函数屏蔽掉后,发现uboot可以启动了。但是很多的配置信息是有问题的,很多的功能应该也是不能用的,都要去查验。
3、更改开始打印的uboot版本号后们的值,在start_armboot函数中的调用的display_banner函数中的version_string对应的宏的值,也就是这个宏CONFIG_IDENT_STRING的值为for"xxx",这个宏在smdkv210single.h中,这是关键配置的头文件。改完后,同步到Linux源生目录下,之后在make distclean, make smdkv210single_config, make
4、时钟配置
时钟的代码是不用修改的,在lowlevel_init.S中,因为我们三星用的芯片也是这个芯片,我们用的芯片也是这个芯片,所以我们大多数关注的应该是开发板级别的移植,从串口打印的信息也可以看出来,时钟的配置确实是对的,如果想改时钟的配置,也只是需要在smdkv210single.h头文件中打开或者关闭一个宏即可。如果要改时钟的配置,不用改时钟函数中的代码,只需要改动配置头文件smdkv210single.h中的宏的配置就行。
5、DDR配置信息的更改
(1)因为三星的uboot运行时打印出来的DDR大小是1G,但是我们的DDR是512M的,所以有问题,DDR的相关信息是有问题的。可以在uboot运行的时候,用bdinfo命令看DDR等更多的信息。从bdinfo命令打印出来的信息可以看出来,DDR的起始地址三星配置为0X20000000和0X40000000,DDR的大小每片都配置成了0X20000000(512M大)。
(2)我们使用md命令和mw命令,分别读DDR的内存中的内容,和往内存中写东西,发现DDR是可以用的,所以说明DDR的初始化是成功的,只是配置的不对,我们在访问0X30000000地址时,发现访问的情况和访问0X20000000的情况是一样的,可以说明我们的DDR本身确实是没有512M大的,只有256M大小的,那为什么访问0X30000000和访问0X20000000内存地址处的情况一样呢,可能是内存本身的一些特性,也可能是代码中实现的。
6、DDR地址另外配置
(1)目标,将DDR端口0的起始地址配置为0X30000000,配置成30000000开头的地址就可以和我们板子上的bank1第二片DDR的40000000地址连起来了。因为我们的板子上的大小是256MB。
(2)DDR初始化的代码在lowlevel_init.S中,初始化的代码是不用我们改的,我们只需要改在include/configs/xxx.h中的宏配置就行。
(3)关于DDR相关参数的设置,要结合我们开发板的数据手册进行配置。
将配置头文件中的#define DMC0_MEMCONFIG_0 0x20E01323 改成 #define DMC0_MEMCONFIG_0 0x30E01323
这样的话,将来往那个DMC0CONTRL寄存器中写入的值就变了,寄存中的值变了,相应的硬件就会发生了变化,地址就真的映射到了3开头的地址去了,但是硬件变了,但是软件的配置还没有变,所以我们要把配置文件中的这个宏#define MEMORY_BASE_ADDRESS 0x20000000 内存的基地址也改成 0X30000000,这个是在软件架构成,我们告诉uboot内存的起始地址是从哪里开始的
(4)虚拟地址映射表中相应修改
uboot中开启了MMU对内存进行了段式映射,有一张内存映射表。
(5)怎么找这个虚拟地址映射表呢?
现在start.S中找_mmu_table_base:
.word mmu_table
找到mmu_table相关的符号,找到了mmu_table在去在SI中索引mmu_table处,最后找到是在lowlevel_init.s中。
怎么看呢?
.set __base,0
// Access for iRAM
.rept 0x100
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
意思是从0地址开始的地方到0X10000000地址的地方这256M的空间原样
.rept 0x200 - 0x100
.word 0x00000000
.endr
意思是0x20000000-0x10000000,这段地址映射到了0地址,应该是不可以访问的
.set __base,0x200
// should be accessed
.rept 0x600 - 0x200
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
意思是0x200开头的地址范围到0x600映射到0x200,开始的地址,原样映射
.rept 0x800 - 0x600
.word 0x00000000
.endr
意思是0x8000-0x600地址也是不可访问的
set __base,0x200
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
意思是0x200开头的地址被映射到了0XC00到0XD00范围,一共是256M
(6)所以我们虚拟地址映射表中,应该把C0000000-D0000000地址空间映射到30000000-40000000这个256MB的地址中去
方法是:修改这样
set __base,0x300
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
(7)修改完以后,在细细的检查一下配置头文件中的,关于内存的宏的配置是否正确,主要是看地址是否是我改过的。
(8)运行时,发现只打印出来了OK,经过分析,发现是DMC0_MEMCONFIG_0的问题,把这个宏的值改成0X30F01323,之后在编译烧录,运行,发现好了一部分了。但是到SD卡打印的那段就不运行了。
(9)经过分析是虚拟地址到物理地址的映射函数中的问题。将-0x20000000改成-0x30000000,在 uboot/board/samsung/smdkc110/smdkc110.c中。
(10)iNand驱动问题的解决
@1:先从现象定位问题。将打印出来的错误信息,找到关键字在SI中搜索,发现问题的所在地方,在看当前位置的上下文,来理解是什么原因造成的,最后发现是从mmc设备的扩展寄存器中读取到的版本号大于了我们代码中给的5版本号导致的。我们第一个解决方案是将大于5改成大于8,给一更大的版本号。
@2:其中还有一个事情,就是三星的uboot中,代码中,初始化打印的是mmc通道0的,也就inand,我们如果将这个设备号改成了1,可能就会给外部的SD卡发送读取到SD卡的版本号,inand的版本比SD卡的版本高,虽然两者很类似,所以改了这个通道,可能也会解决问题,就是在初始化mmc设备时的传递的参数。
(11)修改输出到控制台的串口号 ,从三星默认的串口2,修改到串口0,
@1:只需要改动,smdkv210single.h中的关于串口的那一个宏就行。串口初始化的代码是在lowlevel_init.S中,跟标准输入输出绑定的是在seriver.c中。总宏定义决定初始化哪个串口的宏是在smdkv110.h中
(12)修改网络的配置信息,也是在smdkv210single.h中的关于网络配置的宏中修改就行。
(13)在我们uboot刚开始运行的时候,如果你用的mmc设备是0,用的是板子上的inand的话,你的环境变量刚开始用的是uboot内部自带的环境变量的值,但是当你改过了以后你在saveenv后,如果你选择的mmc设备是0的话,那么就会保存到你mmc设备0通道对应的设备中,我们的板子对应的是inand,所以就保存到了inand中了,并不是保存到了你的mmc设备通道1对应的那个sd卡通道2,我们的sd卡,
(14)所以如果我们要破坏inand中的那一份环境变量的值,而想用uboot源码中自带的环境变量的值的话,就需要先破坏掉inand中被从DDR中的环境变量分区保存到了inand中环境变量分区的那一份环境变量,破坏方法就在用mmc writer 0 30000000 11# 32 因为我的环境变量保存时,是放在了第17个扇区,分区大小是32个扇区。意思就是将内存中0x30000000中的开始的环境变量分区到整个环境变量分区的大小,全部写成0,完了之后保存到了mmc设备通道0对应的设备中。所以这个时候,mmc设备中对应的环境变量分区的值就是不对了,将来在校验的时候,就会发现这个设备中没有环境变量可以用,所以用的时候就会用uboot源码中自带的环境变量的值了。
(15)网卡驱动的移植1
@1:srom是sram/rom,是一个统称,SOC内部的srom controller控制器就是SOC对外提供的一种总线式连接sram/rom的一种接口,如果我们的SOC要外部连接一个sram或这rom存储芯片,或者一些伪装成srom接口的芯片(如网卡芯片,DM9000),就需要用到SOC的这个srom controller来连接进行外部扩展。总线式访问的好处就是可以直接用地址的方式来进行访问,不需要通过什么发命令啊什么的,时序好什么的去访问。当网卡芯片通过srom接口接在了soc上的时候,我们的主机soc去访问网卡芯片内部的寄存器时,就可以直接通过总线来用寻址的方式来直接放问网卡芯片。我们的板子上,网卡芯片是接在soc的srom中的一个bank上。
@2:网卡芯片内部有很多个寄存器,既然网卡芯片和我们的soc是通过srom接口进行链接的,我们就可以总线式的寻址去访问网卡芯片,由于网卡芯片内部的寄存器相对于网卡来说,是从0开始编址的,所以我们的soc要想通过地址去访问到网卡芯片内部的寄存器的时候,就要用一个相对地址去访问网卡芯片,就是起始地址+网卡芯片本身寄存器的地址。
起始地址指的就是网卡芯片接在soc的srom的bank上的那个bank对应的地址。也就是用soc访问网卡芯片内部寄存器的时候,要用网卡芯片接在srom bank上的那个基地址加上一个网卡芯片内部地址的。相当于用基地址加偏移量的方式去访问,很好理解。
@3:主机soc要想上网,就要对网卡芯片内部寄存器进行操作和网卡芯片内部的缓冲区(可以理解为内存)来进行上网,所以主机soc是通过网卡芯片来实现间接上网的。
@4:所以,如果连上了网以后,如果主机要通过网络来接受数据的话,网卡芯片硬件会自动的将从网络来的数据放到自己内部的缓冲区中,我们的主机soc只要去这个网卡芯片内部的缓冲区中读取数据就可以了,如果我们的主机soc想通过网路来发送数据的话,就只需要将我们想要发送的数据丢到网卡芯片内部的缓冲区中,就行,网卡芯片硬件也会自动从自己的缓冲区中把数据通过网络发送出去。
@5:通过看我们开发板的原理图,可以知道,我们网卡芯片有16根数据线和我们的soc相连接了,所以说明我们的soc的srom控制器用的16bit接口模式的。
@6:网线有8根线,但是有用的只有四根线,其他四根线是跟抗干扰有管的,这四根有用的线中,两根发,两根收。因为网线中传输的差分信号。差分信号传输的距离相对较远,抗干扰能力也较强
@7:网卡芯片有一个CS引脚:chip selcte,片选信号,意思就是主机向CS发送有效信号,则我们的从机芯片工作,主机向CS发送无效信号,则从机芯片不工作。这个引脚要接到我们soc中的srom bank中的片选信号。我们的每一个srom bank中都有一个片选信号端CSn,从原理图中可以看出来,我们DM9000的片选信号端接在soc中的srom bank1上,因为是cs1,所以我们DM9000相对我们主机soc的总线基地址就是我们主机soc中的sromc bank1的基地址(0x88000000)。
@8:DM9000的CMD引脚接到了soc的addr2引脚上,这个引脚也很重要。DM9000为了减少芯片的引脚数,数据线和地址线是复用的。DATA0-DATA15这16根线是有时做数据线传输数据的,有时做地址线传输地址的,当DM9000的CMD引脚的接受到高电平的时候,代表这时复用的是数据线,当CMD为低电平的时候传输的是地址,在DM9000中叫index,索引的意思,也就是相对于主机的地址的索引地址。这是查DM9000的数据手册时知道的。
@9:这些引脚上面的电平变化都是我们soc中的sromc控制器做的,我们只需要在配置寄存器的值时,充分考虑到硬件电路的接法,给我们相应的寄存器配置正确的值就行。
(15)网卡驱动的移植2
@1:uboot程序中本身就有很多网卡芯片驱动的程序,在uboot/drivers/net文件夹下,有很多个关于不同网卡芯片的驱动程序,大多数都是来自于Linux内核,我们网卡芯片是DM9000,所以我们应该看这个net文件夹下的dm9000.c和dm9000.h
,这两个文件我们目前就不用看了,因为会越看越糊涂的,因为还没有开始学习驱动,对驱动,对Linux内核对网络驱动这块的框架不是很熟悉。
@2:我们可以不用看这个网卡驱动DM9000的代码,因为驱动是做好的,数据和代码是分离开的,这里只是驱动代码,数据是由我们开发板中的接法决定的,数据由一定的数据结构提供,所以驱动具有可移植性,所以这里的代码我们我可以不用动,我们要动的是数据,数据就在smdkc210single.h中关于网卡配置的那些宏
@3:网卡移植的关键:初始化。在uboot的第二阶段,start_armboot中那个函数指针数组中,里面就有一个board_init,这个函数指针指向的那个函数中,就有网卡的初始化,这个初始化才是网卡移植的关键,这个初始化只要把网卡芯片初始化好了,网卡芯片就可以工作(意思是网卡驱动dm9000x.c和dm9000x.h依赖于这里的初始化而工作。)
@4:dm9000_pre_init这个函数就是移植网卡芯片的关键。这个初始化函数和我们开发板上的DM9000硬件连接有关,必须要结合我们开发板的原理图来分析,然后了决定这个函数怎么编程,所以我们要根据自己的开发板的硬件接法去修改这个初始化函数,来让我们的网卡芯片工作
@5:DM9000_16BIT_DATA这个宏用来表示DM9000工作在16位模式下,我们的开发板上的DM9000也是工作在16位模式下的
@6:SROM_BW_REG,从三星的源码中和对应数据手册,可以看出三星将网卡芯片DM9000接在了SOC中的sromc中的bank5上,而我们的开发板DM9000网卡芯片是接在SOC中的srom中的bank1上的,所以根据手册我们要操作这个寄存的bit4-bit7,这里四个bit位表示的是bank1的。
@7:我们是工作在16位模式的,所以这个SROM_BW_REG寄存中的bit4是1,因为我们数据线是一一对齐的,所以bit5是1,其他两位,按照模式来的话,按照别人的经验配置成1,非必须情况可以不用弄清楚这两个位。
@8:所以根据数据手册和实际情况,我们应该修改的寄存有三个SROM_BC5_REG SROM_BW_REG MP01CON_REG,最后一个是在GPIO中。
@8:基地址的配置:修改完上面那个初始化函数后,因为驱动分为两个部分:代码和数据,代码不用动,所以我们还要修改一些数据,在配置头文件中,关于网卡的那些宏。
CONFIG_DM9000_BASE 是DM9000网卡通过srom bank 映射到SOC的地址空间的地址,因为我们用的是srom中的bank1 所以根据数据手册中的内存图,可以知道,我们的基地址应该是0X88000000。
#define DM9000_IO (CONFIG_DM9000_BASE) 这个表示访问我们网卡芯片IO的基地址,寻找芯片内部寄存器等的时候。
#define DM9000_DATA (CONFIG_DM9000_BASE+4) 还有这个宏,我们要改成4,这个宏是来决定我们当前发送的是数据的,当我们要发送数据的时候,由原理图知道,我们的CMD引脚接在了ADDR2,也就第二根地址线上,4的就100,所以就是让第二根地址线保持高电平,这样就表示复用发送数据。
@9:改完这些,网卡实际上不可以直接工作的,还要修改CONFIG_DM9000_BASE 将这个地址的0X88000000改成0X88000300,为什么改成这个呢,猜想可能是因为网卡芯片由于版本的问题,自身有了一个偏移量,在以前的时候,可以用这个0X88000000地址,也就是这个srom bank的地址直接就能找到DM9000本身内部的那些寄存器的起始地址,但是可能由于版本问题,现在DM9000本身的寄存器的地址是从300H开始的。
@10:内核启动不起来,将串口改到串口2,因为三星提供的Linux内核用的是串口2,看配置头文件中有没有这两个宏,
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_CMDLINE_TAG
这两个宏,确保传参的
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。