嵌入式uboot移植之三星官方uboot开始移植

注:以下内容来自朱老师物联网课件

1. 移植前的准备工作

1.1 获取三星移植过的uboot源代码

我们使用的是老师提供的android_uboot_smdkv210.tar.bz2,文件存储在课件2.3.零距离初体验uboot部分

1.2 SourceInsight准备

(1)移植的时候最重要的工作就是看代码、改代码然后编译运行测试。
(2)编译代码必须在linux中(windows共享文件夹中配置uboot不行的),那么看代码和改代码可以在linux中(vim、gedit)也可以在windows中(Sourceinsight)。
(3)我一般习惯的方式是:在windows中解压一份uboot源代码,在linux中也解压一份,注意这两份代码原始情况是一模一样的。然后移植的时候是在windows中这一份中去看代码、改代码;在linux中这一份去编译烧写。这种做法需要在windows中和linux中2份代码之间保持同步(直白点说就是windows中改过了后要把改过的源代码复制到linux中那一份去覆盖linux中那一份里面的同目录同文件)。
(4)问题来了,怎么在windows中和linux中同步代码?通过共享文件夹在linux中进行复制(cp /mnt/hgfs/winshare/xxx.c ./);通过一些专用工具,譬如sshsecureshell。

1.3 Ubuntu 上网

上网的方式有两种:NAT和桥接
我们要连接开发板的话就要使用桥接的方式
(1)虚拟机上网有2种模式,NAT和桥接。
(2)虚拟机上网配置要注意这几个地方:
第一个要注意选择NAT还是桥接模式;
第二个要注意ubuntu中网络配置文件/etc/network/interfaces,这个文件中是配置网卡信息的(譬如静态ip还是dhcp,静态ip地址是多少等);

如下为我的interfaces文件设置

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.1.109
netmask 255.255.255.0
gateway 192.168.1.1

第三个如果是桥接模式要注意桥接到哪个网卡上(一般笔记本都有2个网卡,一个是有线网卡一个是无线网卡),如果是NAT模式没关系。
(3)ubuntu14.04中重启网卡的命令变了。(ifdown eth0 ifup eth0)

(4)几种常见的上网配置过程

  • 演示:NAT方式下上网配置过程。
    前提是主机windows通过无线wifi上网了(或者windows通过有线上网也可以)。然后在虚拟机中配置2点:第一选择NAT方式,第二配置/etc/network/inerfaces文件中使用dhcp方式;然后重启网卡,确认ip地址得到后即可上网。
  • 演示:桥接方式上网配置过程。
    前提是主机windows通过无线wifi上网了(主机通过有线网卡上网的配置方式有不同)。然后虚拟机中配置注意三点:第一选择桥接方式,第二配置桥接到无线网卡(如果主机windows是通过有线上网的,则桥接到有线网卡);第三配置/etc/network/inerfaces文件中使用dhcp方式;然后重启网卡,确认ip地址得到后即可上网。
  • 演示:虚拟机要ping通开发板的配置过程。
    前提是开发板和电脑之间通过网线连接好。然后虚拟机中配置注意三点:第一选择桥接方式,第二配置桥接到有线网卡(如果配置为自动或者配置桥接到无线网卡则肯定无法ping通开发板);第三配置/etc/network/inerfaces文件中使用static方式,ip地址配置保证和主机windows、开发板三者处于同一网段;然后重启网卡,确认ip地址得到后即可ping通开发板。

(5)windows系统中有一个bug,如果windows没有检测到有线网卡连接了外部网络则windows中本地连接是不工作的,网卡不工作。解决方案是用网线随便连接一个有联网能力的东西即可,譬如网线连接你的电脑到旁边兄弟的电脑上,譬如插上你的开发板(开发板中运行了linux系统),譬如插上路由器端口。

1.4 文件传输工具SSH(secure shell)

SSH(Secure SHell)使用
第一步 :在windows中安装sshsecureshell客户端:找到SSHSecureShellClient-3.2.9.exe,直接按照一般Windows软件安装即可。

