新闻  |   论坛  |   博客  |   在线研讨会
DM9000单片机驱动代码
zxwroot | 2010-09-12 10:16:07    阅读:8579   发布文章

/*************************dm9000.c writer zxw 2010.3.26******************************/


#include"dm9000.h"
#include "def.h"
#include "ARP.h"

/************************************************************************************/
/******************************函数宏定义********************************************/


#define XIO_In16(InputPtr) (*(volatile unsigned int*)(InputPtr))
#define XIO_In8(InputPtr) (*(volatile unsigned char*)(InputPtr))
#define XIO_In32(InputPtr) (*(volatile unsigned long*)(InputPtr))
#define XIO_Out16(OutputPtr,Value) ((*(volatile unsigned int *)(OutputPtr))=(Value))


#define DM_ADD    (*(volatile U16*)0x20000300)
#define DM_CMD    (*(volatile U16*)0x20000304)
/************************************************************************************/
/******************************函数申明**********************************************/


unsigned int ior(unsigned long BaseAddress,unsigned int reg);
unsigned int Dm9000_Read(unsigned long BaseAddress,int type);
void Dm9000_Write(unsigned long BaseAddress,int type,unsigned int Value);
void iow(unsigned long BaseAddress,unsigned int reg,unsigned int data);
void delay(unsigned int t);
void Dm9000_reset(void);
void clear_interrupts(void);
void phy_write(unsigned long BaseAddress,unsigned int reg,unsigned int value);
void Dm9000_init(unsigned long BaseAddress);
void TransmitPacket(unsigned char *data_ptr,unsigned short tx_len);
unsigned char ReceivePacket(unsigned char *data_ptr);

/**********************************定义接受数组和发送数组****************************/

//unsigned char data_ptrR[MAX_PACKET_SIZE];
//unsigned char data_ptrT[MAX_PACKET_SIZE];

unsigned char ether_addr0[6]={8,90,90,90,90,90};
//unsigned char ether_addr1[6]={8,90,90,90,90,90};


/***************************函数实体********************************************************/
void dm9000_reg_write(U8 reg, U8 data)

{

    delay(1000);//之前定义的微妙级延时函数,这里延时20us
   
   
    DM_ADD = reg;//将寄存器地址写到INDEX端口

    delay(1000);
   
  
    DM_CMD = data;//将数据写到DATA端口,即写进寄存器
   
}

/**********************************************/
U8 dm9000_reg_read(U8 reg)

{

    delay(1000);
   
  
    DM_ADD = reg;

    delay(1000);
   
    return DM_CMD;//将数据从寄存器中读出

}

 


unsigned int ior(unsigned long BaseAddress,unsigned int reg)
 {
   delay(100);
   Dm9000_Write(BaseAddress,IO_addr,reg);
   delay(100);
   return Dm9000_Read(BaseAddress,IO_data);
  }
unsigned int Dm9000_Read(unsigned long BaseAddress,int type)

 {
  return XIO_In16(BaseAddress+type);
  }
void iow(unsigned long BaseAddress,unsigned int reg,unsigned int data)
 {
  delay(100);
  Dm9000_Write(BaseAddress,IO_addr,reg);
  delay(100);
  Dm9000_Write(BaseAddress,IO_data,data);
  }

void Dm9000_Write(unsigned long BaseAddress,int type,unsigned int value)
  {
   XIO_Out16(BaseAddress+type,value);
   }


void Dm9000_reset(void)
   {
    iow(BaseAddress1,DM9000_NCR,0x03);
    delay(100);
    iow(BaseAddress1,DM9000_NCR,0x00);
    iow(BaseAddress1,DM9000_NCR,0x03);
    delay(100);
    iow(BaseAddress1,DM9000_NCR,0x00);
    }
void delay(unsigned int t)
    {
     while(t--);
     }
 
void clear_interrupts(void)
    {
     iow(BaseAddress1,DM9000_IMR,0x80);
     }

