cortex-a8 uboot系列:第十七章 uboot移植-网卡DM9000移植
0赞一、 网卡基础知识
1. 网卡芯片与开发板的连接方式
总线式连接方式,使用SROM总线接口。
开发板核心板,使用SROM控制器的bank1。因此有效地址是0x8800_0000 – 0xffff_ffff。
开发板上DM9000的连接。使用16-bit数据连接方式
网卡芯片有CS引脚,(CS就是chip_select,选线信号,主机向CS发送有效信号则从机芯片工作,主机向CS发送无效信号则从机芯片不工作)。这个引脚要接soc的srom控制器的片选引脚。
主机s5pv210的srom控制器每一个bank都有一个片选信号CSn(n=0-5),这里接CSn1,说明DM9000接的是srom的bank1。
所以,可以得到DM9000的总线基地址是0x8800_0000。
DM9000的CMD引脚,并接到了210的ADDR2引脚上。为低,表示16位数据线上发送的是地址,为高,表示16位数据线上发送的数据。因此,地址和数据是复用的。
也就是如果要往 DM9000的 0x04地址写入数据a。那么要执行以下两步
第一步:
ADDR2拉低,16位数据写0x04。
第二步:
ADDR2拉高,16位数据写a
也就是 *0x8800_0004 = a
DM9000的通过HR911105A接口与外部网线相连。
网线有8根线,但是实际只有4根有效通信线,另外4根都是GND,用来抗干扰的。4根通信线中管发送的是有2根(TX-和TX+),管接收的2根(RX+和RX-),因为网上传输的是差分信号。
210有SROM控制器,
2. Soc的SROM控制器
Bank和网卡芯片的CS引脚(SROM就是SRAM/ROM)。Soc的srom控制器其实就是soc提供的对外总线式连接sram/rom的接口。如果soc要外部外接一些sram/rom类的存储芯片(或者伪装成srom接口的芯片,如网卡芯片)就要通过srom控制器来连接。
SROM控制器有6个bank,地址和数据都是共有的,但是片选信号不是共用的。因此外部的SROM器件通过连接到自己的片选信号是否有效,从而决定地址和数据是否可用。
网卡接在srom中好处就是网卡芯片好像一个存储芯片一样,被扩展在soc的一个地址空间中,这样soc就可以直接用一个地址来访问网卡芯片的内部寄存器。
1) 网卡芯片内部寄存器使用相对地址访问
网卡芯片内部很多寄存器有一个地址,这个地址是从0x00开始的,但是实际上soc不能用0地址去访问这个网卡的芯片的内部寄存器。
所以soc访问网卡芯片0地址寄存器的地址应该是:起始地址 + 0x00。其中起始地址就是网卡芯片对应接在srom控制器的bankn对应的基地址。
如使用的九鼎开发板,网卡芯片接在bank0,基地址就是0x8000_0000。那么soc使用0x8000_0000访问网卡芯片的0地址寄存器,使用0x8000_0004访问4地址的寄存器。
2) 主机soc上网
其实就是操控网卡芯片内部的寄存器、缓冲区等资源来上网的。也就是soc是通过网卡芯片来间接上网的。
3) 总结
实际上也是一种总线式连接方式。优势是soc内部不需要内置网卡控制器,所有的SFR全都在外部网卡芯片中,而且还可以通过地址直接访问(IO与内存统一编址),不用像NAND/SD接口一样使用时序来访问。
从逻辑上看,网卡更像是soc内部串口等模块。
二、 Uboot中驱动文件
在drivers/net目录下,有很多网卡驱动芯片,对于开发板使用的是DM9000,所以要查看dm9000.h和dm9000.c。这些驱动代码来自于linux kernel源代码。
这个驱动代码是linux内核中设计好的,因此不用修改,在uboot中可以直接使用的。而且因为linux驱动设计的很合理(数据和代码是分开的,这样驱动主要是代码,数据是由硬件开发板中的接法决定,数据由一定的数据结构提供),所以驱动本身具有可移植性。
网卡移植的关键:初始化
Uboot在第二阶段init_sequences中进行了一系列的初始化,其中就有网卡芯片的初始化。这个初始化是关键,在这里的初始化中只要将网卡芯片正确的初始化了,则网卡芯片就能正常工作。
在board/Samsung/smdkc110/smdkc110.c中的board_init函数,就对dm9000进行了初始化。
被注释掉的是三星提供的uboot中的代码,后面新增的是修改的代码。在三星原版中,使用的是SROM的bank5,但是开发板使用的是bank1,因此要对SROM控制器的bank1进行初始化。
SROM_BW设置SROM控制器的总配置。每4个位控制一个bank,对于使用的bank1,操作7-4位。因此要对这几位进行操作。
网卡工作在16-bit模式,所以 DataWidth1为1 。
原理图连接时,srom控制器的数据data15-0接到网卡的data15-0,所以是以字节对齐的,所以AddrMode1 为1。
至于第7位和第6位,和时序相关。这里都设置为1。
SROM_BCx, 设置各个bank的时序信息。
MP0_1CON寄存器,配置SROM控制器的GPIO的片选功能。将7-4位设置为0x20,表示MP01_1管脚为srom的bank1的片选引脚。
照理来说,还需要设定SROM控制器的地址和数据的GPIO的功能,但是对应的GPIO功能默认为就是SROM的地址和数据功能,因此可以不用设置。
基地址的配置
在smdkv210single.h中,关于DM9000有如下的宏定义。
表示基地址是0XA800_0000(因为使用的是bank5),CMD线接在了ADDR1。
根据所用开发板,修改为如下
基地址为0x8800_0000(bank1),CMD线接在了ADDR2,所以数据的地址是基地址+4。
但是上面这样,是不工作的。
需要将CONFIG_DM9000_BASE 定义为 0x88000300。
修改为88000300的原因,应该是和DM9000的芯片有关系,内部寄存器的偏移不是以0地址作为偏移,而是以0x300地址为偏移的。
Uboot中使用ping命令,测试网卡移植是否成功。
如果移植出现以下信息,说明SROM控制器的寄存器配置不正确。检查dm9000_pre_init函数(board/Samsung/smdkc110/smdkc110.c),寄存器设置是否正确。
三、 Linux网卡驱动的典型工作方式
在linux系统中,网卡是一个设备,这个设备驱动工作后会生成一个设备名叫ethn(n是0、1、2……),无线网卡名字一般叫wlan0、wlan1……。
然后linux系统用一些专用命令来操作网卡,如ifconfig命令。
Linux下的应用程序如何使用网卡驱动来进行网络通信?最通用的方法就是socket借口。Linux系统中有一系列的API和库函数,提供了一个socket编程接口,linux下的应用程序都是通过socket来实现上网的,socket内部就是间接调用网卡驱动实现网络通信的。
Linux设计是非常完备的,应用层和驱动层是严格分离的。也就是说写网络编程应用层的人根本不用管驱动,只要会用socket接口即可;写底层驱动的人根本不用管应用层,只要面向linux的网络驱动框架模型即可。
Ping这样的命令实现的代码就是网络应用的应用程序,像dm9000.h和dm9000.c这样的代码属于驱动程序。在uboot中应用是直接调用驱动实现的,也就是说ping命令内部是直接调用了dm9000的网卡驱动中的函数来实现。
1. Uboot的ping命令实现
实现函数是do_ping,在common/cmd_net.c中。
使用string_to_ip函数将输入的ip地址转化为IPaddr_t类型值。
然后调用NetLoop函数(net\net.c中)
函数前面的部分,都是在构建ping的包。
构建好后,使用PingStart函数(net\net.c),准备发送ping包。
最后调用PingSend函数(net\net.c),将包发出去。
前面在构建数据,最后使用ArpRequest函数(net\net.c),将ARP包发送。因为ping使用的是ARP包。
函数在之前也在做数据的处理,最后调用eth_send函数(drivers/net/dm9000x.c中),将数据包发送出去。可以看出,这个函数是和具体的网卡芯片有关的。
这个函数,将指定的包,发送给DM9000网卡,网卡在将该包发送到网络中。
这样,就完成了ping的ARP包的发送。
剩下,就是要接收从网络回发的ARP包。
在net_loop函数的后面,调用eth_rx函数(drivers/net/dm9000x.c中)对网络数据包进行接收。可以看出这个接收函数和具体网卡有关的。
四、 启动内核
使用tftp命令,将镜像下载到内存中,然后使用bootm命令运行内核。
但是要将串口改为串口2。
bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=3 bootcmd=movi read kernel 30008000; movi read rootfs 30b00000 30000; bootm 30008000 30b00000 |
smdkv210single.h中要保证有如下宏,这样uboot才能给linux传递参数。启动内核才能成功。