第二步: 在Ubuntu安装ssh服务器openssh-server
功能(让远程主机可以通过网络访问sshd服务,开始一个安全shell)
在Ubuntu下输入:sudo apt-get install openssh-server,出现依赖问题可参考------>ubuntu安装openssh-server 报依赖错误的解决过程
注意: 获取依赖的版本时你的Ubuntu必须是联网下载的,为了在线获取对应的版本,
提示了系统中openssh-client被降级后,这样再安装openssh-server就可以了。

第三步: 在Windows中登录Ubuntu ,点击Quick Connect ,然后输入Ubuntu的IP地址和用户名,选择登录方式,登录。
嵌入式uboot移植之三星官方uboot开始移植
如果出现登录不上,让你重复输入密码,或者普通用户可以登录,但是root用户就是不行,可以参考如下文档进行设置(主要是sshd的默认配置设置)
【笔记】Ubuntu14.04解决ssh登录不上

1.5 secureCRT登录

在上一章节中我们在Ubuntu安装ssh服务器openssh-server已经安装成功,那么我们也可以使用我们的串口工具进行登录
嵌入式uboot移植之三星官方uboot开始移植
嵌入式uboot移植之三星官方uboot开始移植

2. 移植初体验

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

第一步:先将我们要移植的uboot拷贝到Linux下,解压。(实际操作)
第二步:在Windows中我们使用SI打开要移植的uboot对应的工程(方便查看)
第三步:首先我们查看Makefile中的交叉编译工具链是否和我们的匹配
我们在147行找到了配置文件,并且这个和我们实际是匹配的

 CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

第四步:查找配置文件
虽然我们没有找到我们板子的S5PV210的配置文件,但是我们找到了相似的(2581~2583)
配置文件

 smdkv210single_config : unconfig
        @$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110
        @echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/smdkc110/config.mk

2.2 根据实际结果进行逐步修改

第一次尝试编译运行
现象:我们发现串口只输出:SD checksum Error ,没有OK输出,但是开发板电源置锁是正常的。
解决方案:我们顺着start.S 发现开发板置锁是在lowlevel_init(我们找到的是在smdkc110中)中,并且串口初始化也在这里面,如果正常就会输出‘O’,这样的话我们锁定了范围就在电源置锁之后,串口初始化之前,最后发现了bl PMIC_InitIp ,但是我们没有使用电源管理,所以这里直接屏蔽。

第二次尝试编译运行,显示如下的画面,并且卡在了NAND这个部分,;说明我们上一步已经成功解决,但又遇到了新的问题
问题1:DRAM显示信息出错,我们应该是512MB
问题2:SD/MMC fail
问题3:hang在NAND的部分
嵌入式uboot移植之三星官方uboot开始移植
我们找到了配置文件:smdkv210single.h
修改了起始地址 :MEMORY_BASE_ADDRESS 0x30000000
修改了每块内存的大小为256MB:SDRAM_BANK_SIZE 0x10000000

第三次编译运行。我们观察到DRAM的问题1已经解决,现在已经可以显示512MB了

所以这次我们直接将smdkv210single.h中nand的条件编译拿掉
遇到了一个问题,只要拿掉smdkv210single.h中nand的条件编译编译就会报错,猜测是影响到了110.h的某个配置,所以我们采用直接在board.c中直接屏蔽掉nand这段代码
第四次编译运行。就已经将NAND屏蔽掉了。所以问题3解决了
嵌入式uboot移植之三星官方uboot开始移植
小测试:
目标:将DDR端口0地址配置为30000000开头
目的:第一是让大家体验内存配置的更改过程;
第二是3开头的地址和DRAM bank1上40000000开头的地址就连起来了。这样我们就得到了地址连续的512MB内存,而原来我们得到的512MB内存地址是断续的。
(1) DDR初始化参数更改
根据裸机中讲DDR初始化部分的课程,和uboot前面分析uboot中DDR初始化部分的代码的课程,得出结论就是:DDR的初始化代码部分是在lowlevel_init.S中写的,是不动的。代码部分就是对相应寄存器做相应值的初始化;要动的是值,而uboot为了具有可移植性把值都宏定义在include/configs/xxx.h中了。因此我们只需要去这个配置头文件中更改配置值即可。
更改内容是:#define DMC0_MEMCONFIG_0 0x20E01323改为:
#define DMC0_MEMCONFIG_0 0x30E01323 注意20改为30了。
(2) uboot中DDR相关的一些软件配置值
#define MEMORY_BASE_ADDRESS 0x20000000改为:
#define MEMORY_BASE_ADDRESS 0x30000000
(3) 虚拟地址映射表中相应修改
通过之前的学习我们知道这个设置是在第一阶段start.s中完成的,所以顺着start.s我们在lowlevel_init.s中找到了mmu_table:

