微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > s3c2440的网卡接口扩展

s3c2440的网卡接口扩展

时间:11-19 来源:互联网 点击:
网络对于嵌入式系统来说必不可少。可是s3c2440没有集成以太网接口,所以要想使s3c2440具备以太网的功能,就必须扩展网卡接口。在这里,我们外接DM9000,使其可以与以太网相连接。

DM9000可以直接与ISA总线相连,也可以与大多数CPU相连。在这里,我们当然是要让DM9000与s3c2440相连接了。DM9000对外来说只有两个端口——地址口和数据口,地址口用于输入内部寄存器的地址,而数据口则完成对某一寄存器的读写。DM9000的CMD引脚用来区分这两个端口,当CMD引脚为0时,DM9000的数据线上传输的是寄存器地址,当CMD引脚为1时,传输的是读写数据。我们把DM9000的A8和A9接为高电平,把A4~A7接为低电平,并且把DM9000的AEN接到s3c2440的nGCS4引脚上,则DM9000的端口基址为0x20000300,如果再把DM9000的CMD引脚接到s3c2440的ADDR2引脚上,则我们就可以定义DM9000的这两个端口地址,它们分别为:

#define DM_ADDR_PORT(*((volatile unsigned short *) 0x20000300))//地址口
#define DM_DATA_PORT(*((volatile unsigned short *) 0x20000304))//数据口

如果要写入DM9000中的某个寄存器,则先把该寄存器的地址赋予DM_ADDR_PORT,然后再把要写入的数据赋予DM_DATA_PORT即可。读取DM9000中的某个寄存器也类似。下面的函数的作用分别是DM9000的读、写寄存器操作:

//写DM9000寄存器
void __inline dm_reg_write(unsigned char reg, unsigned char data)
{
DM_ADDR_PORT = reg;//将寄存器地址写到地址端口
DM_DATA_PORT = data;//将数据写到数据端口
}

//读DM9000寄存器
unsigned char __inline dm_reg_read(unsigned char reg)
{
DM_ADDR_PORT = reg;
return DM_DATA_PORT;//将数据从数据端口读出
}

完成了对DM9000寄存器的读写函数的编写,下面我们就可以初始化DM9000,它的过程就是适当配置DM9000寄存器的过程。DM9000的内部寄存器在这里就不做介绍,而且DM9000的应用数据手册也有如何初始化DM9000的步骤,我们这里只给出具体的程序:

void dm_init(void)
{
dm_reg_write(DM9000_NCR,1);//软件复位DM9000
delay(30);//延时至少20μs
dm_reg_write(DM9000_NCR,0);//清除复位位

dm_reg_write(DM9000_NCR,1);//为了确保复位正确,再次复位
delay(30);
dm_reg_write(DM9000_NCR,0);

dm_reg_write(DM9000_GPCR,1);//设置GPIO0为输出
dm_reg_write(DM9000_GPR,0);//激活内部PHY

dm_reg_write(DM9000_NSR,0x2c);//清TX状态
dm_reg_write(DM9000_ISR,0xf);//清中断状态

dm_reg_write(DM9000_RCR,0x39);//设置RX控制
dm_reg_write(DM9000_TCR,0);//设置TX控制
dm_reg_write(DM9000_BPTR,0x3f);
dm_reg_write(DM9000_FCTR,0x3a);
dm_reg_write(DM9000_FCR,0xff);
dm_reg_write(DM9000_SMCR,0x00);

dm_reg_write(DM9000_PAR1,0x00);//设置MAC地址:00-01-02-03-04-05
dm_reg_write(DM9000_PAR2,0x01);
dm_reg_write(DM9000_PAR3,0x02);
dm_reg_write(DM9000_PAR4,0x03);
dm_reg_write(DM9000_PAR5,0x04);
dm_reg_write(DM9000_PAR6,0x05);

dm_reg_write(DM9000_NSR,0x2c);//再次清TX状态
dm_reg_write(DM9000_ISR,0xf);//再次清中断状态

dm_reg_write(DM9000_IMR,0x81);//打开接受数据中断
}