void phy_write(unsigned long BaseAddress,unsigned int reg,unsigned int value)
    {
     /*set phy register address into EPAR REG.0CH*/
     iow(BaseAddress,0x0c,reg|0x40);
    /*phy register address setting,and Dm9000_phy 0ffset=0x40*/
    /*fill phy write data into EPDR REG.0xEH&REG.0DH*/
    /*phy data hign_byte*/
     iow(BaseAddress,0x0E,((value>>8)&0xff));
    /*phy data low_byte*/
     iow(BaseAddress,0x0D,value&0xff);
     /*issue phy+write commmand=0x0a into EPCR REG.0BH*/
     /*clear phy commmand first*/
     iow(BaseAddress,0x0B,0x08);
    /*issue phy+write command*/
    Dm9000_Write(BaseAddress,IO_data,0x0A);
    delay(25);
    /*clear phy command again*/
    Dm9000_Write(BaseAddress,IO_data,0x08);
    /*wait 1~30us(>20us)for phy+write completion*/
    delay(25);
    }
 /***********************DM9000初始化*********************************/
void Dm9000_init(unsigned long BaseAddress)
/*initialize Dm9000 LAN chip*/
   {
    unsigned int i;
  
  
    /*set the internal phy power_on(GPIOs normal setting)*/
    //iow(BaseAddress,0x1E,0x01);
    iow(BaseAddress,DM9000_GPCR,0x01);
    delay(100);
    /*GPCR REG.1E=1 selected GPIO0"output" port for internal phy*/
   // iow(BaseAddress,0x1F,0x00);
    iow(BaseAddress,DM9000_GPR,0x00);
    delay(100);
    /*GPR REG.1F GPIO0 Bit[0]=0 to active interal phy*/
    /*wait >2ms for phy powner_up ready*/
    /*software-reset */
    Dm9000_reset();
    delay(100);
    /*set GPIO0=1 then GPIO=0 to turn off and on the internal phy*/
    /*GPR Bit[0]=1 turn-off phy*/
//    iow(BaseAddress,0x1f,0x01);
    /*GPR Bit[0]=0 to active phy*/
//    iow(BaseAddress,0x1f,0x00);
    /*wait >4ms for phy powner-up*/
//    delay(10000);
    /*set phy operation mode*/
    /*reset phy:registers back to the default states */
//    phy_write(BaseAddress,0,phy_reset);
    /*wait>30us for phy software-reset ok*/
//    delay(350);
    /*turn off phy reduce -powner-down mode only*/
//    phy_write(BaseAddress,16,0x404);
//    phy_write(BaseAddress,4,phy_txab);
    /*set phy TX ability:ALL+Flow_control*/
//    phy_write(BaseAddress,0,0x1200);
    /*phy auto-NEGO re-start enable(RESTART_AUTO_NEGOTIATION+AUTO_NEGOTIATION_ENABLE)to auto sense and recovery phy registers*/
    /*wait>2ms for phy auto-sense linking to partner*/
      iow(BaseAddress,DM9000_NSR,0x2C);
      delay(100);
      iow(BaseAddress,DM9000_ISR,0x3f);
      delay(100);
      iow(BaseAddress,DM9000_RCR,0x38);
      delay(100);
      iow(BaseAddress,DM9000_TCR,0x00);
      delay(100);
      iow(BaseAddress,DM9000_BPTR,0x3f);
      delay(100);
      iow(BaseAddress,DM9000_FCTR,0x3a);
      delay(100);
      iow(BaseAddress,DM9000_FCR,0xff);
      delay(100);
      iow(BaseAddress,DM9000_SMCR,0x00);
      delay(100);
      for(i=0;i<6;i++)
         {
          iow(ETH_Port_0,0x16+i,ether_addr0[i]);
          delay(100);
         }
      iow(BaseAddress,DM9000_NSR,0x2C);
      delay(100);
      iow(BaseAddress,DM9000_ISR,0x3f);
      delay(100);
      iow(BaseAddress,DM9000_IMR,0x81);
      delay(100);
    /*store MAC address into NIC*/
/*    if(Num==0)
    {
     for(i=0;i<6;i++)
     iow(ETH_Port_0,16+i,ether_addr0[i]);
     }
    else if(Num==1)
     {
      for(i=0;i<6;i++)
      iow(ETH_Port_1,16+i,ether_addr1[i]);
      }
     /*clear any pending interrupt*/
/*   clear_interrupts();
     iow(BaseAddress,DM9000_NSR,0x2C);
     /*clear the TX status:TX1END,TX2END,WAKEUP 3bits,by RW/C1*/
     /*program operating registers*/
/*     iow(BaseAddress,DM9000_NCR,NCR_set);
     /*NCR REG.00 enable the chip functions(and disable this MAC loopback mode back to normal)*/
/*     iow(BaseAddress,0x08,BPTR_set);
     /*BPTR REG.08(if necessary)RX Back Pressure Threshold in Half duplex moe only:High Water 3KB,600us*/
/*     iow(BaseAddress,0x09,FCTR_set);
     /*FCTR REG.09(if necessary)Flow Control Threshold setting High/Low Water Overflow 5KB/10KB*/
/*     iow(BaseAddress,0x0A,RTFCR_set);
     /*RTFCR REG.0AH (if necessary)RX/TX Flow Control Register enable TXPEN,BKPM(TX_Half),FLCE(RX)*/
/*     iow(BaseAddress,0x0f,0x00);/*clear the all Event*/
     //iow(BaseAddress,0x2D,0x80);/*Switch LED to mode 1*/
    

     /*set other registers depending on applications*/
     //iow(BaseAddress,ETXCSR,ETXCSR_set);

     /*enable interrupts to active DM9000 on*/
/*     iow(BaseAddress,DM9000_IMR,INTR_set);
     /*enable RX(Broadcast/ALL_MULTICAST)*/
 /*    iow(BaseAddress,DM9000_RCR,0x39);*/

    }
 /********************************************/
  void DM9000_init1(void)
       {
        U8 i;
        dm9000_reg_write(DM9000_NCR, dm9000_reg_read(DM9000_NCR)&(~(1<<7)));
        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。

       //  delay(50000);//延时2ms以上等待PHY上电。
       //  delay(50000);
       //  delay(50000);
       while(!(dm9000_reg_read(DM9000_NSR)&0x40));//延时2ms以上
       
       dm9000_reg_write(DM9000_NCR, 0x03);//软件复位

     
       do {
    
      delay(1000);//延时20us以上等待软件复位完成
  
        } while (dm9000_reg_read(DM9000_NCR) & 1);

       dm9000_reg_write(DM9000_NCR, 0x00);//复位完成,设置正常工作模式。
 

       dm9000_reg_write(DM9000_NCR, 0x03);//第二次软件复位,为了确保软件复位完全成功。此步骤是必要的。

        do {
    
      delay(1000);//延时20us以上等待软件复位完成
  
        } while (dm9000_reg_read(DM9000_NCR) & 1);


       dm9000_reg_write(DM9000_NCR, 0x00);

      /*以上完成了DM9000的复位操作*/

       dm9000_reg_write(DM9000_NSR, 0x2c);//清除各种状态标志位

       dm9000_reg_write(DM9000_ISR, 0x3f);//清除所有中断标志位

     /*以上清除标志位*/

       dm9000_reg_write(DM9000_RCR, 0x6f);//接收控制
   
       dm9000_reg_write(DM9000_TCR, 0x00);//发送控制

       dm9000_reg_write(DM9000_BPTR, 0x3f);

       dm9000_reg_write(DM9000_FCTR, 0x3a);

       dm9000_reg_write(DM9000_FCR, 0xff);

       dm9000_reg_write(DM9000_SMCR, 0x00);

   /*以上是功能控制,具体功能参考参考数据手册的介绍*/

       for(i=0; i<6; i++)
 
           dm9000_reg_write(0x16 + i, ether_addr0[i]);//mac_addr[]自己定义一下吧,6个字节的MAC地址

/*以上存储MAC地址(网卡物理地址)到芯片中去,这里没有用EEPROM,所以需要自己写进去*/

/*关于MAC地址的说明,要参考网络相关书籍或资料*/

      dm9000_reg_write(DM9000_NSR, 0x2c);

      dm9000_reg_write(DM9000_ISR, 0x3f);

/*为了保险,上面有清除了一次标志位*/

      dm9000_reg_write(DM9000_IMR, 0x83);

/*中断使能(或者说中断屏蔽),即开启我们想要的中断,关闭不想要的,这里只开启的一个接收中断*/

        
       } 