//.set __base,0x200
	.set __base,0x300
	// 256MB for SDRAM with cacheable
	.rept 0xD00 - 0xC00
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr

(4)修改虚拟地址到物理地址的映射函数
修改uboot/board/samsung/smdkc110/smdkc110.c中的virt_to_phy_smdkc110,将其中的20000000改为30000000。
(5)修改DMC0的配置信息
实验验证,发现只显示SD checksum Error OK这一部分就停止了,说明uboot的第二阶段没有开始,也就是我们DDR的初始化有问题,我们发现是DMC0的配置问题
#define DMC0_MEMCONFIG_0 0x30E01323 中的E0改为F0
嵌入式uboot移植之三星官方uboot开始移植
再次验证:就可以正常启动了,并且0x30000000 中的内容和0xc0000000内容一致,说明地址映射成功
嵌入式uboot移植之三星官方uboot开始移植

下来就是SD/MMC 的问题了,猜测是mmc_initialize,但是直接找比较困难,我们根据输出的fail信息进行查找EXT_CSD ,在mmc的mmc.c中我们找到了这个函数,可以发现这是个判断版本的函数,我们这里暂时将它改为8,但是后续会造成什么结果目前我们还不知道。

	ext_csd_struct = ext_csd[EXT_CSD_REV];
	if (ext_csd_struct > 5) {
		printf("unrecognised EXT_CSD structure "
			"version %d\n", ext_csd_struct);
		err = -1;
		goto out;
	}

第五次编译运行。我们可以看到SD/MMC 已经得到了解决,但是后面出现了一行报错信息
:The input address don’t need a virtual-to-physical translation :23e9c008
嵌入式uboot移植之三星官方uboot开始移植
通过查找,我们在smdkc110.c中发现了这条报错信息,看代码的意思是如果addr在0xc0000000~ 0xd0000000之间就进行虚拟地址到物理地址的转换,通过实际测试,我们执行的也是上面的这个函数,根据我们的地址映射表我们只有0xc0000000~ 0xd0000000这段进行了映射,其他都没有进行映射,这里的这条提示信息我们可以直接屏蔽掉。

#ifdef CONFIG_MCP_SINGLE
ulong virt_to_phy_smdkc110(ulong addr)
{
	if ((0xc0000000 <= addr) && (addr < 0xd0000000))
		return (addr - 0xc0000000 + 0x20000000);
	else
	/*
		printf("The input address don't need "\
			"a virtual-to-physical translation : %08lx\n", addr);
	*/
	return addr;
}
#else
ulong virt_to_phy_smdkc110(ulong addr)
{
	if ((0xc0000000 <= addr) && (addr < 0xd0000000))
		return (addr - 0xc0000000 + 0x30000000);
	else if ((0x30000000 <= addr) && (addr < 0x50000000))
		return addr;
	else
		printf("The input address don't need "\
			"a virtual-to-physical translation : %08lx\n", addr);

	return addr;
}
#endif
	

第六次编译运行。我们就能看到uboot显示的log信息是没有问题的了
嵌入式uboot移植之三星官方uboot开始移植

