注:本文是学习朱老师课程整理的笔记,基于三星官方uboot-1.3.4和九鼎X210BV3S开发板进行移植。
前面移植过程见三星官方uboot移植实战1
问题9:网卡驱动移植
SoC的SROM Controller(SROM就是SRAM/ROM)其实就是SoC提供的对外总线式连接SRAM/ROM的接口。如果SoC要外部接一些SRAM/ROM类的存储芯片就要通过SROM Controller来连接。网卡接在SROM中好处就是网卡芯片好像一个存储芯片一样被扩展在SoC的一个地址空间中,主机SoC可以直接用一个地址来访问网卡芯片内部寄存器。
网卡芯片内部寄存器使用相对地址访问。网卡芯片内部寄存器都有自己的地址,这个地址是从0偏移量开始的。
但是实际上SoC不能用0地址去访问这个网卡的芯片内部寄存器。SoC访问网卡芯片寄存器时的地址应该是:SROM bankn地址+网卡寄存器地址的偏移量。
主机SoC上网,其实就是通过操控网卡芯片内部的寄存器、缓冲区等资源来上网的。X210的SROM控制器允许8/16bit的接口,九鼎的X210开发板实际使用的是16位接口。网卡芯片有个CS引脚,(CS就是chip select,片选信号,主机向CS发送有效信号则从机芯片工作,主机向CS发送无效信号则从机芯片不工作。),这个引脚要接主机SoC的片选信号引脚,主机S5PV210的每一个SROM bank中有一个片选信号CSn(n=0-5),从原理图可以看出,X210开发板上将DM9000的CS引脚接到了CSn1上,对应SROM bank1,由此可以知道DM9000的总线地址基地址是0x88000000。
DM9000的CMD引脚接到了S5PV210的ADDR2引脚上。DM9000为了减少芯片引脚数,数据线和地址线是复用的(DATA0到DATA15这16根线是有时候做数据线传输数据,有时候做地址线传输地址的。什么时候做什么用就由CMD引脚决定。)通过查询数据手册知道:当CMD为高电平时对应传输是DATA,当CMD为低电平时对应传输为INDEX(offset,寄存器地址)。
注明:这些引脚上的电平变化都是控制器自动的,不需要程序员手工干预。程序员所需要做的就是在配置寄存器值时充分考虑到硬件电路的接法,然后给相应寄存器配置正确的数值即可。
补充:网线有8根线,但是实际只有4根有效通信线,另外4根都是GND,用来抗干扰的。4根通信线中发送数据的有2根(Tx-和Tx+),接收数据的有2根(Rx+和Rx-)。因为网线上传输的是差分信号。
uboot中本来就提供了很多网卡芯片的驱动程序,在uboot/drivers/net/dm9000x.c和dm9000x.h。这个驱动来自于linux kernel源代码。要想彻底看懂这个驱动,必须对linux的驱动模型中网络设备驱动有一定的理解才可以。这里只要能移植过来就可以。uboot在第二阶段init_sequences中进行了一系列的初始化,其中就有网卡芯片的初始化。这个初始化就是关键,在这里的初始化中只要将网卡芯片正确的初始化了,则网卡芯片就能工作(网卡驱动dm9000x.c和dm9000x.h依赖于这里的初始化而工作)。
网卡初始化代码的层次结构如下:
start_armboot
init_sequence
board_init
dm9000_pre_init 这个函数就是移植的关键
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);
SROM_BW_REG &= ~(0xf << 4);
SROM_BW_REG |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
#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));
SROM_BC1_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));
tmp = MP01CON_REG;
//tmp &=~(0xf<<20);
tmp &=~(0xf<<4);
//tmp |=(2<<20);
tmp |=(2<<4);
MP01CON_REG = tmp;
}
dm9000_pre_init函数主要功能就是初始化DM9000网卡。这个初始化过程和九鼎X210开发板上DM9000网卡芯片的硬件连接方式有关。必须要结合开发板原理图来分析,然后决定这个函数怎么编写。
#define DM9000_16BIT_DATA
这个宏用来表示DM9000工作在16位总线模式下。九鼎开发板上DM9000确实工作在16位模式下。从三星版本的代码中可以看出,它操作的是bit20-bit23,对照数据手册中寄存器定义,可以看出三星的开发板DM9000是接在Bank5上的。从原理图知道九鼎X210接在bank1上的,因此需要操作的是bit4-bit7。
总结:三个寄存器的修改。主要是三星的开发板DM9000接在bank5,而DM9000接在了bank1上,因此要做一些修改。
下面修改配置头文件smdkv210single.h:
#ifdef CONFIG_DRIVER_DM9000
//#define CONFIG_DM9000_BASE (0xA8000000)
#define CONFIG_DM9000_BASE (0x88000300)
#define DM9000_IO (CONFIG_DM9000_BASE)
#if defined(DM9000_16BIT_DATA)
//#define DM9000_DATA (CONFIG_DM9000_BASE+2)
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#else
#define DM9000_DATA (CONFIG_DM9000_BASE+1)
#endif
#endif
CONFIG_DM9000_BASE是DM9000网卡通过SROM bank映射到SoC中地址空间中的地址。这个地址的值取决于硬件接到了哪个bank,这个bank的基地址是SoC自己定义好的。这里接到了bank1上,bank1的基地址是0x88000000。
DM9000_IO表示访问芯片IO的基地址,直接就是CONFIG_DM9000_BASE;DM9000_DATA表示我们访问数据时的基地址,因为DM9000芯片的CMD引脚接到了ADDR2,因此这里要+4(0b100,对应ADDR2;0b001,对应ADDR0;0b010,对应ADDR1)。
这里将CONFIG_DM9000_BASE改成0x88000300了。这个0x300从哪里来的?跟DM9000网卡芯片型号有关,这个0x300是DM9000网卡本身的问题,他本身的内部寄存器就有一个0x300的一个偏移量。
问题10:设置bootargs启动内核
在uboot命令行输入以下2条命令来设置bootargs分区的参数来启动内核:
set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3
set bootcmd 'movi read kernel 30008000; movi read rootfs 30B00000 300000; bootm 30008000 30B00000'
问题11:看不到启动内核的信息
做基本检查:首先是机器码对不对。
之前做实验时将串口改为了串口0,而内核zImage-qt的串口输出在串口2。如果uboot使用了串口0而内核使用了串口2,在内核启动时看不到内核的启动信息。
问题12:启动内核显示不识别的SD版本号
这个问题和上一篇文章中提及的问题5是一样的,只要把卡的版本号数字改成比开发板内置的inand版本号高就可以了。具体参考问题5。