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_第1张图片

 

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

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_第2张图片

 

 

需要注意的问题:

(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文件

  1. #include "basic_io.h"
  2. #include "DM9000A.C"
  3. int main()
  4.     unsigned int a;
  5.     a=DM9000_init();
  6.     DM9000_init();  // initialize DM9000 LAN chip //
  7.     if(!a)
  8.     {
  9.         printf("Success");
  10. //   TransmitPacket(unsigned char *data_ptr,unsigned int tx_len);
  11. //   ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len);
  12.     }
  13.     else
  14.         printf("Failed");
  15.     
  16. }

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

 

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

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

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

  

  main.c文件内容如下:

  1. #include "basic_io.h"
  2. #include "DM9000A.C"
  3. #include "altera_avalon_pio_regs.h"
  4.  
  5. unsigned int aaa,rx_len,i,packet_num;                     
  6. unsigned char RXT[68] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  7.                           0x01,0x60,0x6E,0x11,0x02,0x0F,
  8.                           0x08,0x00,0x11,0x22,0x33,0x44,
  9.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  10.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  11.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  12.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  13.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  14.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  15.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  16.                           0x00,0x00,0x00,0x20 };
  17.                          
  18.  
  19. void ethernet_interrupts()
  20. {
  21.     packet_num++;
  22.     aaa=ReceivePacket (RXT,&rx_len);
  23.     if(!aaa)
  24.     {
  25.       printf("\n\nReceive Packet Length = %d",rx_len);
  26.       for(i=0;i<rx_len;i++)
  27.       {
  28.         if(i%8==0)
  29.         printf("\n");
  30.         printf("0x%2X,",RXT[i]);
  31.         if(RXT[i] == 0x3f)
  32.         IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xff);
  33.       }
  34.     }
  35. }
  36.  
  37. int main(void)
  38. {
  39.   unsigned char TXT[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  40.                           0x01,0x60,0x6E,0x11,0x02,0x0F,
  41.                           0x08,0x00,0x11,0x22,0x33,0x44,
  42.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  43.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  44.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  45.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  46.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  47.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  48.                           0x55,0x66,0x77,0x88,0x99,0xAA,
  49.                           0x00,0x00,0x00,0x20 };
  50.   DM9000_init();
  51.   alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts );
  52.   packet_num=0;
  53.   while (1)
  54.   {
  55.     TransmitPacket(TXT,0x40);
  56.     msleep(500);
  57.   }
  58.  
  59.   return 0;
  60. }
  61. //
  62. //-------------------------------------------------------------------------

  编译、下载、运行。这时候将网线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文件内容如下:

  1. main.c文件
  2. #include <io.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "system.h"
  8. #include "DM9000A.C"
  9. unsigned int aaa,rx_len,i,counter;
  10. unsigned char RXT[70];
  11.  
  12. unsigned int IPsource_1,IPsource_2,IPsource_3,IPsource_4;
  13. unsigned int IPdestination_1,IPdestination_2,IPdestination_3,IPdestination_4;
  14. unsigned int IPchecksum1,IPchecksum2,IPchecksum3,IPchecksum4,IPchecksum5;
  15. unsigned int Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6;
  16. unsigned int Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4, Mac_dest5, Mac_dest6;
  17. unsigned int times, lenght_h, lenght_l;
  18. unsigned int flenght, IPlenght_h, IPlenght_l, data_lenght, IPlenght;
  19.  
  20. /*
  21. // Next step try to recieve packets. (not available now). 
  22. void ethernet_interrupts()
  23. {
  24.     aaa=ReceivePacket (RXT,&rx_len);
  25.     if(!aaa)
  26.     {
  27.       printf("\n\nReceive Packet Length = %d",rx_len);
  28.       for(i=0;i<rx_len;i++)
  29.       {
  30.         if(i%8==0)
  31.         printf("\n");
  32.         printf("0x%2X,",RXT[i]);
  33.       }
  34.     }
  35. }
  36. */
  37. int main(void)
  38. {
  39.  IPsource_1 = 0xC0;        // Assign ie: 192.168.0.44 IP for the DE2
  40.  IPsource_2 = 0xA8;
  41.  IPsource_3 = 0x00;
  42.  IPsource_4 = 0x2C;
  43.  IPdestination_1 = 0xCA;   // Insert your IP data here
  44.  IPdestination_2 = 0x76;
  45.  IPdestination_3 = 0xBB;
  46.  IPdestination_4 = 0x57;
  47.  Mac_dest1 = 0x00;         // Insert your MAC address data here
  48.  Mac_dest2 = 0x0F;
  49.  Mac_dest3 = 0xEA;
  50.  Mac_dest4 = 0xFD;
  51.  Mac_dest5 = 0x9F;
  52.  Mac_dest6 = 0x96;
  53.  Mac_source1 =  0x01;      // Assign an MAC address for DE2
  54.  Mac_source2 =  0x60;
  55.  Mac_source3 =  0x6E;
  56.  Mac_source4 =  0x11;
  57.  Mac_source5 =  0x02;
  58.  Mac_source6 =  0x0F;
  59.  
  60.  data_lenght = 1468;              // Maximun Data lenght 1468 bytes
  61.  
  62.  flenght = data_lenght + 0x2E;    //Total packet lenght
  63.  lenght_h = ((data_lenght+8) & 0xFF00)>>8; // Convert in H byte and L byte
  64.  lenght_l = ((data_lenght+8) & 0x00FF);
  65.  
  66.  IPlenght = data_lenght + 8 + 20;     // IP Lenght for IP header
  67.  IPlenght_h = (IPlenght & 0xFF00)>>8; // Convert in H byte and L byte
  68.  IPlenght_l = (IPlenght & 0x00FF);
  69.  
  70.  // Calculating the IP checksum
  71.  IPchecksum1 = 0x0000C511 + (IPsource_1<<8)+IPsource_2+(IPsource_3<<8)+IPsource_4+
  72.          (IPdestination_1<<8)+IPdestination_2+(IPdestination_3<<8)+(IPdestination_4)+
  73.          (IPlenght_h<<8) + IPlenght_l;
  74.  IPchecksum2 =  ((IPchecksum1&0x0000FFFF)+(IPchecksum1>>16));
  75.  IPchecksum3 = 0x0000FFFF - IPchecksum2;
  76.  IPchecksum4 = (IPchecksum3 & 0xFF00)>>8;
  77.  IPchecksum5 = (IPchecksum3 & 0x00FF);
  78.  
  79.  unsigned char SND[flenght]; // Payload buffer
  80.  
  81.    unsigned char TXT[] =  { Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4 ,Mac_dest5, Mac_dest6,
  82.                             Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6,
  83.                             0x08, 0x00, 0x45, 0x00, IPlenght_h, IPlenght_l,
  84.                             0x00, 0x00, 0x00, 0x00, 0x80, 0x11,
  85.                             IPchecksum4, IPchecksum5, IPsource_1, IPsource_2, IPsource_3, IPsource_4,
  86.                             IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4, 0x04, 0x00,
  87.                             0x04, 0x00, lenght_h, lenght_l, 0x00, 0x00};
  88.  
  89.     for (i = 0; i < 42; i++) // Load the TXT[] in the SND (ethernet packet).
  90.      SND[i] = TXT[i];
  91.    
  92.     for (i = 42; i < flenght-4; i++) // generating the data to send.
  93.      SND[i] = i-42;
  94.  
  95.     SND[i++] = 0x35;   // This checksum is not correct... but also the net recieve the packets correctly.
  96.     SND[i++] = 0x15;   // To do, calculate checksum.
  97.     SND[i++] = 0xF0;
  98.     SND[i++] = 0x13;
  99.                          
  100.   DM9000_init();  // Initialize the DM9000A.
  101. // Next step try to recieve packets.(not available now). 
  102. //  alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts );
  103.   
  104.   while (1)
  105.   {
  106.     TransmitPacket(SND,flenght); // Send repetitively 1468 bytes of data.
  107. //    printf("0x%2X,",ior(NSR)); // For check if 10Mbps or 100Mbps active, 0x80 = 10Mbps, 0x40 = 100Mbps.
  108. //    may happend an RX overflow buffer = 0x42
  109. //    msleep(500);
  110.   }
  111.   return 0;
  112. }
  113. //---------------------------------------------------------------

六、说明

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

 

你可能感兴趣的:(DIY_DE2之DM9000A网卡调试系列例程(二)——DM9000A测试、自收发、实现UDP)