2.3 一些零散的参数修改

  1. 尝试修改串口
    我们在lowlevel_init.s中会进行串口的初始化,所以我们直接查找可以得到串口的改变是通过条件编译宏(#define CONFIG_SERIALn)的方式来控制ULCONn寄存器,我们实际使用的是#define CONFIG_SERIAL3 ,如果需要修改直接更改数字3即可。并且将硬件连接到对应的接口。
#if defined(CONFIG_SERIAL1)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#elif defined(CONFIG_SERIAL2)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)
#elif defined(CONFIG_SERIAL3)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET)
#elif defined(CONFIG_SERIAL4)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART3_OFFSET)
#else
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#endif

  1. 修改默认网络地址设置
    (1)修改配置头文件smdkv210single.h中的CONFIG_IPADDR等宏,则可以修改uboot的默认环境变量。
    (2)更改完成后如果环境变量还是原来的,正常。因为原来uboot执行过saveenv,因此环境变量已经被保存到iNand中的ENV分区中去了。uboot启动后校验时iNand的ENV分区中的环境变量是正确的,因此会优先加载。我们在uboot源代码中修改的只是默认的环境变量。解决方案是擦除掉iNand中的那一份环境变量,然后迫使uboot启动时使用uboot代码中自带的默认的这一份环境变量,就可以看到了。
    (3)可以使用mmc指令擦除我们之前在inand里面的那一份,十六进制的11表示十进制的17
DonkeV210 # help mmc
mmc read <device num> addr blk# cnt
mmc write <device num> addr blk# cnt
mmc rescan <device num>
mmc list - list available devices

mmc write 0 30000000 11# 32(表示将DDR的0x30000000开头的一段内存中的内容写入iNand中的第17个扇区开始的32个扇区内,写入长度是32个扇区长度(16KB))
执行成功后,重启发现环境变量已经被更改了。
总结: 系统在启动过程中如果发现iNand中有通过CRC校验的环境变量,就不会执行程序中设定的全局变量,当我们擦除iNand 中的那一份后,系统就会将全局变量作为默认的环境变量放进iNand 中。

  1. 修改提示符,直接在smdkv210single.h头文件中对相应的宏进行更改即可。

2.4 网卡驱动移植

2.4.1 什么是网卡

如下网卡信息摘录自----->网关,网卡

  1. 什么是网卡?
    计算机与外界局域网的连接是通过主机箱内插入一块网络接口板(或者是在笔记本电脑中插入一块PCMCIA卡)。网络接口板又称为通信适配器或网络适配器(adapter)或网络接口卡NIC(Network Interface Card)但是现在更多的人愿意使用更为简单的名称“网卡”。

  2. 网卡的作用?
    网卡是工作在数据链路层的网路组件,是局域网中连接计算机和传输介质的接口,不仅能实现与局域网传输介质之间的物理连接和电信号匹配,还涉及帧的发送与接收、帧的封装与拆封、介质访问控制、数据的编码与解码以及数据缓存的功能等。
    网卡的主要功能有以下三个:
      1.数据的封装与解封:发送时将上一层交下来的数据加上首部和尾部,成为以太网的帧。接收时将以太网的帧剥去首部和尾部,然后送交上一层;

2.链路管理:主要是CSMA/CD协议的实现;

3.编码与译码:即曼彻斯特编码与译码。

2.4.2 硬件连接与原理图

网卡芯片与开发板的连接方式
(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。
嵌入式uboot移植之三星官方uboot开始移植
嵌入式uboot移植之三星官方uboot开始移植
原理图分析
(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)。
嵌入式uboot移植之三星官方uboot开始移植
嵌入式uboot移植之三星官方uboot开始移植

(4)DM9000的CMD引脚接到了S5PV210的ADDR2引脚上。DM9000为了减少芯片引脚数,数据线和地址线是复用的(DATA0到DATA15这16根线是有时候做数据线传输数据,有时候做地址线传输地址的。什么时候做什么用就由CMD引脚决定。)通过查询数据手册知道:当CMD为高电平时对应传输是DATA,当CMD为低电平时对应传输为INDEX(offset,寄存器地址)。
嵌入式uboot移植之三星官方uboot开始移植

注明:这些引脚上的电平变化都是控制器自动的,不需要程序员手工干预。程序员所需要做的就是在配置寄存器值时充分考虑到硬件电路的接法,然后给相应寄存器配置正确的数值即可。

2.4.3 网卡驱动文件介绍

(1)uboot中本来就提供了很多网卡芯片的驱动程序,在uboot/drivers/net/dm9000x.c和dm9000x.h。这个驱动来自于linux kernel源代码。所以我们uboot中是移植而不是编写。
(2)要想彻底看懂这个驱动,必须对linux的驱动模型中网络设备驱动有一定的理解才可以。因为我们还没学驱动,因此这个源代码就不用看了。
(3)这个驱动是linux内核中做好的,根本不用动可以在uboot中直接使用的。而且因为linux驱动设计的很合理(数据和代码是分开的,这里驱动主要是代码,数据是由硬件开发板中的接法决定的,数据由一定的数据结构来提供。),所以驱动本身具有可移植性。这个就决定了我们移植DM9000驱动时这个驱动文件dm9000x.c和h不用动,要动的是数据。

2.4.3 网卡移植的关键:初始化

(1)uboot在第二阶段init_sequences中进行了一系列的初始化,其中就有网卡芯片的初始化。这个初始化就是关键,在这里的初始化中只要将网卡芯片正确的初始化了,则网卡芯片就能工作(意思是网卡驱动dm9000x.c和dm9000x.h依赖于这里的初始化而工作)。
(2)网卡初始化代码地方在:

start_armboot
	init_sequence
		board_init
			dm9000_pre_init		这个函数就是移植的关键

(3)dm9000_pre_init函数主要功能就是初始化DM9000网卡。这个初始化过程和我们开发板上DM9000网卡芯片的硬件连接方式有关。必须要结合开发板原理图来分析,然后决定这个函数怎么编程。

之前的代码

static void dm9000_pre_init(void)
{
	unsigned int tmp;

#if defined(DM9000_16BIT_DATA)
	SROM_BW_REG &= ~(0xf << 20);
	SROM_BW_REG |= (0<<23) | (0<<22) | (0<<21) | (1<<20);

#else	
	SROM_BW_REG &= ~(0xf << 20);
	SROM_BW_REG |= (0<<19) | (0<<18) | (0<<16);
#endif
	SROM_BC5_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));

	tmp = MP01CON_REG;
	tmp &=~(0xf<<20);
	tmp |=(2<<20);
	MP01CON_REG = tmp;
}

