先看一下DM9000的框图
DM9000主要由两大部分组成PHY和MAC。简单的说PHY就是实现以太网的物理层协议包括各种电气特性的设置,MAC主要完成以太网逻辑功能的各种设置。图中看到有EEPROM,我的板子上没有接,这个EEPROM一般是用来存放MAC地址和一些默认寄存器设置的。PHY模块与以太网接口相连,MAC模块与处理器接口相连
具体说说dm9000a的处理器接口,这是编程最关心的。dm9000系列有8/16/32位接口,而这里提到的dm9000a只提供8/16位接口。接口的选择由引脚EECS控制,下图是我板子上dm9000a与s3c2440链接的电路图,
可以看到EECS已经固定拉低,也就是固定了16bit位宽的使用方式。对应16bit位宽的数据总线。简单的说,dm9000内部寄存器的设置是通过“命令”方式实现的,而命令和数据公用一条数据总线,需要通过cmd引脚来区分当前传输的是命令还是数据,通常的接法就是将cmd接到地址总线的低2位即图中的ADDR2,所以数据访问和命令访问对应的dm9000的地址相差0x4。
dm9000的设置方式很简单,内部MAC寄存器都有独立的地址,设置相应的寄存器只需要先将寄存器的地址通过数据总线写入,接下来将数据放到总线上写数据,读的过程类似。通过前面cmd引脚的作用分析,写命令时要保持cmd引脚为低,写数据时要保持cmd引脚为高,这实际就是对应了两个操作地址,具体结合程序,
先定义dm9000的基地址
#define DM900_BASE_ADDR 0x20000000
//CMD引脚为高表示写入数据,为低表示写入的是地址.对应下面的两个访问地址
#define rDM9000ADD (*(volatile u16_t *)(DM900_BASE_ADDR)) //写地址寄存器
#define rDM9000CMD (*(volatile u16_t *)(DM900_BASE_ADDR + 0x4)) //写数据寄存器
接下来定义dm9000内部一些列寄存器的地址
//DM9000 内部寄存器地址定义
#define DM9000_NCR 0x00
#define DM9000_NSR 0x01
#define DM9000_TCR 0x02
#define DM9000_TSR1 0x03
#define DM9000_TSR2 0x04
#define DM9000_RCR 0x05
#define DM9000_RSR 0x06
#define DM9000_ROCR 0x07
#define DM9000_BPTR 0x08
#define DM9000_FCTR 0x09
#define DM9000_RTFCR 0x0A
#define DM9000_EPCR 0x0B
#define DM9000_EPAR 0x0C
#define DM9000_EPDRL 0x0D
#define DM9000_EPDRH 0x0E
#define DM9000_WCR 0x0F
#define DM9000_PAR 0x10 //物理地址寄存器
#define DM9000_MAR 0x16
//Multicast Address Register
#define DM9000_MAR1 0x16
#define DM9000_MAR2 0x17
#define DM9000_MAR3 0x18
#define DM9000_MAR4 0x19
#define DM9000_MAR5 0x1a
#define DM9000_MAR6 0x1b
#define DM9000_MAR7 0x1c
#define DM9000_MAR8 0x1d
#define DM9000_GPCR 0x1e
#define DM9000_GPR 0x1f
#define DM9000_TRPAL 0x22
#define DM9000_TRPAH 0x23
#define DM9000_RWPAL 0x24
#define DM9000_RWPAH 0x25
#define DM9000_VIDL 0x28
#define DM9000_VIDH 0x29
#define DM9000_PIDL 0x2A
#define DM9000_PIDH 0x2B
#define DM9000_CHIPR 0x2C
#define DM9000_OTCR 0x2e
#define DM9000_SMCR 0x2F
#define DM9000_MRCMDX 0xF0
#define DM9000_MRCMDX1 0xF1
#define DM9000_MRCMD 0xF2
#define DM9000_MRRL