视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
DM9000网卡调试教程
2025-09-24 07:18:45 责编:小OO
文档
DIY_DE2之DM9000A网卡调试系列例程(一)——准备工作 

一、摘要

  根据最近一段时间的工作,将DIY_DE2中的网卡DM9000A所涉及到的例程做了调试,接下来几篇博文将循序渐进的阐述这些例程的实现过程,涉及到的具体原理及理论将会另开博文叙述。本篇主要阐述一下调试例程前的准备工作。

二、准备工作

1、网线

  经常接触的网线叫双绞线,双绞线有2种,直通线和交叉线,通常又把后者叫做双机互联线。前者用于连接计算机与交换机、HUB等,后者用于连接计算机与计算机,交换机与交换机等。

 

  上图即是交叉线的制作方法,有时别人给制作并不是严格按照上图的对应颜色,但只要RJ-45水晶头满足1和3对调,2和6对调即可。

  后续的几篇例程除了用到这种交叉线外,DM9000A自收发的例程还用到另外一种线,这种线也极为简单,只留网线的一边水晶头,另外一头剪掉,对照留下的那头的线序,将剪掉那头的线1和3连接,2和6连接,为了测试连线是否正常,可以将水晶头插入电脑RJ-45里面,若网口灯亮,则说明连接正常。定义该种网线为网线A,交叉线为网线B。

2、Altera不同版本软件的安装

  NIOS II中有TCP/IP模板程序,根据Altera不同版本软件,实现TCP/IP所使用的协议栈却不同;低版本(7.2版本以下)使用的是LWIP协议栈,而高版本中摒弃了LWIP协议栈,使用的是NicheStack协议栈,前者不需要授权,而后者需要授权。

  后续的几篇博文中,分别实现了LWIP协议栈和NicheStack协议栈,因此需要安装不同版本的Altera软件。Altera的软件,高版本兼容低版本。如果安装了6.0版本的,再安装了9.0版本的,则6.0版本的就不能用了。这里有个处理技巧:

(1)在安装完6.0版本之后,记录一下跟其相关的系统变量。

(2)之后安装9.0版本的软件,记录一下跟其相关的系统变量。

(3)使用9.0的时候,将系统变量的值修改成9.0的即可。

(4)使用6.0的时候,将系统变量的值修改成6.0的即可。

系统变量位置:右击我的电脑——>属性——>高级——>环境变量——>系统变量。

如下是我安装6.0版本软件后的相关的系统变量:

6.0系统变量:

变量名:SOPC_KIT_NIOS2

变量值:c:\\altera\\kits\\nios2_60

 

变量名:SOPC_BUILDER_PATH_60

变量值:c:\\altera\\kits\\nios2_60

 

变量名:QESS_ROOTDIR

变量值:C:\\altera\\quartus60

 

变量名:QUARTUS_ROOTDIR

变量值:C:\\altera\\quartus60

  另外,如果下载配置文件的时候提示没有USB-Blaster的话,重新找一下对应版本的驱动即可。一般情况下,配置驱动的情况一次就OK了!

3、硬件平台

  这里仍使用的是自己制作的板子DIY_DE2。该系列博文所探讨的难点在于DM9000A的驱动,后续3篇博文中所用到的DM9000A的驱动各不相同,不能混用!

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定制软核

 

 

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

cpu_0需要设置的地方:

Reset Vector:cfi_flash_0、

Exception Vector:sram_16bit_512k_0

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

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

2、硬件电路

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

(1)添加生成的软核;

(2)调用锁相环IP核;

(3)连线、分配管脚;

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

最后原理图如下图所示。

 

 

需要注意的问题:

