驱动为dm9000ae芯片在基于tiny6410开发板下实现的。
主要实现1、读写dm9000芯片的id号,目的是能够正常访问dm9000芯片
2、开发板往上位机发送数据buffer。buffer的值为{1,2,3,4,5,6,7,8,9,10}用抓包软件ethereal,抓取数据。
3、上位机往开发板发送数据存到buffer,(待整理)
遇见问题:通过查看硬件原理图找到dm9000ae接到片选1上,也就是SMC Bank1上。然后查看s3c6410的datasheet在SMC的控制器中查看相应的控制寄存器,找到每个Bank的总线宽度是在SMC_BW寄存器中配置的,其中4~7位是配置Bank1的。
SROM 总线宽度 等待控制寄存器(SROM_BW)的设置,*(volatile U32*)0x70000000 |=1<<4; 这里第四位DataWidth1就是控制数据总线宽度的,设为1就是工作在16位模式。
开始没有设置导致抓到的数据包01 00 02 00 03 00 04 00 0500 06 00 07 00 08 00 09 00 0a 00
设置后正常输出 01 02 03 04 05 06 07 08 090a
#include "dm9000.h"
#include "s3c6410_addr.h"
#include "utils.h"
#define DM9KS_BASE_ADDR_ETH0 0x18000000
#define DM_ADD (*((volatile U16 *)0x18000000))
#define DM_CMD (*((volatile U16 *)0x18000004))
#define DM9KS_ID 0x90000A46
#define DM9KS_VID_L 0x28
#define DM9KS_VID_H 0x29
#define DM9KS_PID_L 0x2A
#define DM9KS_PID_H 0x2B
U8 Buffer[1000]; //定义了一个1000字节的接收发送缓冲区
U8 host_mac_addr[6]= { 0x00, 0x1e, 0xc9, 0x2c,0x07, 0xb5 };
U8 mac_addr[6] = {0x44,0x4D,0x50,0x00,0x03,0xfe};//{ 0x52, 0x54,0x4c, 0x38, 0xf7, 0x42 };
U8 ip_addr[4] = { 192, 168, 1,200 };
U8 host_ip_addr[4] = { 192, 168, 1, 100 };
U16packet_len; //接收、发送数据包的长度,以字节为单位
U8 ucSendBuffer[10] ={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A} ;
void udelay(U32 t)
{
U32 i;
for(;t>0;t--)
{
for(i=0;i<100;i++){}
}
}
voidTest_DM9000AE()
{
U32 id_val;
id_val = 0;
DM_ADD = DM9KS_VID_L;
id_val = (U8)DM_CMD;
Uart_Printf("%x\n",id_val);
DM_ADD = DM9KS_VID_H;
id_val |=(U8)DM_CMD<<8;
Uart_Printf("%x\n",id_val);
DM_ADD = DM9KS_PID_L;//udelay(2);
id_val |=(U8)DM_CMD<<16;
Uart_Printf("%x\n",id_val);
DM_ADD = DM9KS_PID_H;//udelay(2);
id_val |=(U8)DM_CMD<<24;
Uart_Printf("%x\n",id_val);
Uart_Printf("DM9000AE ChipId is %x\r\n",id_val);
if(id_val == DM9KS_ID)
{
Uart_Printf("DM9000 ID正确\r\n");
}
else
{
Uart_Printf("DM9000 ID不对\r\n");
}
}
voidIOSetInit(void)
{
// rGPNCON = (rGPNCON& ~(0x03<<14)) |(0x01<<14);//GPN7设置为EINT7
*(volatileU8 *)0x70000000 |= 1<<4;
}
//向DM9000寄存器写数据
void dm9000_reg_write(U16 reg, U16 data)
{
DM_ADD =reg; //将寄存器地址写到INDEX端口
DM_CMD =data; //将数据写到DATA端口,即写进寄存器
}
//从DM9000寄存器读数据
U8 dm9000_reg_read(U16reg)
{
DM_ADD =reg;
returnDM_CMD;//将数据从寄存器中读出
}
U16 dm9000_reg_read16(U16reg)
{
DM_ADD =reg;
returnDM_CMD;//将数据从寄存器中读出
}
void DM9000_init(void)
{
U32 i; U16 oft;
U16 addr[6];
Test_DM9000AE();
IOSetInit();
//初始化设置步骤:1
dm9000_reg_write(DM9000_GPCR,0x01); //设置 GPCR(1EH)bit[0]=1,使DM9000的GPIO3为输出。
dm9000_reg_write(DM9000_GPR, 0x00); //GPR bit[0]=0使DM9000的GPIO3输出为低以激活内部PHY。
udelay(5000); //延时2ms以上等待PHY上电。
//初始化设置步骤: 2
dm9000_reg_write(DM9000_NCR, 0x03); //软件复位
udelay(3000); //延时20us以上等待软件复位完成
dm9000_reg_write(DM9000_NCR, 0x00); //复位完成,设置正常工作模式。
dm9000_reg_write(DM9000_NCR, 0x03); //第二次软件复位,为了确保软件复位完全成功。此步骤是必要的。
udelay(3000);
dm9000_reg_write(DM9000_NCR, 0x00);
//初始化设置步骤: 3
dm9000_reg_write(DM9000_NSR, 0x2c); //清除各种状态标志位
//dm9000_reg_write(DM9000_ISR, 0xbf); //清除所有中断标志位
//初始化设置步骤: 4
dm9000_reg_write(DM9000_RCR, 0x39); //接收控制
dm9000_reg_write(DM9000_TCR, 0x00); //发送控制
dm9000_reg_write(DM9000_BPTR, 0x3f);
dm9000_reg_write(DM9000_FCTR, 0x38); //接收FIFO门限3k8k
dm9000_reg_write(DM9000_FCR, 0xff);
dm9000_reg_write(DM9000_SMCR, 0x00);
//初始化设置步骤: 5
//for(i=0; i<6; i++)
// dm9000_reg_write(DM9000_PAR +i, mac_addr[i]);// 6个字节的MAC地址
for (i = 0, oft = 0x10; i < 6;i++, oft++)
dm9000_reg_write(oft,mac_addr[i]);
for (i = 0, oft = 0x16; i < 8;i++, oft++)
dm9000_reg_write( oft,0xff);
for (i = 0, oft = 0x10; i < 6;i++, oft++)
addr[i] = dm9000_reg_read(oft);
dm9000_reg_write ( DM9000_NCR , 0x00);
//初始化设置步骤: 6
dm9000_reg_write(DM9000_NSR, 0x2c); //清除各种状态标志位
dm9000_reg_write(DM9000_ISR, 0x0f); //清除所有中断标志位 3f
//初始化设置步骤: 7
//dm9000_reg_write(DM9000_IMR,0x80); //中断使能
dm9000_reg_write(DM9000_IMR, 0xff);
}
void DM9000_sendPcket(U8 *datas, U32length)
{
U32 len,i,j;
U8 tmp;
U16 temp_i16u;
Uart_Printf("发送数据\r\n");
dm9000_reg_write(DM9000_IMR,0x80); //先禁止网卡中断,防止在发送数据时被中断干扰
len = length ; //把发送长度写入
dm9000_reg_write(DM9000_ISR,IMR_PTM);
DM_ADD = DM9000_MWCMD;
for(i=0;i
{
udelay(2);
DM_CMD = datas[i] |(datas[i+1]<<8);
}
dm9000_reg_write(DM9000_TXPLH,(len>>8) &0x0ff);
dm9000_reg_write(DM9000_TXPLL, len & 0x0ff);
dm9000_reg_write(DM9000_TCR,0x01); //发送数据到以太网上
while(1)//等待数据发送完成
{
U8 data;
data = dm9000_reg_read(DM9000_TCR);// 读发送控制器TXREQ,发送完成后自动清零。
if((data&0x01) == 0x00)break;
}
tmp =dm9000_reg_read(DM9000_NSR); //读网络状态寄存器
if((tmp& 0x01) == 0x04)
{
if((dm9000_reg_read(DM9000_TSR1)&0xfc)== 0x00)
Uart_Printf("TSR1成功\r\n");
else
Uart_Printf("TSR1失败r\n");
}
else
{
if((dm9000_reg_read(DM9000_TSR2)&0xfc)== 0x00)
Uart_Printf("TSR2成功\r\n");
else
Uart_Printf("TSR2失败r\n");
}
dm9000_reg_write(DM9000_TCR, 0x01);
dm9000_reg_write(DM9000_NSR,0x2c); //清除状态寄存器,由于发送数据没有设置中断,因此不必处理中断标志位
dm9000_reg_write(DM9000_IMR,0x81); //DM9000网卡的接收中断使能
Uart_Printf("发送数据完成\r\n");
}