最近在看DM9000网卡驱动,一直不太明白,这几天问师兄,查资料总算明白了一点,在这里整理出来,也当加深理解。我刚刚学习ARM,很多东西不懂,理解错误或者不当之处还请指出,大家共同进步。
S3C2440是32位微处理器,有32根地址线,支持4GB存储空间。其中0-40000000的1G空间被分为8块128M空间,分别由NGCS0-NGCS7片选。DM9000的AEN地址使能引脚与S3C2440的NGCS4相连(对应匹配),对应的初始地址为0x2000000,地址范围为0x20000000-0x28000000。
1、 DM9000地址线
DM9000地址线SA4-SA9用于S3C2440选择DM9000网卡。因为DM9000的AEN地址使能引脚已经和S342440的NGCS4引脚相连,完成了选通,其余位可不连直接置位即可:SA9、SA8置为高电平,SA7置为低电平,SA6-SA4和TXD2-TXD0匹配(如果取DM9000 IO默认基地址,SA6-SA4可置为低电平)。
2、 DM9000数据线
DM9000数据线SD0-SD15与S3C2440数据线DATA0-DATA15相连。
3、 DM9000数据端口和命令端口的确定
由开始讨论知,对于DM9000网卡寄存器的操作在0x20000000-0x28000000的区间内进行,由于网卡IO默认基地址为300H,所以操作网卡对应内存的起始地址为0x20000300,又有DM9000网卡CMD端口与S3C2440的地址总线ADDR2相连,并且DM9000的CMD命令管脚有这样的特性:当为高电平时,从数据线传输的是数据,当为低电平时传输的是命令。
4、 具体程序
#define DM_ADD (*((volatile unsigned short*) 0x20000300))
#define DM_CMD (*((volatile unsigned short*) 0x20000304))
在定义端口,分别把0x20000300和0x20000304宏定义为DM_ADD和DM_CMD
寄存器读写操作函数
static void dm9000_reg_write(INT16U reg, INT16U data)
{
udelay(20);
DM_ADD=reg;
udelay(20);
DM_CMD=data;
}
static INT8U dm9000_reg_read(INT16U reg)
{
udelay(20);
DM_ADD=reg;
udelay(20);
return DM_CMD;
}
程序中volatile类型修饰符,在处理器对外部寄存器读写时几乎是必用的,作用是确保变量每次被调用的时候都会从内存中重新读取而不是读取内部缓存cache(处理器把常用的数据进行备份保存在此处,避免每次调用该数据时都要操作内存)里面的数据,尽管这样浪费的时间,可是提高了系统的准确性。
通过确定了地址线和数据线的连线,加上在内存里的地址映射,可以通过对内存的操作实现对寄存器的读取。具体过程是这样的:
当对以0x20000300(DM_ADD)为起始地址的内存空间进行操作时,对应的ADDR2管脚为低电平,CMD命令管脚为低电平,数据线传输的是地址,同理,当对0X20000304(DM_CMD)为起始地址的内存空间进行操作时,对应管脚为高电平,数据线传输的是数据。传输到外部芯片的地址选取寄存器,传输到外部芯片的数据写相应寄存器,这个过程由CMD控制,当CMD为低电平时选取寄存器(此时可以直接读取寄存器的内容),CMD为高电平时,写入寄存器(之前必须先选取寄存器)。在内存里的情况,这样理解。