(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.{ 

5.    unsigned int a;

6.    a=DM9000_init();

7.    DM9000_init();  // initialize DM9000 LAN chip //

8.    if(!a)

9.    {

10.        printf("Success");

11.//   TransmitPacket(unsigned char *data_ptr,unsigned int tx_len);

12.//   ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len);

13.    }

14.    else

15.        printf("Failed");

16.    

17.}

(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;i27.      {

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

3.#include

4.#include

5.#include

6.#include

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;i29.      {

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

. 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. 

.    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网卡调试系列例程(三)——基于LWIP协议栈的TCP/IP实现 

一、摘要

  Altera软件NIOS II低版本(7.2版本以下,本例程中使用的是6.0版本)中实现TCP/IP所用的协议栈为LWIP,常用的例程有2个,web_server和simple_socket_server,这篇文章将叙述这2个例程实现的过程。这两个例程参考了友晶科技的DE2_WEB例程。

 

二、实验平台

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

硬件平台:DIY_DE2

 

三、实验内容1——>实现web_server

1、采用SOPC定制软核

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

cpu_0需要设置的地方:

Reset Vector:cfi_flash_0、

Exception Vector:sdram_0

必须要添加timer_0,供uC/OS系统所使用

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

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

2、硬件电路

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

(1)添加生成的软核;

(2)调用锁相环IP核;

(3)连线、分配管脚;

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

最后原理图如下图所示。

需要注意的问题:

(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,新建工程,调用web_server工程模板。

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

(3)打开文件network_utilities.c,赋予静态IP。

(4)编译、下载、运行,之前要先将.sof的配置文件下载到FPGA内。在DOS下输入ping命令:ping 192.168.2.1,如下图所示,则可以正常ping通。

  如果事先将网页数据烧录到FLASH中,在PC打开浏览器,则可以在浏览器上看到FLASH中的网页内容。这个实验之前在DE2板子上做过,这里就不再重复了。

4、工程文件解读

(1)http.c、http.h:网页相关文件;

(2)Dm9000a.h、dm9000a.c:DM9000A的驱动;

(3)User.h:任务调度优先级、缺省IP设置等等;

(4)network_utilities.c:设置IP,设置MAC;

(5)Web_server:主函数所在文件。

 

四、实验内容2——>实现simple_socket_server

1、建立工程及文件解读

  在上一步的基础上,直接在NIOS II中新建工程,调用simple_socket_server工程模板。添加DM9000A的驱动,将dm9000a.h、dm9000a.c添加到建立的工程文件夹下。工程文件主要包括以下几个:

(1)alt_error_handler.h、alt_error_handler.c:错误类型句柄文件;

(2)dm9000a.h、dm9000a.c:DM9000A的驱动;

(3)network_utilities.c:设置IP,设置MAC;

(4)simple_socket_server.h、simple_socket_server.c:工程的主体程序,包括任务调度优先级、缺省IP设置、套接字、各种任务调度等等工作;

(5)led.c:LED、七段数码管显示程序;

(6)lwip_init.c:程序主函数。

2、需要修改的地方

依照web_server例程,对simple_socket_server例程进行部分修改:

(1)simple_socket_server.h文件,

添加分配DHCP优先级:#define DHCP_TMR_PRIO 8

添加语句:void die_with_error(char err_msg[]);

添加DHCP超时任务函数:void dhcp_timeout_task();

添加语句:#define DIE_WITH_ERROR_BUFFER 256

(2)lwip_init.c文件

添加DM9000A驱动:#include "dm9000.h"

添加DM9000A接口语句:ALTERA_AVALON_DM9K_INSTANCE(DM9000A, dm9k);

添加语句:OS_EVENT *attained_ip_address_sem;

在static void init_done_func(void *arg)添加以下语句:

 

//++sunev

  ALTERA_AVALON_DM9K_INIT(dm9k);

  /*

   * At this point lwIP has been initialized, but the Ethernet interface has

   * not; the lwip_devices_init() call does so, adding in MicroC-OS/II

   * threads for low-level Ethernet MAC interface and TCP protocol timer.

   */

//++sunev  

   attained_ip_address_sem = OSSemCreate(1);

  

   if (!lwip_devices_init(LWIP_RX_ETHER_TASK_PRIORITY))

   {

      alt_lwIPErrorHandler(EXPANDED_DIAGNOSIS_CODE,

"[init_done_func] Fatal: lwip_devices_init failed, perhaps ethernet interface.");

   }

//++sunev

#if LWIP_DHCP == 1

  if(!(IORD(0, 0) & (1<<17))) sys_thread_new(dhcp_timeout_task, NULL, DHCP_TMR_PRIO);

  /*

   * If DHCP is enabled, activate a thread for the 120-second long time period

   * that will set a static IP address if acquisistion via DHCP times out.

   */

//--sunev

/*   if (!sys_thread_new(NETUTILSDHCPTimeoutTask, NULL,

                       NETUTILS_DHCP_TIMEOUT_TASK_PRIORITY))

   {

      alt_lwIPErrorHandler(EXPANDED_DIAGNOSIS_CODE,

                 "[init_done_func] Fatal: Can't add NETUTILSDHCPTimeoutTask!");

   }*/

(3)将web_server中的network_utilities.c文件直接替换掉simple_socket_server中的network_utilities.c文件。

3、编译、下载、运行

之前要先将.sof的配置文件下载到FPGA内。在DOS下输入ping命令:ping 192.168.2.1,如下图所示,则可以正常ping通。

再输入telnet命令:telnet 192.168.2.1,则得到如下图所示:

在PC键盘输入0-7数字,则DIY_DE2上的8个LED就会相应的亮或者灭。至此,说明,telnet正常。

 

五、实验结果分析

  这个实验结果分析,对上述2个实验内容均为一致。

  解读上述程序,在network_utilities.c文件中,可以得知,设置IP的3种方法:第一种,程序设定静态IP;第二种,DHCP获得动态IP;第三种,缺省IP。其优先级及顺序如下:

  (1)当设定静态IP之后,DHCP能获得一个动态IP,但以设置的静态IP为有效IP。

  (2)当未设定静态IP之后,DHCP则不能获得一个动态IP,但过了设定的DHCP超时时间后(以上2个例程中的超时时间为120s),使用的是缺省IP,缺省IP为有效IP。

设定静态IP时,NIOS II 运行结果

未设定静态IP时,需等待2分钟(DHCP超时可在simple_socket_server.h中设定),NIOS II 运行结果

 

注:可以在network_utilities.c文件中将

#if LWIP_DHCP == 1

*use_dhcp = 1;

中的

*use_dhcp = 1;

设置为

*use_dhcp = 0;

来取消DHCP功能。

 

六、实验的几点说明

1、IP值设置:

  因为是采用局域网通信,所以要将PC和DIY_DE2的IP的前3位设置为相同,最后一位不同。

2、MAC值设置:

  直接采用程序设定即可,或者是将MAC值存储在FLASH中,上电读取即可。本例采用的是前一种方法。

3、端口设定:

  telnet的时候,需要侦听端口,当侦听的端口号和DIY_DE2中设定的相同的时候,才能正常通信。方法:telnet 192.168.2.1时,会有一个专用的端口23,将DIY_DE2中设定的端口号改为23即可(在文件simple_socket_server.h中#define SSS_PORT 23)。

4、关于这个例程在NIOS II方面:

  关于Software Components这个按钮下Lightweight TCP/IP Stack下选项为灰色的原因,其实这个不必理他。这一点也得到了友晶科技的证实。如果用LAN91c111这个网卡,上述位置的选项则可以正常使用,这说明NIOS II软件只认SOPC中原装的器件

DIY_DE2之DM9000A网卡调试系列例程(四)——基于NicheStack协议栈的TCP/IP实现 

一、摘要

  Altera软件NIOS II高版本(7.2版本以上,本例程中使用的是9.0版本)中实现TCP/IP所用的协议栈为NicheStack,常用的例程有2个,web_server和simple_socket_server,这篇文章只叙述simple_socket_server例程实现的过程。这里DM9000A的驱动和上篇博文中基于LWIP的驱动不同。

 

二、实验平台

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

硬件平台:DIY_DE2

 

三、实验内容——>实现simple_socket_server

1、采用SOPC定制软核

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

cpu_0需要设置的地方:

Reset Vector:cfi_flash_0、

Exception Vector:sram_16bit_512k_0

必须要添加sys_timer_0,供uC/OS系统所使用

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

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

2、硬件电路

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

(1)添加生成的软核;

(2)调用锁相环IP核;

(3)连线、分配管脚;

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

最后原理图如下图所示。

需要注意的问题:

(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,新建工程,调用simple_socket_server工程模板。

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

(3)打开network_utilities.c文件,将附录代码覆盖原始代码,这里采用的是使用静态IP的方法(IP的值将在后面给出说明),并且赋给MAC值。

(4)打开iniche_init.c文件,

添加头文件#include"dm9000a.h",

添加DM9000A接口语句DM9000A_INSTANCE(DM9000A_0, dm9000a_0);

在函数void SSSInitialTask(void *task_data)中,

添加DM9000A的初始化语句DM9000A_INIT(DM9000A_0, dm9000a_0);

(5)编译、下载、运行,之前要先将.sof的配置文件下载到FPGA内。在DOS下输入ping命令:ping 192.168.2.1,如下图所示,则可以正常ping通。

再输入telnet命令:telnet 192.168.2.1,则得到如下图所示:

在PC键盘输入0-7数字,则DIY_DE2上的8个LED就会相应的亮或者灭。至此,说明,telnet正常。

4、工程文件解读

(1)alt_error_handler.h、alt_error_handler.c:错误类型句柄文件;

(2)dm9000a_regs.h、dm9000a.h、dm9000a.c:DM9000A的驱动;

(3)network_utilities.h、network_utilities.c:设置IP,设置MAC;

(4)simple_socket_server.h、simple_socket_server.c:工程的主体程序,包括任务调度优先级、缺省IP设置、套接字、各种任务调度等等工作;

(5)led.c:LED、七段数码管显示程序;

(6)iniche_init.c:程序主函数。

 

四、实验结果分析

NIOS II运行结果:

稍过2分钟后,得到如下结果:

  实验现象,程序一开始运行,先赋给静态IP,这时候ping能够跑通,但telnet却不能跑通。稍过2分钟之后(这个默认时间在LWIP协议栈实现的时候可以调整,但在NicheStack协议栈中不能调整,至少在工程文件里是这样),出现上面第二幅结果图的时候,能够ping正常,telnet正常。

  分析可得,虽赋予静态IP,但是系统仍是先通过DHCP获取IP,获取超时,使用缺省IP,缺省IP的设置在simple_socket_server.h中。而真正能够ping正常,telnet正常的却是事先赋予的静态IP。

 

注:取消DHCP的方法同上一篇博文。

 

五、实验的几点说明

1、IP值设置:

  因为是采用局域网通信,所以要将PC和DIY_DE2的IP的前3位设置为相同,最后一位不同。

2、MAC值设置:

  直接采用程序设定即可,或者是将MAC值存储在FLASH中,上电读取即可。本例采用的是前一种方法。

3、端口设定:

  telnet的时候,需要侦听端口,当侦听的端口号和DIY_DE2中设定的相同的时候,才能正常通信。方法:telnet 192.168.2.1时,会有一个专用的端口23,将DIY_DE2中设定的端口号改为23即可(在文件simple_socket_server.h中#define SSS_PORT 23)。

4、关于这个例程在NIOS II方面:

  关于Software Components这个按钮下Lightweight TCP/IP Stack下选项为灰色的原因,其实这个不必理他。这一点也得到了友晶科技的证实。如果用LAN91c111这个网卡,上述位置的选项则可以正常使用,这说明NIOS II软件只认SOPC中原装的器件。

 

 

 

附录:

network_utilities.c文件

 

#include

#include

#include

#include

#include

#include "includes.h"

#include "io.h"

#include "simple_socket_server.h"

 

#include

 

#include "ipport.h"

#include "tcpport.h"

#include "network_utilities.h"

 

#define IP4_ADDR(ipaddr, a,b,c,d) ipaddr = \

    htonl((((alt_u32)(a & 0xff) << 24) | ((alt_u32)(b & 0xff) << 16) | \

          ((alt_u32)(c & 0xff) << 8) | (alt_u32)(d & 0xff)))

 

/*

* get_mac_addr

*

* Read the MAC address in a board specific way

*

*/

static unsigned char macaddr[6] = { 0x00, 0x07, 0xed, 0xff, 0x06, 0x00 };

 

int get_mac_addr(NET net, unsigned char mac_addr[6])

{

  int rv = -1;

 

  /* first 3 bytes are altera's vendor id */

  /* last 3 bytes are picked from serial number sticker */

  mac_addr[0] = macaddr[0];

  mac_addr[1] = macaddr[1];

  mac_addr[2] = macaddr[2];

  mac_addr[3] = macaddr[3];

  mac_addr[4] = macaddr[4];

  mac_addr[5] = macaddr[5];

 

  /* return the mac address in the array */

  rv = 0;

 

  return rv;

}

 

/*

 * get_ip_addr()

 *

 * This routine is called by InterNiche to obtain an IP address for the

 * specified network adapter. Like the MAC address, obtaining an IP address is

 * very system-dependant and therefore this function is exported for the

 * developer to control.

 *

 * In our system, we are either attempting DHCP auto-negotiation of IP address,

 * or we are setting our own static IP, Gateway, and Subnet Mask addresses our

 * self. This routine is where that happens.

 */

int get_ip_addr(alt_iniche_dev *p_dev,

                ip_addr* ipaddr,

                ip_addr* netmask,

                ip_addr* gw,

                int* use_dhcp)

{

 

    IP4_ADDR(*ipaddr, 192, 168, 2, 1);

    IP4_ADDR(*gw, 192, 168, 2, 1);

    IP4_ADDR(*netmask, 255, 255, 255, 0);

 

#ifdef DHCP_CLIENT

    *use_dhcp = 1;

#else /* not DHCP_CLIENT */

    *use_dhcp = 0;

 

    printf("Static IP Address is %d.%d.%d.%d\\n",

        ip4_addr1(*ipaddr),

        ip4_addr2(*ipaddr),

        ip4_addr3(*ipaddr),

        ip4_addr4(*ipaddr));

#endif /* not DHCP_CLIENT */

 

    /* Non-standard API: return 1 for success */

    return 1;

}下载本文

显示全文
专题