DIY_DE2之DM9000A网卡调试系列例程(二)——DM9000A测试、自收发、实现UDP

一、摘要

通过在 SOPC 中定制软核,在 Quartus II 中建立硬件工程,然后在 NIOS II 中建立 3 个工程,分别实现 DM9000A 测试、DM9000A 自收发和基于 DM9000A 的 UDP 协议的例子。3 个例子所使用的 DM9000A 的驱动是一样的。

二、实验平台

软件平台:Quartus II 9.0 + Nios II 9.0

硬件平台:DIY_DE2

三、实验内容 1——>DM9000A 测试

通过对 DM9000A 的初始化,测试 DM9000A 是否能够正常的初始化,能否正常的运行。该内容不需要使用网线。以下为实现步骤。

1、采用 SOPC 定制软核

DIY_DE2之DM9000A网卡调试系列例程(二)——DM9000A测试、自收发、实现UDP

定制软核的详细步骤不再赘述,以上为定制的软核。

cpu_0 需要设置的地方:

Reset Vector:cfi_flash_0、

Exception Vector:sram_16bit_512k_0

第二个标签页:Data Master 处,Data Cache 设置为 None

之后分配地址,分配中断号,生成即可。

2、硬件电路

采用原理图的形式,创建顶层文件。

(1)添加生成的软核;

(2)调用锁相环 IP 核;

(3)连线、分配管脚;

(4)编译、综合,生成配置文件。

最后原理图如下图所示。

DIY_DE2之DM9000A网卡调试系列例程(二)——DM9000A测试、自收发、实现UDP

需要注意的问题:

(1)软核程序在 SDRAM 里面运行,为了使软核的速度提升,因此 SDRAM 的频率和 cpu 的频率都设置为 100M。cpu 时钟 clk_100 和 sdram 操作时钟 clk_50 都接 PLL 的 c0,100M,无相位偏移;SDRAM 的时钟管脚 SDRAM_CLK 连接 PLL 的 c1,100M,偏移-3ns。

(2)DM9000A 的时钟管脚接 50M,直接连接晶振的输入端即可。

(3)复位管脚接高电平 VCC 即可。

(4)CFI_FLASH 的复位管脚 FLASH_RESET 接高电平 VCC 即可。

3、软件方面

(1)打开 NIOS II,新建工程,调用一个空的工程模板。

(2)添加 DM9000A 驱动:dm9000a.h 和 dm9000a.c,将上述两个文件包括 basic_io 复制到上步建立的工程文件夹下。见附录。

(3)添加一个新的.c 文件,命名为 main.c。将下列代码复制到 main.c 内。

main.c 文件

#include "basic_io.h"
#include "DM9000A.C"
int main()
{ 
    unsigned int a;
    a=DM9000_init();
    DM9000_init();  
    // initialize DM9000 LAN chip //
    if(!a)
    {
        printf("Success");
//   TransmitPacket(unsigned char *data_ptr,unsigned int tx_len);
//   ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len);
    }
    else
        printf("Failed");
     
}

(4)编译、下载、运行,之前要先将.sof 的配置文件下载到 FPGA 内。就可以看到 RJ-45 的黄色的灯和绿色的灯亮了起来。另外,在 NIOS II 的控制台 Console 中也能看到输出了 Success 。这时,说明 DM9000A 能正常运行,且初始化正常。

四、实验内容 2——>实现 DM9000A 自收发

通过 DM9000A 将数据包发送出去,之后通过中断接收。需要使用到网线 A。

不需要改动硬件系统,在上一步的基础上,直接在 NOIS II 中新建工程,添加 main.c 文件。

main.c 文件内容如下:

#include "basic_io.h"
#include "DM9000A.C"
#include "altera_avalon_pio_regs.h"
  
unsigned int aaa,rx_len,i,packet_num;                     
unsigned char RXT[68] = { 
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
                           
0x01,0x60,0x6E,0x11,0x02,0x0F,
                           
0x08,0x00,0x11,0x22,0x33,0x44,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x00,0x00,0x00,0x20 
};
                          
  
void ethernet_interrupts()
{
    packet_num++;
    aaa=ReceivePacket(RXT,&rx_len);
    if(!aaa)
    {
      printf("\n\nReceive Packet Length = %d",rx_len);
      for(i=0;i<rx_len;i++)
      {
        if(i%8==0)
        printf("\n");
        printf("0x%2X,",RXT[i]);
        if(RXT[i] == 0x3f)
         
        IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xff);
      }
    }
}
  
int main(void)
{
  unsigned char TXT[] = { 
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
                           
0x01,0x60,0x6E,0x11,0x02,0x0F,
                           
0x08,0x00,0x11,0x22,0x33,0x44,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                    
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x55,0x66,0x77,0x88,0x99,0xAA,
                           
0x00,0x00,0x00,0x20 
};
  DM9000_init();
  alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts );
  packet_num=0;
  while (1)
  {
    TransmitPacket(TXT,0x40);
    msleep(500);
  }
  
  return 0;
}
//
//-------------------------------------------------------------------------