嵌入式uboot移植之三星官方uboot开始移植

对照代码查询数据手册,可以知道官方使用的是bank5[23:20],所以我们只需要将其改为bank1[7:4]就可以了。其中bit4表示我们使用的位数,bit5表示字节对齐,bit6表示Enables WAIT,bit7表示Using UB/LB
SROM_BC5_REG 寄存器是时序相关的设定,这里我们直接使用之前的数值即可,所以改为我们对应的寄存器SROM_BC1_REG
MP01CON_REG这个控制器是在设定我们的CSn[1],根据硬件电路可知,我们使用的是CSn[1],也就是2<<4
嵌入式uboot移植之三星官方uboot开始移植

(4)原来的代码是三星的工程师根据三星的开发板SMDKV210的硬件接法来写的程序,我们要根据自己的开发板的硬件接法去修改这个程序,让网卡在我们的开发板上能工作。
(5)#define DM9000_16BIT_DATA这个宏用来表示DM9000工作在16位总线模式下。根据上节课的硬件原理图的分析,可以看到我们开发板上DM9000确实工作在16位模式下。
(6)从三星版本的代码中可以看出,它操作的是bit20-bit23,对照数据手册中寄存器定义,可以看出三星的开发板DM9000是接在Bank5上的。而我们接在bank1上的,因此我们需要操作的bit位是bit4-bit7

总结:三个寄存器的修改。主要是三星的开发板DM9000接在bank5,我们接在了bank1上,因此要做一些修改。

2.4.3 基地址的配置等

(1)之前说过,驱动分为2部分:代码和数据。代码不用动,数据要修改。
(2)CONFIG_DM9000_BASE是DM9000网卡通过SROM bank映射到SoC中地址空间中的地址。这个地址的值取决于硬件接到了哪个bank,这个bank的基地址是SoC自己定义好的。譬如我们这里接到了bank1上,bank1的基地址是0x88000000.
(3)DM9000_IO表示访问芯片IO的基地址,直接就是CONFIG_DM9000_BASE;DM9000_DATA表示我们访问数据时的基地址,因为DM9000芯片的CMD引脚接到了ADDR2,因此这里要+4(0b100,对应ADDR2)
(4)本来这样配置就完了,重新编译运行网卡就应该工作了。但是实际测试发现不工作,要怎么样修改呢?修改方式是将CONFIG_DM9000_BASE改成0x88000300就工作了。
问题?这个0x300从哪里来的?我得出的感觉最靠谱的解释是:跟DM9000网卡芯片型号版本有关,我认为这个0x300是DM9000网卡本身的问题,他本身的内部寄存器就有一个0x300的一个偏移量。