DM9000内部有0x3FF大小的SRAM用于接受和发送数据缓存。在发送或接收数据包之前,数据是暂存在这个SRAM中的。当需要连续发送或接收数据时,我们需要分别把DM9000寄存器MWCMD或MRCMD赋予数据端口,这样就指定了SRAM中的某个地址,并且在传输完一个数据后,指针会指向SRAM中的下一个地址,从而完成了连续访问数据的目的。但当我们在发送或接受一个数据后,指向SRAM的数据指针不需要变化时,则要把MWCMDX或MRCMDX赋予数据端口。下面的程序为DM9000发送数据的函数,它的两个输入参数分别为要发送数据数组首地址和数据数组长度。在这里我们已经知道数据的宽为16位,它是由DM9000的硬件引脚设置实现的。

void dm_tran_packet(unsigned char *datas, int length)
{
int i;

dm_reg_write(DM9000_IMR, 0x80);//在发送数据过程中禁止网卡中断

dm_reg_write(DM9000_TXPLH, (length>>8) & 0x0ff);//设置发送数据长度
dm_reg_write(DM9000_TXPLL, length & 0x0ff);

DM_ADDR_PORT = DM9000_MWCMD;//发送数据缓存赋予数据端口

//发送数据
for(i=0;i{
delay(50);
DM_DATA_PORT = datas[i]|(datas[i+1]<8);//8位数据转换为16位数据输出
}

dm_reg_write(DM9000_TCR, 0x01);//把数据发送到以太网上

while((dm_reg_read(DM9000_NSR) & 0x0c) == 0)
;//等待数据发送完成

delay(50);

dm_reg_write(DM9000_NSR, 0x2c);//清除TX状态
dm_reg_write(DM9000_IMR, 0x81);//打开DM9000接收数据中断
}

发送数据比较简单,接收数据就略显复杂,因为它是有一定格式要求的。在接收到的一包数据中的首字节如果为0x01,则表示这是一个可以接收的数据包;如果为0x0,则表示没有可接收的数据包。因此在读取其他字节时,一定要先判断首字节是否为0x01。数据包的第二个字节为数据包的一些信息,它的高字节的格式与DM9000的寄存器RSR完全一致。第三个和第四个字节为数据包的长度。后面的数据就是真正要接收的数据了。下面就是DM9000接收数据的程序,其中输入参数为存放输入数据数组的首地址,输出参数为接收数据的长度。

int dm_rec_packet(unsigned char *datas)
{
unsigned char int_status;
unsigned char rx_ready;
unsigned short rx_status;
unsigned short rx_length;
unsigned short temp;
int i;

int_status = dm_reg_read(DM9000_ISR);//读取ISR
if(int_status & 0x1)//判断是否有数据要接受
{
rx_ready = dm_reg_read(DM9000_MRCMDX);//先读取一个无效的数据
rx_ready = (unsigned char)DM_DATA_PORT;//真正读取到的数据包首字节

if(rx_ready == 1)//判读首字节是否为1或0
{
DM_ADDR_PORT = DM9000_MRCMD;//连续读取数据包内容

rx_status = DM_DATA_PORT;//状态字节

rx_length = DM_DATA_PORT;//数据长度

if(!(rx_status & 0xbf00) && (rx_length < 10000))//判读数据是否符合要求
{
for(i=0; i{
delay(50);
temp = DM_DATA_PORT;
datas[i] = temp & 0x0ff;
datas[i + 1] = (temp >> 8) & 0x0ff;
}
}
}
else if(rx_ready !=0)//停止设备
{
//dm_reg_write(DM9000_IMR,0x80);//停止中断
//dm_reg_write(DM9000_ISR,0x0F);//清中断状态
//dm_reg_write(DM9000_RCR,0x0);//停止接收
//还需要复位系统,这里暂时没有处理
}
}
dm_reg_write(DM9000_ISR, 0x1);//清中断
return rx_length;
}

关于DM9000的设置我们就介绍到这里,下面就是s3c2440的设置。在这里,网卡发送数据利用的是查询方式,接收数据利用的是中断方式,因此我们把DM9000的INT引脚连接到了s3c2440的EINT7上。另外我们还是用UART0接口来控制和显示网卡数据。这两个接口的初始化为:

//

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top