编译、下载、运行。这时候将网线 A 插入 DIY_DE2 开发板的 RJ-45,能够看到黄色的灯闪烁,绿色的灯一直亮,另外,在 NIOS II 控制台也能看到收到的数据。

五、简单 UDP 协议的实现

DM9000A 与 PC 的简单通信,采用 UDP 协议,用 B 网线连接 DIY_DE2 与 PC。FPGA 内部产生递增数据,够一个数据包后,通过网络将数据传输给 PC,PC 也可以通过网络给 FPGA 发送数据,FPGA 则通过中断接收数据。

同样,直接在 NOIS II 中新建工程,添加 main.c 文件。

可以使用 Wireshark 软件来捕捉数据包,并测试其传输速度。经过测试:

cpu 采用 100MHz 时,

(1)cpu/e:SRAM 运行,速度 3Mbps;

SDRAM 运行,50MHz 时,速度 600Kbps;

SDRAM 运行,100MHz 时,速度 1.0Mbps;

(2)cpu/f:SRAM 运行,速度 11Mbps。

main.c 文件内容如下:

#include #include #include #include #include #include "system.h"
#include "DM9000A.C"
unsigned int aaa,rx_len,i,counter;
unsigned char RXT[70];
  
unsigned int IPsource_1,IPsource_2,IPsource_3,IPsource_4;
unsigned int IPdestination_1,IPdestination_2,IPdestination_3,IPdestination_4;
unsigned int IPchecksum1,IPchecksum2,IPchecksum3,IPchecksum4,IPchecksum5;
unsigned int Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6;
unsigned int Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4, Mac_dest5, Mac_dest6;
unsigned int times, lenght_h, lenght_l;
unsigned int flenght, IPlenght_h, IPlenght_l, data_lenght, IPlenght;
  
/*
// Next step try to recieve packets. (not available now). 
void ethernet_interrupts()
{
    aaa=ReceivePacket (RXT,&rx_len);
    if(!aaa)
    {
      printf("\n\nReceive Packet Length = %d",rx_len);
      for(i=0;i>8; // Convert in H byte and L byte
 lenght_l = ((data_lenght+8) & 0x00FF);
  
 IPlenght = data_lenght + 8 + 20;     // IP Lenght for IP header
 IPlenght_h = (IPlenght & 0xFF00)>>8; // Convert in H byte and L byte
 IPlenght_l = (IPlenght & 0x00FF);
  
 // Calculating the IP checksum
 IPchecksum1 = 0x0000C511 + (IPsource_1<<8)+IPsource_2+(IPsource_3<<8)+IPsource_4+
         (IPdestination_1<<8)+IPdestination_2+(IPdestination_3<<8)+(IPdestination_4)+
         (IPlenght_h<>16));
 IPchecksum3 = 0x0000FFFF - IPchecksum2;
 IPchecksum4 = (IPchecksum3 & 0xFF00)>>8;
 IPchecksum5 = (IPchecksum3 & 0x00FF);
  
 unsigned char SND[flenght]; // Payload buffer
  
   unsigned char TXT[] =  { Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4 ,Mac_dest5, Mac_dest6,
                            Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6,
                            0x08, 0x00, 0x45, 0x00, IPlenght_h, IPlenght_l,
                            0x00, 0x00, 0x00, 0x00, 0x80, 0x11,
                            IPchecksum4, IPchecksum5, IPsource_1, IPsource_2, IPsource_3, IPsource_4,
                            IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4, 0x04, 0x00,
                            0x04, 0x00, lenght_h, lenght_l, 0x00, 0x00};
  
    for (i = 0; i < 42; i++) // Load the TXT[] in the SND (ethernet packet).
     SND[i] = TXT[i];
    
    for (i = 42; i < flenght-4; i++) // generating the data to send.
     SND[i] = i-42;
  
    SND[i++] = 0x35;   // This checksum is not correct... but also the net recieve the packets correctly.
    SND[i++] = 0x15;   // To do, calculate checksum.
    SND[i++] = 0xF0;
    SND[i++] = 0x13;
                          
  DM9000_init();  // Initialize the DM9000A.
// Next step try to recieve packets.(not available now). 
//  alt_irq_register( DM9000A_IRQ, NULL, 
(void*)ethernet_interrupts );
   
  while (1)
  {
    TransmitPacket(SND,flenght); // Send repetitively 1468 bytes of data.
//    printf("0x%2X,",ior(NSR)); // For check if 10Mbps or 100Mbps active, 0x80 = 10Mbps, 0x40 = 100Mbps.
//    may happend an RX overflow buffer = 0x42
//    msleep(500);
  }
  return 0;
}
//---------------------------------------------------------------

六、说明

UDP 属于无连接的通信,这里不必把本机和 DE2 的 IP 设置成同一网段,即可完成通信。

扫码关注尚为网微信公众号

尚为网微信公众号
每天学习电路设计嵌入式系统的专业知识,关注一波,没准就用上了。

原创文章,作者:sunev,如若转载,请注明出处:https://www.sunev.cn/embedded/21.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2012年3月11日 15:21
下一篇 2012年3月13日 23:25

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注