/********************发送数据包*********************/
void TransmitPacket(unsigned char *data_ptr,unsigned short tx_len)
   {
    unsigned int i,len;
    /*mask NIC interrupts IMR:PAR only*/
    delay(1000);
   dm9000_reg_write(DM9000_IMR,PAR_set);
 //  while(dm9000_reg_read(DM9000_IMR)&0x03);
    len=tx_len;
    /*issue TX packet'length into TXPLH REG.FDH&TXPLL REG.FCH*/
    /*TXPLH High_byte length*/
    delay(1000);
    dm9000_reg_write(DM9000_TXPLH,(len>>8)&0x0ff);
    /*TXPLL low_byte length*/
    delay(1000);
    dm9000_reg_write(DM9000_TXPLL,len&0x0FF);
    /*write transmit data to chip SRAM*/
    /*set MWCMD REG.F8H TX I/O port ready*/
    delay(1000);
    DM_ADD=DM9000_MWCMD;
    delay(1000);
    for(i=0;i<tx_len;i+=2)
     {
     //
     Uart_SendByte(data_ptr[i]);
      //delay(20000);
      //delay(20000);
     Uart_SendByte(data_ptr[i+1]);
     
      DM_CMD=(data_ptr[i+1]<<8)|data_ptr[i];
    //  DM_CMD=data_ptr[i];
       delay(50000);
       delay(50000);
       delay(50000);
     
    
     
      }
     /*issue TX polling commmand activated*/
     /*TXCR Bit[0] TXREQ auto clear after TX completed*/
     dm9000_reg_write(DM9000_TCR,0x01);
     /*wait TX transmit done*/
     while(!(dm9000_reg_read(DM9000_NSR)&0x0C));
    
     /*clear the NSR Register*/
     dm9000_reg_write(DM9000_NSR,0x2c);
     /*ren-enable NIC interrupts*/
     dm9000_reg_write(DM9000_RCR,0x39);
   //  dm9000_reg_write(DM9000_IMR,INTR_set);
     dm9000_reg_write(DM9000_IMR,0x81);
    }


