DM9000CEP在S3C2440上的裸机驱动
此次的驱动主要还是在许多前辈的经验的写出来的,其中几遍博客文章对我帮助很大,如:
http://blog.sina.com.cn/s/blog_6c73c98d0100ta2h.html
http://blog.csdn.net/b02330224/article/details/7895724
http://blog.csdn.net/zhaocj/article/details/5672588
可以说这篇文章原创性很少,主要是总结一下自己对DM9000的学习,以方便以后回顾吧。
首先DM9000CEP与S3C2440管脚连接:
. .
通过(32)CMD与ADDR2管脚相连,其功能是当为1时,为数据端口,当为0时为地址端口,(37)CS与NGCS4相连,选择DM9000的端口基址为0x20000000,偏移300个单位。
则ADDR2为1时,0100=4,ADDR2为0时 0000=0;故设置地址数据端口为:
#define DM_ADDR_PORT (*((volatile unsigned short *)0x20000300)) //地址口 3为0也行
#define DM_DATA_PORT (*((volatile unsigned short *)0x20000304)) //数据口 3为0也行
通过以上则可以写出DM9000寄存器读写操作的基本函数:
void __inline dm_reg_write(unsigned charreg, unsigned char data)
{
DM_ADDR_PORT = reg; //将寄存器地址写到地址端口
delay(20);
DM_DATA_PORT = data; //将数据写到数据端口
delay(20);
}
//读DM9000寄存器
unsigned char __inline dm_reg_read(unsigned char reg)
{
DM_ADDR_PORT = reg;
delay(20);
return DM_DATA_PORT; //将数据从数据端口读出
}
以下则对DM9000的内部寄存器进行初始化:
void dm_init(void)
{
//int i;
unsignedchar temp;
Test_DM9000AE();
dm_reg_write(DM9000_GPCR,1); //设置GPIO0为输出
delay(50);
dm_reg_write(DM9000_GPR,0); //激活内部PHY
delay(50);/
dm_reg_write(DM9000_NCR,3); //1 //软件复位DM9000
delay(300); //延时至少20μs
dm_reg_write(DM9000_NCR,0); //清除复位位
dm_reg_write(DM9000_NCR,3); //1 //为了确保复位正确,再次复位
delay(300);
dm_reg_write(DM9000_NCR,0);
delay(300);
dm_reg_write(DM9000_NSR,0x2c); //清TX状态
delay(300);
dm_reg_write(DM9000_ISR,0x3f); //0xf //清中断状态
// Uart_Printf("DM9000_ISR=%x\n",dm_reg_read(DM9000_ISR));
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);///dm9000_reg_write(DM9000_FCTR,0x00);//接收FIFO门限3K,8K
dm_reg_write(DM9000_FCR,0xff);
dm_reg_write(DM9000_SMCR,0x00);
delay(300);
dm_reg_write(DM9000_PAR,0x00); //设置MAC地址:00-01-02-03-04-05
dm_reg_write(DM9000_PAR+1,0x01);
dm_reg_write(DM9000_PAR+2,0x02);
dm_reg_write(DM9000_PAR+3,0x03);
dm_reg_write(DM9000_PAR+4,0x04);
dm_reg_write(DM9000_PAR+5,0x05);
dm_reg_write(DM9000_NSR,0x2c); //再次清TX状态
dm_reg_write(DM9000_ISR,0x3f); //0xf //再次清中断状态
delay(300);
dm_reg_write(DM9000_IMR,0x81); //打开接受数据中断
Uart_Printf("DM9000_PAR+0=%x\n",dm_reg_read(DM9000_PAR+0));
Uart_Printf("DM9000_PAR+1=%x\n",dm_reg_read(DM9000_PAR+1));
Uart_Printf("DM9000_PAR+2=%x\n",dm_reg_read(DM9000_PAR+2));
Uart_Printf("DM9000_PAR+3=%x\n",dm_reg_read(DM9000_PAR+3));
Uart_Printf("DM9000_PAR+4=%x\n",dm_reg_read(DM9000_PAR+4));
Uart_Printf("DM9000_PAR+5=%x\n",dm_reg_read(DM9000_PAR+5));
}
以上要注意的是初始化需要几秒钟,如NCR寄存器要在写操作之后几秒才能有你想看到的值显示出来。在初始化完成之后,如果你的网线有插到开发板上的网络接口进行对联,应该可以看到有绿光之类的闪烁,然后可以通过DM9000进行收发数据,其中其发数据的函数如下:
void dm_tran_packet(unsigned char *datas,int length)
{
int i;
unsigned char rx_ready;
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<length;i+=2)
{
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状态
delay(50);
//dm_reg_write(DM9000_IMR, 0x81); //打开DM9000接收数据中断
}
在上面需要注意的是MWCMD,该寄存器这样就指定了SRAM