烧录尝试启动
注意点:如果出现ping过程中卡死就说明是在函数中出问题了,导致程序出不来,这个时候看看SROM_BW_REG |= (0<<23) | (0<<22) | (0<<21) | (1<<20);是否已经更改SROM_BW_REG |= (1<<7) | (1<<6) | (1<<5) | (1<<4);

通过实际验证我们发现0x88000300和0x88000000都是可以ping通的。所以我们的网卡移植是成功的。

3. 网卡驱动如何工作

3.1 linux系统中网卡驱动的典型工作方式简介

(1)在linux系统中,网卡算是一个设备,这个设备驱动工作后会生成一个设备名叫ethn(n是0、1、2、····)(无线网卡名字一般叫wlan0、wlan1····)。然后linux系统用一些专用命令来操作网卡,譬如ifconfig命令。
(2)linux下的应用程序如何使用网卡驱动来进行网络通信?最通用的方法就是socket接口。linux系统中有一系列的API和库函数,提供了一个socket编程接口,linux下的应用程序都是通过socket来实现上网的,socket内部就是间接调用的网卡驱动实现网络通信的。
(3)linux设计是非常完备的,应用层和驱动层是严格分离的。也就是说写网络编程应用层的人根本不用管驱动,只要会用socket接口即可;写底层驱动的人根本不用管应用层,只要面向linux的网络驱动框架模型即可。

3.2 uboot中网卡驱动的工作方式简介

(1)一定要记住:uboot本身是一个裸机程序,是一个整体,没有分层。所以uboot中根本没有驱动和应用的概念。
(2)按照逻辑来说,ping这样的命令实现的代码就是网络应用的应用程序,像dm9000x.c和dm9000x.h这样的代码属于驱动程序。所以在uboot中这些东西是揉在一起的,应用是直接调用驱动实现的。也就是说ping命令内部是直接调用了dm9000的网卡驱动中的函数来实现自己的。

3.3 以ping命令为例查找代码验证分析

(1)ping命令是uboot的众多命令之一,ping命令实现的函数叫do_ping
(2)函数的调用关系:

do_ping
	NetLoop
		PingStart
			PingSend
				ArpRequest
					eth_send(dm9000x.c中)

(3)验证了2.11.11.3中说的uboot中应用程序(ping)调用驱动程序(dm9000x.c)的方式。这就是一种直接调用的方式。

注:lcd驱动与logo显示,在2.13.uboot杂记-logo显示和fastboot原理等中详解

4. 使用自己移植的uboot启动内核

问题:当前uboot不能启动内核

首先,我们的环境变量还没更改,所以我们先改环境变量中的bootcmd和bootargs
注意:我们更改bootcmd时使用的是单引号,set bootcmd ‘movi read kernel 30008000; bootm 30008000’

之前在命令学习的2.2.2 run_command函数实现过程章节很疑问这个单引号会在那里使用,今天这个就是很好的例子------->嵌入式之uboot的命令体系学习笔记

改完之后直接就可以启动了。
如果出现不能启动可以尝试如下的方法,一步步确认问题。

(1)用同样的方法(使用tftp 0x30008000 zImage-qt; 然后bootm 0x30008000),分别使用我们自己移植的uboot和使用九鼎移植版本的uboot去启动内核,发现九鼎移植版本的可以启动,但是我们自己移植的不可以启动。到此我们就断定我们的uboot有问题,不能启动内核。
(2)做基本检查:首先怀疑是机器码不对。经过和九鼎移植版本的uboot对比发现machid都是2456,说明机器码没错。
(3)想到一个问题,我们之前做实验时将串口改为了串口0,而内核zImage-qt的串口输出在串口2.怀疑可能的问题是uboot使用了串口0而内核使用了串口2所以在uboot后看不到内核的启动信息。

根据现象分析,定位问题并试图解决
(1)如果已经启动了内核,那没什么好说的了。应该是可以直接启动了。
(2)如何内核没有启动,是smdkv210single.h中没有定义bootm传参需要的那几个宏造成的。

上一篇:NAND Flash与eMMC的区别


下一篇:H7-TOOL重大更新发布,开始支持外网控制,eMMC支持加密,脱机烧录新增赛普拉斯和复旦微等(2021-07-02)