DM9000裸机驱动

1 总体介绍

DM9000是以太网MAC控制器。它有一个一般处理接口、一个10/100M自适应的PHY4K DWORD值的SRAM。它的目的是在低功耗和高性能进程的3.3V5V的支持宽带。

DM9000还提供了介质无关接口(MII)。该DM9000支持8位、16位和32位接口访问内部存储器,以支持不同的处理器。DM9000PHY接口完全支持10MBps3类、4类、5非屏蔽双绞线100MBps5类非屏蔽双绞线。它的自动协调功能将自动完成配置以最大限度地适合其线路带宽。它还支持IEEE 802.3x全双工流量控制。

2 准备知识

物理层的任务接受一个原始的位流,并试图将它传递到目标机器。

PHY是物理层接口收发器,它实现物理层。包括MII(与介质无关接口)子层、PCS(物理编码子层)等其它子层。

PHY在发送数据的时候,接受MAC发过来的数据(对PHY来说,没有帧的概念,对它来说一切都是原始的位流)。然后每4bit增加1bit的检错码,然后把并行数据转化为串行流数据,再按照物理层的编码规则把数据编码,再变为模拟信号把数据送出去。

隔离变压器把PHY送出来的差分信号用差模耦合的线圈耦合滤波以增强信号,并通过电磁场的转换耦合到连接网线的另一端。

MII(与介质无关接口)。与介质无关表明在不对MAC硬件重新设计或交换的情况下,任何类型的PHY设备都可以正常工作。

MAC(介质访问控制协议)主要负责控制与连接物理层的物理介质,以实现无差错传输。在发送数据的时候,MAC协议可以事先判断是否可以发送数据,如果可以发送将给数据加上一些控制信息,最终将数据以及控制信息以规定的格式发送到物理层;在接收数据的时候,MAC协议首先判断输入的信息是否有传输错误,如果没有错误,则去掉控制信息发送至LLC层。

3 DM9000原理

DM9000Davicom公司的一款以太网控制芯片,在网络中它可自动获得同设定MAC地址一致的IP包,完成IP包得收发,再用一个单片机来结合完成上层协议,就构成了一个完整的网络终端。在单片机中嵌入了一个精简TCP/IP协议栈。

3.1 DM9000结构框图

3.2 DM9000的PIN

DM9000的管脚分为8大类。

第一类:MII Interface

    外部扩张接口,TQ2440没用。

第二类:Processor Interface

处理器(ARM)与DM9000的接口,包括:片选、地址、数据、命令、状态标志。

IO16:字命令标志,当内部存储器的总线是16位或32位时。

INT:中断请求。

第三类:EEPROM Interface

    控制EEPROM的接口,TQ2440没有用。

第四类:Clock Interface

    25M时钟接口。

第五类:LED Interface    

第六类:10/100M PHY/Fiber

与网线相连的。

第七类:Miscellaneous

    对TQ2440来说没什么用。

第八类:Power Pins

用在TQ2440上的管脚

管脚号

输入输出类型

管脚名称

管脚功能

1

I

IOR#

读命令

2

I

IOW#

写命令

3

I

AEN

地址使能

4

O

IOWAIT

L表示命令等待,正常情况下时H。使用上拉电阻进行上拉,增强信号。

6~13

89~82

I/O

SD0~15

数据总线

92

I

CMD

命令类型:

H:数据;L:地址

100

O

INT

中断请求

以下为不重要的

14(硬件)

I

RST

复位(H)。被接地,故不能硬件复位。

93~98(硬件)

I

SA4~9

地址总线,选择DM9000

TQ2440中,

SA9SA8H

SA7SA6SA5SA4L

80(硬件)

I

PW_RST#

低电平有效,用于上电复位。

67(硬件)

I/O

EECS

用于LED模式选择引脚。

H:模式1(TQ2440)

L:模式0

62(LED灯)

O

LINK&ACT#

与LED相连

(1)在LED mode1表示连接和内部PHY的载波侦测信号的运行情况

(2)在LED mode2 表示内部PHY的载波侦测信号的运行情况

60(LED灯)

O

SPEED100#

L表示内部PHY运行在100Mbps;

H表示内部PHY运行在10Mbps

29

I

RXI+

TP RX Input

30

I

RXI-

TP Rx Input

33

O

TXO+

TP TX Output

34

O