/******************数据包接收函数****************************/
  unsigned char ReceivePacket(unsigned char *data_ptr)
     { 
        unsigned int rx_len;
        unsigned char rx_READY;
        unsigned int Tmp,RxStatus,i;
        RxStatus=rx_len=0;
       //  dm9000_reg_write(DM9000_RCR, 0x38);//接收控制
   //      dm9000_reg_write(DM9000_IMR, 0x80);
        /* mask NIC interrupts IMR:PAR only*/
       // iow(BaseAddress,DM9000_IMR,PAR_set);
   /*     if(dm9000_reg_read(DM9000_ISR)&0x01)
           {
            dm9000_reg_write(DM9000_ISR,0x01) ;
           }*/
 
        /* dummy read a byte from MRCMDX REG.F0H*/
        rx_READY=dm9000_reg_read(DM9000_MRCMDX);
         // Uart_SendByte(rx_READY);
        /* got most updated byte:rx_READY*/
       // rx_READY=Dm9000_Read(BaseAddress,IO_data)&0x03;
       /*check if(rx_READY==0x01):received packet ready?*/
    if((rx_READY&0x0ff)!=DM9000_PKT_READY)
     {
       rx_READY=dm9000_reg_read(DM9000_MRCMDX);
       if((rx_READY&0x01)!=DM9000_PKT_READY)
        {
           if((rx_READY&0x01)!=0x00)
              {
                   dm9000_reg_write(DM9000_IMR, 0x80);//屏幕网卡中断
                   DM9000_init1();//重新初始化
                   dm9000_reg_write(DM9000_IMR, 0x81);//打开网卡中断
              }
           return 0;  
         }
      }    
           /*got RX_Status&RX_Length from RX SRAM*/
           
            RxStatus=dm9000_reg_read(DM9000_MRCMD);
            delay(1000);
            rx_len=DM_CMD;
        
            /*Check this packet_status GOOD or BAD? */
           if(!(RxStatus&0xBF00)&&(rx_len<MAX_PACKET_SIZE))
               {
                /*read 1 received packet from RX SRAM into RX buffer*/
                 for(i=0;i<rx_len;i+=2)
                    {
                     delay(1000);
                     Tmp=DM_CMD;
                     data_ptr[i]=Tmp&0xFF;
                     data_ptr[i+1]=(Tmp>>8)&0xFF;
                     }
                }/*end if(GOODPACKET)*/
        
            else   {return 0;}
           
       if(rx_len>1000) return 0;
//       dm9000_reg_write(DM9000_IMR,0x83);
      
      /* if((ARPBUFR->ethhdr.type != HON(0x0806))\
       &&(ARPBUFR->ethhdr.type != HON(0x0800))) { return 0;} 
          return (ARPBUFR->ethhdr.type); */ 
          return 1;   
     }        
              
              
               
              
       

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客