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

驱动为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 Bank 1上。然后查看s3c6410的datasheet在SMC的控制器中查看相应的控制寄存器,找到每个Bank的总线宽度是在SMC_BW寄存器中配置的,其中4~7位是配置Bank 1的。
SROM 总线宽度   等待控制寄存器(SROM_BW)的设置,*(volatile U32 *)0x70000000 |= 1<<4;  这里第四位DataWidth1就是控制数据总线宽度的,设为1就是工作在16位模式。

开始没有设置导致抓到的数据包01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0a 00

设置后正常输出 01 02 03 04 05 06 07 08 09 0a
#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 };
U16 packet_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++){}
   }
}

 
void Test_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");
 }
 
}

 

 void IOSetInit(void)
{
   // rGPNCON = (rGPNCON & ~(0x03<<14)) | (0x01<<14);//GPN7设置为EINT7
    *(volatile U8 *)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(U16 reg)
{
  
    DM_ADD = reg;
    return DM_CMD;//将数据从寄存器中读出 
}

U16 dm9000_reg_read16(U16 reg)
{
  
    DM_ADD = reg;
    return DM_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门限3k 8k
    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, U32 length)
{
 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值