TXO-

TP TX Output

3.3 DM9000的寄存器

 DM9000有许多的控制和状态寄存器,我们可以通过主机控制它。这些控制和状态寄存器(CSRs)是字节对齐的。所有的CSRs被硬件被设置为它们默认的值,也可以被软件设置为制定的值。

具体请参考DM9000的datasheet。

3.4 DM9000的初始化

(1)配置相关管脚

(2)进行ID测试

(3)配置寄存器

        a) 激活内部PHY

        b) 软件复位

        c) 使能中断

       d) 清除原网络状态和中断状态

       e) 对发射和接收进行新的控制

       f) 设置MAC地址

      g) 清除原网络状态和中断状态

      h) 使能中断

注意将MMU的BANK4的权限设为NCNB

MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_NCNB);

DM9000初始化函数如下

[cpp]  view plain copy
  1. //================================================================  
  2. //DM9000_Init()  
  3. //1.将相关的管脚配置好  
  4. //2.将相关的寄存器配置好  
  5.   
  6. //初始化寄存器主要做的事情:  
  7. //1.复位  
  8. //2.清楚原先的状态  
  9. //3.对发射、接收进行控制  
  10. //4.使能中断  
  11. //在设置时,有些地方需要重复设置。  
  12. //================================================================  
  13. void DM9000_Init()  
  14. {  
  15.     U8 i;  
  16.       
  17.     //1.配置管脚  
  18.     EINT_INIT( EINT7, Rising_edge);  
  19.     //2.进行ID测试  
  20.     Test_DM9000_ID();  
  21.     //3.配置寄存器  
  22.     //3.1.激活内部PHY  
  23.     DM9000_Write(GPCR,0x01);//设置GPCR bit[0]=1,使DM9000为GPIO0为输出  
  24.     DM9000_Write(GPR,0x00);//GPR bit[0]=0,使GPIO0输出低电平以激活内部PHY  
  25.     uDelay(5000);  
  26.       
  27.     //3.2 软件复位  
  28.     DM9000_Write(NCR,0x03); //软件复位,MAC内部循环反馈(?)  
  29.     uDelay(3000);           //延时10us以上,等待软件复位完成  
  30.     DM9000_Write(NCR,0x00); //复位完成,设置正常工作模式  
  31.     DM9000_Write(NCR,0x03); //第二次软件复位。确保软件复位完全成功  
  32.     uDelay(3000);             
  33.     DM9000_Write(NCR,0x00);  
  34.       
  35.     //3.3 使能中断  
  36.     DM9000_Write(IMR,0x80);//使能指向SRAM的指针的自动返回功能  
  37.       
  38.       
  39.     //3.4 清除原网络和中断状态  
  40.     DM9000_Write(NSR,0x2c); //清除各种状态标志位  
  41.     DM9000_Write(ISR,0xbf); //清除所有中断标志位,8-bit  
  42.       
  43.     //3.5 对发射和接收进行新的控制  
  44.     //    对中断进行新的控制  
  45.     DM9000_Write(RXCR,0x39);//接收控制  
  46.     DM9000_Write(TXCR,0x00);//发送控制  
  47.     DM9000_Write(BPTR,0x3f);//设置RX的最低阀值,小于将产生拥塞  
  48.     DM9000_Write(FCTR,0x00);//接收FIFO门限3K,8K  
  49.     DM9000_Write(FCR,0xff);//启动一些控制功能  
  50.     DM9000_Write(SMCR,0x00);//未启动特殊模式  
  51.       
  52.     //3.6  设置MAC地址   
  53.     for(i=0; i<6; i++)  
  54.         DM9000_Write(PAR+i, mac_addr[i]);  
  55.     //3.7  清除原网络状态和中断标志位  
  56.     DM9000_Write(NSR,0x2c); //清除各种状态标志位  
  57.     DM9000_Write(ISR,0x3f); //清除所有中断标志位,8-bit  
  58.       
  59.     //3.8 使能中断  
  60.     DM9000_Write(IMR,0x81);//使能指向SRAM的指针满后自动返回功能。  
  61.                            //使能数据包接收中断  
  62.                              
  63.     Uart_Printf("DM9000初始化结束");  
  64.     /MAC地址///  
  65.     Uart_Printf("\r\nMAC = %x",DM9000_Read(PAR)&0x00ff);  
  66.     Uart_Printf("  %x",DM9000_Read(PAR+1)&0x00ff);  
  67.     Uart_Printf("  %x",DM9000_Read(PAR+2)&0x00ff);  
  68.     Uart_Printf("  %x",DM9000_Read(PAR+3)&0x00ff);  
  69.     Uart_Printf("  %x",DM9000_Read(PAR+4)&0x00ff);  
  70.     Uart_Printf("  %x\r\n",DM9000_Read(PAR+5)&0x00ff);  }

    3.5 DM9000的数据包发送函数

    3.5.1 思路

        抓住主干;step by step

    3.5.2 发送数据包的过程

         DM9000发送数据总共包括两个过程:(1)发送过程;(2)状态职置位过程。

         首先,我们看发送过程:

    a) 检测内存数据位宽

    b) 将数据写入TX SRAM

    c) 将传输的长度写入MDRAL & MDRAH

    d) 将TXCRTXREQ置为1,当数据发送完毕后将TXREQ0(这个标志位可以用来检测数据是否发送完毕)。

           然后,我们看状态置位过程:

           当数据包被发送完毕后,

    a) 系统会将ISR(reg_FEH)的bit[1]PTS1(之前必须设置IMRPTM位为1,即使能数据包发送)。这个状态位可以用在中断服务函数中。

    b) 系统会使NSR(reg_01)bit[2]TX1END1。这个中断位可以用在轮询中。

    注意:内存数据位宽是可以通过ISRbit[7:6]设置的,可以设置为8bit, 16bit, 32bit

    3.5.3 数据包发送函数

    [cpp]  view plain copy
    1. //================================================================  
    2. //DM9000_send_Packet  
    3. //DM9000 packet发送函数  
    4. //================================================================  
    5. void DM9000_sendPacket(U8 *data_str, U32 length)  
    6. {  
    7.     U32 len; //数据的长度  
    8.     U32 i;  
    9.     U8  tmp;  
    10.     //==========数据发送开始=============//  
    11.     Uart_Printf("\r\nDM9000\r\n发送数据...\r\n");  
    12.     //1.关闭网卡中断  
    13.     DM9000_Write(IMR,0x80); //先禁止网卡中断,防止在发送数据时被中断干扰。  
    14.     //2.将传输长度写到TXPLH和TXPLL中  
    15.     len = length;           //将发送长度写入  
    16.     DM9000_Write(TXPLH,(len>>8)&0x0ff);  
    17.     DM9000_Write(TXPLL,len & 0x0ff);  
    18.     //3.将数据写入TX SRAM中,通过MWCMD。  
    19.     rDM9000_ADDR = MWCMD; //将Memory Write CMD发送到ADD上  
    20.     for(i=0; i<len; i+=2)  
    21.     {  
    22.         uDelay(2);  
    23.         DM9000_WriteC_DATA(data_str[i] | (data_str[i+1]<<8));  
    24.     }  
    25.     //4.将TXCR的TXREQ置位  
    26.     DM9000_Write(TXCR, 0x01);  
    27.       
    28.     //5.等待数据发送完成                         
    29.     while(1)  
    30.     {  
    31.         U8 status;  
    32.         status = DM9000_Read(TXCR);  
    33.         if((status & 0x01) == 0x00)  
    34.             break;  
    35.     }  
    36.     //Uart_Printf("\r\n数据发送完毕,进入检测阶段\r\n");  
    37.     //==========数据发送结束=============//  
    38.     //==========状态置位开始=============//  
    39.     tmp = DM9000_Read(NSR);  
    40.     //Uart_Printf("\r\nNSR = %x\r\n",tmp);  
    41.     if(tmp && 0x04)  
    42.     {  
    43.         if((TSRI&0xfc) == 0x00)  
    44.             ;//Uart_Printf("TSRI成功\r\n");  
    45.         else  
    46.             ;//Uart_Printf("TSRI失败\r\n");  
    47.     }  
    48.     DM9000_Write(NSR,0xfc); //清除状态寄存器,以防止对下一次的干扰。  
    49.                             //由于发送数据没有设置中断,因此不必处理中断标志位。  
    50.     DM9000_Write(IMR,0x81); //DM9000网卡的接收中断使能。  
    51.     Uart_Printf("\r\n数据发送完毕\r\n");  
    52. }  

    3.6 数据包接收函数

    3.6.1 DM9000接收数据包结构

       第一个字节表明其后是否还有数据包;

       第二个字节和接收状态寄存器(RXSR)的值相同;

       第个和第四个为接收数据包的长度。

       其它字节为接收数据包。

    3.6.2 DM9000接收数据包过程

       DM9000接收数据包共包括两个过程:(1)接收过程;(2)状态置位过程。

       接收过程如下:

    (1)通过MRCMDX读数据包的第一个字节,并辨别其后是否有数据包;

    (2)驱动IO的宽度;

    (3)通过MRCMD读数据包的第二和第三字节,得到RXSR的值和接收数据包的长度;

    (4)接收数据包

       状态置位过程:

       数据包接收完成后,会置位ISR的第一位置为1

    3.6.3 DM9000的数据包接收函数

    [cpp]  view plain copy
    1. //================================================================  
    2. //DM9000_received_Packet  
    3. //DM9000 packet接收函数  
    4. //================================================================  
    5. U32 DM9000_receivePacket(U8 *data_str)  
    6. {  
    7.     U8  RX_First_byte=0;//RX SRAM的第一个字节的值  
    8.     U8  RX_status=0;//寄存器RXSR的值  
    9.     U32 RX_length=0;//接收数据包的长度  
    10.     U16  data_temp=0;  
    11.     U32 i;//计数用   
    12.     //读取RX SRAM的第一个字节  
    13.     RX_First_byte = DM9000_Read(MRCMDX);//读取RX SRAM的第一个字节的值  
    14.     Uart_Printf("RX_First_byte = 0x%x",RX_First_byte);                                  //第一次读取经常得到00  
    15.     RX_First_byte = DM9000_Read(MRCMDX);//第二次读取一般能得到数据  
    16.     Uart_Printf("RX_First_byte = 0x%x",RX_First_byte);  
    17.     //读取RX SRAM的第二、三、四个字节  
    18.     if(RX_First_byte == 0x01)  
    19.     {  
    20.         U8 io_mode = DM9000_Read(ISR)>>6;  
    21.         rDM9000_ADDR = MRCMD; //将Memory Write CMD发送到ADD上  
    22.           
    23.         if(io_mode == 0)//IO word mode  
    24.         {  
    25.             RX_First_byte = DM9000_ReadC_DATA();//读取接收状态寄存器的值  
    26.             Uart_Printf("\r\nRX_First_byte = %d\r\nRX_status = %d\r\n",RX_First_byte&0x00ff,(RX_status>>8)&0x00ff);  
    27.             RX_length = DM9000_ReadC_DATA();//读取接收状态寄存器的值  
    28.             Uart_Printf("\r\nRX_length = %d\r\n",RX_length);;  
    29.         }  
    30.         else if(io_mode == 1)//IO dword mode  
    31.         {  
    32.           
    33.         }  
    34.         else if(io_mode == 2)//IO byte mode  
    35.         {  
    36.           
    37.         }  
    38.           
    39.         //读取接收的数据包  
    40.         for(i=0;i<RX_length;i=i+2)  
    41.         {  
    42.             //uDelay(20);  
    43.             data_temp = DM9000_ReadC_DATA();//读取到的16bit的数据  
    44.             data_str[i]   = data_temp&0x00ff;  
    45.             //Uart_Printf("data_str[%d] = %x",i,data_str[i]);  
    46.             Uart_Printf("  %x",data_str[i]);  
    47.             data_str[i+1] = (data_temp >> 8)&0x00ff;  
    48.             //Uart_Printf("data_str[%d] = %x",i+1,data_str[i+1]);  
    49.             Uart_Printf("  %x",data_str[i+1]);  
    50.         }  
    51.         //Uart_Printf("\r\nRX Data :%s.\r\n",data_str);//接收的数据  
    52.         //Uart_Printf("\r\nRX_length is %ld\r\n",RX_length);//接收的数据的长度  
    53.         return RX_length;  
    54.               
    55.     }  
    56.     else  
    57.     {  
    58.         Uart_Printf("无数据包");  
    59.         return -1;  
    60.     }  
    61.       
    62. }  

      1 ARP协议简介

              ARP协议是Address Resolution Protocol(地址解析协议)的缩写。所谓的“地址解析”就是主机在发送帧前将目标IP地址转换为目标MAC地址的过程。

              ARP协议的基本功能就是通过目标设备的IP地址(32位),查询目标设备的MAC地址(48位),以保证通信的顺利进行。

      2 ARP协议的数据结构

      [cpp]  view plain copy
      1. typedef struct _arp_hdr     //以太网头部 + ARP首部结构  
      2. {  
      3.     ETH_HDR  ethhdr;//以太网首部  
      4.        
      5.         U16  hwtype;//硬件类型(1表示传输的是以太网MAC地址)  
      6.         U16  protocol;//协议类型(0x800表示传输的IP地址)  
      7.       
      8.         U8   hwlen;//硬件地址长度(6)  
      9.         U8   protolen;//协议地址长度(4)  
      10.       
      11.         U16  opcode;//操作(1表示ARP请求,2表示ARP应答)  
      12.       
      13.         U8   s_mac[6];//发送者MAC地址  
      14.         U8   s_ipaddr[4];//发送者IP地址  
      15.           
      16.         U8   d_mac[6];//目的端MAC地址  
      17.         U8   d_ipaddr[4];//目的端IP地址  
      18. }ARP_HDR;  

      3 发送ARP请求数据包

      3.1 发送ARP数据包的过程

      (1)为ARP协议的数据包的相关值进行赋值。

      (2)设置发送的数据包的长度

      (3)发送数据包

      3.2 发送ARP数据包的函数

      [cpp]  view plain copy
      1. void arp_request(void)  //发送ARP请求数据包  
      2. {  
      3.       
      4.     ///经验发现:每次发射前,需要进行一定的初始化  
      5.     //3.2 软件复位  
      6.     DM9000_Write(NCR,0x03); //软件复位,MAC内部循环反馈(?)  
      7.     uDelay(3000);           //延时10us以上,等待软件复位完成  
      8.     DM9000_Write(NCR,0x00); //复位完成,设置正常工作模式  
      9.     DM9000_Write(NCR,0x03); //第二次软件复位。确保软件复位完全成功  
      10.     uDelay(3000);             
      11.     DM9000_Write(NCR,0x00);  
      12.       
      13.     //3.3 使能中断  
      14.     DM9000_Write(IMR,0x80);//使能指向SRAM的指针的自动返回功能  
      15.       
      16.     //3.4 清除原网络和中断状态  
      17.     DM9000_Write(NSR,0x2c); //清除各种状态标志位  
      18.     DM9000_Write(ISR,0xbf); //清除所有中断标志位,8-bit  
      19.       
      20.     //3.5 对发射和接收进行新的控制  
      21.     //    对中断进行新的控制  
      22.     DM9000_Write(RXCR,0x39);//接收控制  
      23.     DM9000_Write(TXCR,0x00);//发送控制  
      24.     DM9000_Write(BPTR,0x3f);//设置RX的最低阀值,小于将产生拥塞  
      25.     DM9000_Write(FCTR,0x00);//接收FIFO门限3K,8K  
      26.     DM9000_Write(FCR,0xff);//启动一些控制功能  
      27.     DM9000_Write(SMCR,0x00);//未启动特殊模?  
      28.     ///  
      29.       
      30.     ARPBUF = (ARP_HDR*)&Buffer; //ARPBUF指向Buffer  
      31.       
      32.     //为ARPBUF赋值  
      33.     memcpy(ARPBUF->ethhdr.d_mac,host_mac_addr,6);  
      34.     memcpy(ARPBUF->ethhdr.s_mac,mac_addr,6);  
      35.     ARPBUF->ethhdr.type = HON(0x0806);  
      36.       
      37.     ARPBUF->hwtype = HON(1);  
      38.     ARPBUF->protocol = HON(0x0800);  
      39.       
      40.     ARPBUF->hwlen = 6;  
      41.     ARPBUF->protolen =4;  
      42.       
      43.     ARPBUF->opcode = HON(1);  
      44.       
      45.     memcpy(ARPBUF->s_mac, mac_addr,6);  
      46.     memcpy(ARPBUF->s_ipaddr, ip_addr,4);  
      47.       
      48.     memcpy(ARPBUF->d_mac, host_mac_addr,6);//  
      49.     memcpy(ARPBUF->d_ipaddr, host_ip_addr,4);  
      50.       
      51.     packet_len = 42;//14+28  
      52.     //将ARP发送出去  
      53.     DM9000_sendPacket(Buffer, packet_len);    
      54. }  

      4  ARP协议接收处理函数

      4.1 ARP协议接收数据包的处理过程

      (1)根据 HON(ARPBUF->ethhdr.type)判断所接受的数据包是否符合ARP协议

      (2)根据HON(ARPBUF->opcode)判断接收的是请求还是应答。

      4.2 ARP协议接收处理函数

      [cpp]  view plain copy
      1. U8 arp_process(void)    //ARP接收函数,成功返回1,否则返回0  
      2. {  
      3.       
      4.     ARPBUF = (ARP_HDR*)&RX_Buffer;  //ARPBUF指向Buffer      
      5.       
      6.     if( HON(ARPBUF->ethhdr.type) != 0x0806)  
      7.     {  
      8.         Uart_Printf("非ARP协议包");  
      9.         return 0;  
      10.     }  
      11.     else  
      12.     {  
      13.         Uart_Printf("\r\n收到的为ARP协议包\r\n");  
      14.     }  
      15.       
      16.     //简单判断ARP数据包是否有损坏,有损坏则丢弃,不予处理  
      17.     if(packet_len < 28)  //数据包长度小于28个字节,为无效数据。  
      18.     {  
      19.         Uart_Printf("未进入,数据包长度小");  
      20.         return 0;  
      21.     }  
      22.       
      23.     switch (HON(ARPBUF->opcode) )  
      24.     {  
      25.         case 1: //处理ARP请求  
      26.             if(  
      27.                 //判断是否是自己的IP,是否向自己询问MAC地址  
      28.                 (ARPBUF->d_ipaddr[0] == ip_addr[0]) &&  
      29.                 (ARPBUF->d_ipaddr[1] == ip_addr[1]) &&  
      30.                 (ARPBUF->d_ipaddr[2] == ip_addr[2]) &&  
      31.                 (ARPBUF->d_ipaddr[3] == ip_addr[3])   )  
      32.             {  
      33.                 ARPBUF->opcode = HON(2); //设置为ARP应答  
      34.                 memcpy(ARPBUF->ethhdr.d_mac,ARPBUF->ethhdr.s_mac,6);  
      35.                 memcpy(ARPBUF->ethhdr.s_mac,mac_addr,6);  
      36.                 memcpy(ARPBUF->s_mac, mac_addr,6);  
      37.                 memcpy(ARPBUF->s_ipaddr, ip_addr,4);  
      38.                 memcpy(ARPBUF->d_mac, ARPBUF->s_mac,6);//  
      39.                 memcpy(ARPBUF->d_ipaddr, ARPBUF->s_ipaddr,4);  
      40.                   
      41.                 packet_len = 42;  
      42.                 DM9000_sendPacket(RX_Buffer,packet_len);    //发送ARP数据包  
      43.                 Uart_Printf("TQ接收到ARP请求包");  
      44.                 return 1;  
      45.             }  
      46.             else  
      47.             {  
      48.                 return 0;  
      49.             }  
      50.           break;  
      51.         case 2: //处理ARP应答  
      52.             //Uart_Printf("\r\nARPBUF->d_ipaddr[3]=%d\r\n",ARPBUF->d_ipaddr[3]);  
      53.             //Uart_Printf("\r\n ip_addr[3]=%d\r\n",ip_addr[3]);  
      54.             if(//再次判断是否是自己的IP,是否向自己询问MAC地址  
      55.                 (ARPBUF->d_ipaddr[0] == ip_addr[0]) &&  
      56.                 (ARPBUF->d_ipaddr[1] == ip_addr[1]) &&  
      57.                 (ARPBUF->d_ipaddr[2] == ip_addr[2]) &&  
      58.                 (ARPBUF->d_ipaddr[3] == ip_addr[3])    
      59.               )  
      60.             {  
      61.                 memcpy(host_mac_addr,ARPBUF->s_mac,6);//保存服务器MAC地址  
      62.                 Uart_Printf("TQ接收到ARP应答包");  
      63.                 return 1;  
      64.             }  
      65.             else  
      66.             {  
      67.                 return 0;  
      68.             }  
      69.           break;  
      70.         default://不是ARP协议  
      71.             Uart_Printf("进入default");  
      72.             return 0;  
      73.          break;  
      74.     }  
      75. }  




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值