s3c2440的网卡接口扩展(一)

2014-11-24 10:09:33 · 作者: · 浏览: 3

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



DM9000可以直接与ISA总线相连,也可以与大多数CPU相连。在这里,我们当然是要让DM9000s3c2440相连接了。DM9000对外来说只有两个端口——地址口和数据口,地址口用于输入内部寄存器的地址,而数据口则完成对某一寄存器的读写。DM9000CMD引脚用来区分这两个端口,当CMD引脚为0时,DM9000的数据线上传输的是寄存器地址,当CMD引脚为1时,传输的是读写数据。我们把DM9000A8A9接为高电平,把A4~A7接为低电平,并且把DM9000AEN接到s3c2440nGCS4引脚上,则DM9000的端口基址为0x20000300,如果再把DM9000CMD引脚接到s3c2440ADDR2引脚上,则我们就可以定义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寄存器MWCMDMRCMD赋予数据端口,这样就指定了SRAM中的某个地址,并且在传输完一个数据后,指针会指向SRAM中的下一个地址,从而完成了连续访问数据的目的。但当我们在发送或接受一个数据后,指向SRAM的数据指针不需要变化时,则要把MWCMDXMRCMDX赋予数据端口。下面的程序为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