一、DM9000物理结构
1、原理图
工作实质就是MAC通过MII控制PHY的过程。
2、网卡和网络模型的映射关系
MAC对应的是数据链路层,PHY对应的是物理层
3、MAC的工作原理
当网络协议栈的IP包送到网卡的时候,先要到达MAC,MAC就根据数据链路层的协议对接收到的数据进行封装,将IP包封装成以太网包,完成数据帧的构建。当然它还具备数据纠错以及传送控制等功能。
4、关于PHY
PHY是物理接口收发器。主要和实际的传输硬件打交道。他接收到来自MAC的以太网包,先加上校检码。然后按照物理层的规则进行数据编码,然后传输到物理介质,接受过程则与之相反。
5、MII即媒体独立接口。表明在MAC一定情况下,更换PHY是不会影响系统的工作的。因为他们最后都要遵循MII接口。故MII起到了MAC和PHY之间通信的桥梁作用。
二、DM9000的编程接口
1、DM9000的接口不是绝对开放的,不能像访问nand控制器那样直接按照地址去访问相关寄存器。
2、但是他提供了两个可以供CPU访问的接口,一个是index另一个是数据端口。
3、index的地址在mini2440上是0x20000300.原因是
(1)mini2440的原理图中
dm9000的片选信号AEN就是接到nLAN_CS片选。再看CPU原理图
我们可以看到nLAN_CS实质接在nGCS4上。再看datasheet
可以看到nGCS4对应的片选信号是0x20000000开头的,在0x20000000-0x28000000之间。所以index的地址开头是0x2********。即片选地址
(2)再看DM9000的datasheet
再看DM9000的TXD【2:0】的引脚接线情况
发现都是0,所以I/O base的地址是300H。即相对片选地址的位置。(相对地址,片选地址相当于基地址)。
(3)不管是index端口还是数据端口都是用SD0-SD15来传递数据。所以要区分具体某一时刻,这些数据到底是给那一个接口用。于是利用CMD引脚来区别。当CMD引脚是高电平的时候,SD上的数据是给数据接口用的,当CMD是低电平的时候,是给index接口用的。index接口是用来传递偏移量的。可以看到CMD接到CPU的ADDR2,当他为1的时候,就是为数据接口传送数据,即地址是0x20000304.当ADDR2为0的时候,SD是为index接口传送偏移量,即ADDR2为0,即地址是0x20000300.故我们找到了,片选地址,I/O base地址,以及数据接口地址。
三、DM9000初始化
1、片选信息设置
(1)数据宽度(BWSCON)
(2)时序信号填写(BANKCON4)
void cs_init()
{
/*1.数据宽度设置*/
BWSCON &= ~(3 << 16);
BWSCON |= (1 <<16);
/*2.时序信号设置*/
BANKCON4 = (0 << 13) | (0 << 11) | (7 << 8) | (1 << 6) | (0 << 4) | (0 << 2) | (0 << 0);
}
2、中断初始化
(1)从原理图找到DM9000使用的中断源
(2)配置相应的中断引脚
(3)设置中断触发方式(高电平,EXTINT0)
(4)使能中断,设置中断屏蔽寄存器(INTMSK,EINTMSK)
(5)清除中断标志(SRCPND,INTPND,EINTPND)
void int_init()
{
/*设置中断引脚工作模式*/
GPFCON = GPFCON &(~(0x3<<14));
GPFCON = GPFCON |(0x2<<14);
/*设置中断触发方式*/
EXTINT0 = EXTINT0 & (~(0x7<<28));
EXTINT0 = EXTINT0 | (0x1<<28);
/*使能中断*/
INTMSK = INTMSK &(~(1<<4));
EINTMASK = EINTMASK & (~(0x1<<7));
/*清楚之前所有的中断标志*/
EINTPEND |= (1<<7);
SRCPND = (1<<4);
INTPND = (1<<4);
}
3、复位设备
(1)实现往DM9000读写数据的函数
(2)设置I/O为输出模式
(3)通过对GPIO0写0为内部的PHY提供电源
(4)软件复位(自动清0),MAC内部回环模式
(5)对(4)中的寄存器全部写入0
(6)重复(4)(5)
void dm9000_write(u16 reg,u16 data)
{
DM_ADD = reg;
DM_DAT = data;
}
u8 dm9000_read(u16 reg)
{
DM_ADD = reg;
return DM_DAT;
}
void dm9000_reset()
{
/*1.设置I/O为输出模式*/
dm9000_write(DM9000_GPCR, GPCR_GPIO0_OUT);
/*2.通过对GPIO0写入0为内部的PHY提供电源*/
dm9000_write(DM9000_GPR, 0);
/*3.软件复位(自动清0),MAC内部回环模式*/
dm9000_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
/*4.对上一步的寄存器写入全0*/
dm9000_write(DM9000_NCR, 0);
/*5.重复(3)(4),用两次实现真正复位*/
dm9000_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
dm9000_write(DM9000_NCR, 0);
}
4、捕获网卡
(1)读取厂家ID
(2)读取product的ID
(3)将两个ID组合与之前预定义的网卡ID进行对比
u8 dm9000_probe()
{
u32 id_val;
/*1.读取厂家ID*/
id_val = dm9000_read(DM9000_VIDL);
id_val |= dm9000_read(DM9000_VIDH) << 8;
/*2.读取产品ID并将其和厂家ID组合*/
id_val |= dm9000_read(DM9000_PIDL) << 16;
id_val |= dm9000_read(DM9000_PIDH) << 24;
if (id_val == DM9000_ID) {
printf("dm9000 is found !\n\r");
return 0;
} else {
printf("dm9000 is not found !\n\r");
return -1;
}
}
5、MAC初始化
参照u-boot设置MAC