整理dm9000ae 芯片驱动程序 ---基…

来源:互联网 发布:美达施膳食纤维粉 知乎 编辑:程序博客网 时间:2024/06/09 03:12

驱动为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");
}

0 0
原创粉丝点击