This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C1294KCPDT移植LWIP2.0.2时发送数据失败

初始化和收发函数是按官方例子enet_lwip、enet_uip改的,代码如下:

/*
******************************************************************************************************
**                                          标志位定义                                               **
******************************************************************************************************
*/
uint8_t     ETH_FLAG_RXPKT;     //->0:没收到数据包     1:接收到数据包
uint8_t     ETH_FLAG_TXPKT;     //->0:数据包发送完成    1:数据包等待发送
/*
******************************************************************************************************
**                                  描述和状态定义以及EMAC内存分配                                   **
******************************************************************************************************
*/
#define NUM_RX_DESCRIPTORS 3
#define NUM_TX_DESCRIPTORS 3

#define RX_BUFFER_SIZE 1536
#define TX_BUFFER_SIZE 1536

tEMACDMADescriptor RxDescriptor[NUM_TX_DESCRIPTORS];
tEMACDMADescriptor TxDescriptor[NUM_RX_DESCRIPTORS];

uint8_t RxBuffer[NUM_RX_DESCRIPTORS][RX_BUFFER_SIZE];
uint8_t TxBuffer[NUM_TX_DESCRIPTORS][TX_BUFFER_SIZE];

static  uint32_t    RxDescIndex;
static  uint32_t    TxDescIndex;

/*
******************************************************************************************************
**                                          设备信息定义                                          **
******************************************************************************************************
*/
typedef struct
{
    uint8_t     mac[6];         //MAC地址.
    uint8_t     ip[4];          //IP地址.
    uint8_t     mark[4];        //子网掩码.
    uint8_t     gate[4];        //默认网关.
    
}device_t;

device_t    Device;

static const uint8_t    IP[4]   ={192,168,1,88};                    //本机IP地址.
static const uint8_t    MARK[4] ={255,255,255,0};                   //子网掩码.
static const uint8_t    GATE[4] ={192,168,1,1};                     //默认网关.

/*
******************************************************************************************************
**函数名称: void InitDescriptors(void)                                                              **
**函数描述: 初始化发送、接收描述相关参量(OWN = 1:owned by the DMA  OWN = 0:owned by the CPU)      **
**参    数:   无                                                                                       ** 
**返    回:   无                                                                                       **
******************************************************************************************************
*/
void InitDescriptors(void)
{
    uint32_t ui32Loop;

    // Initialize each of the receive descriptors.  
    for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
    {
        RxDescriptor[ui32Loop].ui32CtrlStatus   = 0;
        RxDescriptor[ui32Loop].ui32Count        = (DES1_RX_CTRL_CHAINED | (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));
        RxDescriptor[ui32Loop].pvBuffer1        = RxBuffer[ui32Loop];
        RxDescriptor[ui32Loop].DES3.pLink       = (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ? &RxDescriptor[0] : &RxDescriptor[ui32Loop + 1];
    }
    
    // Initialize each of the transmit descriptors.  Note that we leave the OWN bit clear here since we have not set up any transmissions yet.
    for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
    {
        TxDescriptor[ui32Loop].ui32CtrlStatus   = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS);
        TxDescriptor[ui32Loop].ui32Count        = (DES1_TX_CTRL_SADDR_INSERT | (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
        TxDescriptor[ui32Loop].pvBuffer1        = TxBuffer[ui32Loop];
        TxDescriptor[ui32Loop].DES3.pLink       = (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ? &TxDescriptor[0] : &TxDescriptor[ui32Loop + 1];
    }

    // Set the descriptor pointers in the hardware.
    EMACRxDMADescriptorListSet(EMAC0_BASE, RxDescriptor);
    EMACTxDMADescriptorListSet(EMAC0_BASE, TxDescriptor);

    // Start from the beginning of both descriptor chains. We actually set the transmit descriptor index to the last descriptor in the chain
    // since it will be incremented before use and this means the first transmission we perform will use the correct descriptor.
    RxDescIndex = 0;
    TxDescIndex = NUM_TX_DESCRIPTORS - 1;
	
    // Mark the first receive descriptor as available to the DMA to start the receive processing.
    RxDescriptor[RxDescIndex].ui32CtrlStatus |= DES0_RX_CTRL_OWN;
}

/*
******************************************************************************************************
**函数名称: uint32_t PacketReceive(uint8_t *pui8Buf)                                                **
**函数描述: 从DMA接收缓冲区读取一个数据包                                                            **
**参    数:   pui8Buf-------数据包存储缓冲区指针                                                        **
**返    回:   i32FrameLen---数据长度                                                                  **
******************************************************************************************************
*/
uint32_t PacketReceive(uint8_t *pui8Buf)
{
    uint32_t i32FrameLen, i32Loop;

    // Check the arguments.
    ASSERT(pui8Buf != 0);

    // By default, we assume we got a bad frame.
    i32FrameLen = 0;

    // Make sure that CPU own the receive descriptor. 
    if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN))
    {
        // We own the receive descriptor so check to see if it contains a valid frame.  Look for a descriptor error, 
        // indicating that the incoming packet was truncated or, if this is the last frame in a packet, the receive error bit.
        if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_ERR))
        {
            // We have a valid frame so copy the content to the supplied buffer. First check that the "last descriptor" flag is set.
            // We sized the receive buffer such that it can always hold a valid frame so this flag should never be clear at this point but...
            if(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_LAST_DESC)
            {
                i32FrameLen = ((RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_FRAME_LENGTH_M) >> DES0_RX_STAT_FRAME_LENGTH_S);

                // Sanity check.
                if(i32FrameLen > RX_BUFFER_SIZE)
                {
                    i32FrameLen = RX_BUFFER_SIZE;
                }

                // Copy the data from the DMA receive buffer into the provided frame buffer.
                for(i32Loop = 0; i32Loop < i32FrameLen; i32Loop++)
                {
                    pui8Buf[i32Loop] = RxBuffer[RxDescIndex][i32Loop];
                }
            }
        }

        // Move on to the next descriptor in the chain.
        RxDescIndex++;
        if(RxDescIndex == NUM_RX_DESCRIPTORS)
        {
            RxDescIndex = 0;
        }

        // Give this descriptor back to the DMA.
        RxDescriptor[RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;
    }

    // Return the Frame Length.
    return(i32FrameLen);
}

/*
******************************************************************************************************
**函数名称: uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen)                           **
**函数描述: 发送数据包                                                                               **
**参    数:   pui8Buf-----待发送数据包缓冲区指针                                                     **
**          i32BufLen---待发送数据包的长度                                                           **
**返    回:   i32BufLen---实际发送数据的长度                                                           **
******************************************************************************************************
*/
uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen)
{
    uint32_t i32Loop;

    // Indicate that a packet is being sent.
    ETH_FLAG_TXPKT = 1;
printf("ETH_FLAG_TXPKT = 1;\r\n");
    // Wait for the previous packet to be transmitted.
    while(TxDescriptor[TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN);
printf("ETH_FLAG_TXPKT = 2;\r\n");
    // Sanity check.
    if(i32BufLen > TX_BUFFER_SIZE)
    {
        i32BufLen = TX_BUFFER_SIZE;
    }

    // Copy the packet data into the transmit buffer.
    for(i32Loop = 0; i32Loop < i32BufLen; i32Loop++)
    {
        TxBuffer[TxDescIndex][i32Loop] = pui8Buf[i32Loop];
        printf("pui8Buf[%d] = %02X\r\n", i32Loop, pui8Buf[i32Loop]);
    }

    // Move to the next descriptor.
    TxDescIndex++;
    if(TxDescIndex == NUM_TX_DESCRIPTORS)
    {
        TxDescIndex = 0;
    }

    // Fill in the packet size and tell the transmitter to start work.
    TxDescriptor[TxDescIndex].ui32Count         = (uint32_t)i32BufLen;
    TxDescriptor[TxDescIndex].ui32CtrlStatus    = ( DES0_TX_CTRL_LAST_SEG  | 
                                                    DES0_TX_CTRL_FIRST_SEG | 
                                                    DES0_TX_CTRL_INTERRUPT | 
                                                    DES0_TX_CTRL_IP_ALL_CKHSUMS | 
                                                    DES0_TX_CTRL_CHAINED | 
                                                    DES0_TX_CTRL_OWN);

    // Tell the DMA to reacquire the descriptor now that we've filled it in.
    EMACTxDMAPollDemand(EMAC0_BASE);
printf("ETH_FLAG_TXPKT = 3;\r\n");
    // Return the number of bytes sent.
    return(i32BufLen);
}

/*
******************************************************************************************************
**函数名称: void HAL_EMAC_Init(void)                                                                **
**函数描述: 网口初始化                                                                               **
**参    数:   无                                                                                       **
**返    回:   无                                                                                       **
******************************************************************************************************
*/
void HAL_EMAC_Init(void)
{
    // PF0/PF1/PF4 are used for Ethernet LEDs.
    GPIOPinConfigure(GPIO_PF0_EN0LED0);
    GPIOPinConfigure(GPIO_PF4_EN0LED1);
    GPIOPinConfigure(GPIO_PF1_EN0LED2);

    GPIOPinTypeEthernetLED(GPIOF_AHB_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4);
    
    // Wait for the MAC to be ready.
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
    
    // Configure for use with the internal PHY.
    EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | EMAC_PHY_AN_100B_T_FULL_DUPLEX);
    
    // Reset the MAC.
    EMACReset(EMAC0_BASE);
    
    // Initialize the MAC and set the DMA mode.
    EMACInit(EMAC0_BASE, SystemCoreClock, EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0);
    
    // Set MAC configuration options.
    EMACConfigSet(EMAC0_BASE,
                 (EMAC_CONFIG_FULL_DUPLEX | 
                  EMAC_CONFIG_CHECKSUM_OFFLOAD |
                  EMAC_CONFIG_7BYTE_PREAMBLE | 
                  EMAC_CONFIG_IF_GAP_96BITS |
                  EMAC_CONFIG_USE_MACADDR0 |
                  EMAC_CONFIG_SA_FROM_DESCRIPTOR |
                  EMAC_CONFIG_BO_LIMIT_1024),
                 (EMAC_MODE_RX_STORE_FORWARD |
                  EMAC_MODE_TX_STORE_FORWARD |
                  EMAC_MODE_TX_THRESHOLD_64_BYTES |
                  EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
    
    // Initialize the Ethernet DMA descriptors.
    InitDescriptors();
    
    // Program the hardware with its MAC address (for filtering).
    EMACAddrSet(EMAC0_BASE, 0, Device.mac);
    
    // Wait for the link to become active.
    //while((EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0);
    
    // Set MAC filtering options.  We receive all broadcast and multicast packets along with those addressed specifically for us.
    EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR | EMAC_FRMFILTER_PASS_MULTICAST | EMAC_FRMFILTER_PASS_NO_CTRL));

    // Clear any pending interrupts.
    EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
    
    // Enable the Ethernet MAC transmitter and receiver.
    EMACTxEnable(EMAC0_BASE);
    EMACRxEnable(EMAC0_BASE);
    
    // Enable the Ethernet interrupt.
    IntEnable(INT_EMAC0);
    
    // Enable the Ethernet RX Packet interrupt source.
    EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT);
}

/*
******************************************************************************************************
**函数名称: void ENET_IRQHandler(void)                                                              **
**函数描述: 以太网中断服务程序                                                                       **
**参    数:   无                                                                                       **
**返    回:   无                                                                                       **
******************************************************************************************************
*/
void ETH_Handler(void)
{
    uint32_t IntStatus;

    // Read and Clear the interrupt.
    IntStatus = EMACIntStatus(EMAC0_BASE, true);
    MAP_EMACIntClear(EMAC0_BASE, IntStatus);

    // Check to see if an RX Interrupt has occurred.
    if(IntStatus & EMAC_INT_RECEIVE)
    {
        // Indicate that a packet has been received.
        ETH_FLAG_RXPKT = 1;
    }

    // Has the DMA finished transferring a packet to the transmitter?
    if(IntStatus & EMAC_INT_TRANSMIT)
    {
        // Indicate that a packet has been sent.
        ETH_FLAG_TXPKT = 0;
    }
}

/*
******************************************************************************************************
**函数名称: void Config(void)                                                                       **
**函数描述: 参数配置函数                                                                          **
**参    数: 无                                                                                     **
**返    回: 无                                                                                     **
******************************************************************************************************
*/
void Config(void)
{
uint32_t ui32User0, ui32User1;
    
    FlashUserGet(&ui32User0, &ui32User1);
    if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    {
        //
        // We should never get here.  This is an error if the MAC address has
        // not been programmed into the device.  Exit the program.
        // Let the user know there is no MAC address
        //
        printf("No MAC programmed!\n");
        while(1)
        {
        }
    }
    
    Device.mac[0] = ((ui32User0 >>  0) & 0xff);
    Device.mac[1] = ((ui32User0 >>  8) & 0xff);
    Device.mac[2] = ((ui32User0 >> 16) & 0xff);
    Device.mac[3] = ((ui32User1 >>  0) & 0xff);
    Device.mac[4] = ((ui32User1 >>  8) & 0xff);
    Device.mac[5] = ((ui32User1 >> 16) & 0xff);
    
    
    memcpy(Device.ip,   IP,   4);               //IP
    memcpy(Device.mark, MARK, 4);               //MARK
    memcpy(Device.gate, GATE, 4);               //GATEWAY
}

/*
******************************************************************************************************
**函数名称: void APP_LWIP_Init(void)                                                                **
**函数描述: 初始化LWIP所有相关信息                                                                   **
**参    数:   无                                                                                       **
**返    回:   无                                                                                       **
******************************************************************************************************
*/
void APP_LWIP_Init(void)
{
    Config();
    HAL_EMAC_Init();                                    //初始化EMAC.
    lwip_init();                                        //LwIP协议栈初始化.

    // add the network interface.
    netif_add(&my_netif, (ip4_addr_t *)&Device.ip, (ip4_addr_t *)&Device.mark, (ip4_addr_t *)&Device.gate, NULL, ethernetif_init, ethernet_input);

    // Registers the default network interface.
    netif_set_default(&my_netif);

    netif_set_up(&my_netif);


    
    //HTTP应用层初始化
    //httpd_init();                                     //初始化HTTP服务器监听端口.
    //httpd_cgi_ssi_init();                             //CGI、SSI相关初始化.

    //TCP应用层初始化
    //tcp_server_init();                                    //初始化TCP服务器.
    
    //UDP应用层初始化
    //udp_server_init();                                    //初始化UDP服务器.

}

ethernetif.c代码如下:

/**
 * @file
 * Ethernet Interface Skeleton
 *
 */

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 * Author: Adam Dunkels <adam@sics.se>
 *
 */

/*
 * This file is a skeleton for developing Ethernet network interface
 * drivers for lwIP. Add code to the low_level functions and do a
 * search-and-replace for the word "ethernetif" to replace it with
 * something that better describes your network interface.
 */

#include "lwip/opt.h"

#if 1 /* don't build, this is only a skeleton, see previous comment */

#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include "netif/etharp.h"
#include "netif/ppp/pppoe.h"

#include "includes.h"		// add by eBoy---2012-10-20


/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'

/**
 * Helper struct to hold private data used to operate your ethernet interface.
 * Keeping the ethernet address of the MAC in this struct is not necessary
 * as it is already kept in the struct netif.
 * But this is only an example, anyway...
 */
struct ethernetif {
  struct eth_addr *ethaddr;
  /* Add whatever per-interface state that is needed here. */
};

/* Forward declarations. */
err_t  ethernetif_input(struct netif *netif);

/**
 * In this function, the hardware should be initialized.
 * Called from ethernetif_init().
 *
 * @param netif the already initialized lwip network interface structure
 *        for this ethernetif
 */
static void
low_level_init(struct netif *netif)
{
  //struct ethernetif *ethernetif = netif->state;
  
  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  /* set MAC hardware address */
  netif->hwaddr[0] =  Device.mac[0];
  netif->hwaddr[1] =  Device.mac[1];
  netif->hwaddr[2] =  Device.mac[2];
  netif->hwaddr[3] =  Device.mac[3];
  netif->hwaddr[4] =  Device.mac[4];
  netif->hwaddr[5] =  Device.mac[5];
/*	
	printf("netif->hwaddr[0] =  %02X\r\n",netif->hwaddr[0]);
	printf("netif->hwaddr[1] =  %02X\r\n",netif->hwaddr[1]);
	printf("netif->hwaddr[2] =  %02X\r\n",netif->hwaddr[2]);
	printf("netif->hwaddr[3] =  %02X\r\n",netif->hwaddr[3]);
	printf("netif->hwaddr[4] =  %02X\r\n",netif->hwaddr[4]);
	printf("netif->hwaddr[5] =  %02X\r\n",netif->hwaddr[5]);
*/
  /* maximum transfer unit */
  netif->mtu = 1500;
  
  /* device capabilities */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
 
  /* Do whatever else is needed to initialize interface. */  
}

/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *       strange results. You might consider waiting for space in the DMA queue
 *       to become availale since the stack doesn't retry to send a packet
 *       dropped because of memory failure (except for the TCP timers).
 */

static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
  //struct ethernetif *ethernetif = netif->state;
  struct pbuf *q;
  u16_t len=0;
  u8_t	buffer[1536];

  for(q = p; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
      memcpy((u8_t*)&buffer[len], (u8_t*)q->payload, q->len);
      len = len + q->len;
  }
  
  PacketTransmit(buffer, len);

  return ERR_OK;
}

/**
 * Should allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error
 */
static struct pbuf *
low_level_input(struct netif *netif)
{
  //struct ethernetif *ethernetif = netif->state;
  struct pbuf *p, *q;
  u16_t len=0,i=0;
  u8_t	buffer[1536];

  /* Obtain the size of the packet and put it into the "len"
     variable. */
  len = PacketReceive(buffer);

  /* We allocate a pbuf chain of pbufs from the pool. */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  
  if (p != NULL) {

    /* We iterate over the pbuf chain until we have read the entire
     * packet into the pbuf. */
    for(q = p; q != NULL; q = q->next) {
      /* Read enough bytes to fill this pbuf in the chain. The
       * available data in the pbuf is given by the q->len
       * variable.
       * This does not necessarily have to be a memcpy, you can also preallocate
       * pbufs for a DMA-enabled MAC and after receiving truncate it to the
       * actually received size. In this case, ensure the tot_len member of the
       * pbuf is the sum of the chained pbuf len members.
       */
      memcpy((u8_t*)q->payload, (u8_t*)&buffer[i], q->len);
      i = i + q->len;
    }
   }

  return p;  
}

/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
err_t
ethernetif_input(struct netif *netif)
{
  //struct ethernetif *ethernetif = netif->state;
  struct pbuf *p;
  err_t err;

  /* move received packet into a new pbuf */
  p = low_level_input(netif);

  /* no packet could be read, silently ignore this */
  if (p == NULL) return ERR_MEM;

  err = netif->input(p, netif);
  if (err != ERR_OK)
  {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    pbuf_free(p);
    p = NULL;
  }

  return err;
}

/**
 * Should be called at the beginning of the program to set up the
 * network interface. It calls the function low_level_init() to do the
 * actual setup of the hardware.
 *
 * This function should be passed as a parameter to netif_add().
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return ERR_OK if the loopif is initialized
 *         ERR_MEM if private data couldn't be allocated
 *         any other err_t on error
 */
err_t
ethernetif_init(struct netif *netif)
{
  struct ethernetif *ethernetif;

  LWIP_ASSERT("netif != NULL", (netif != NULL));
    
  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL) {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    return ERR_MEM;
  }

#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */

  /*
   * Initialize the snmp variables and counters inside the struct netif.
   * The last argument should be replaced with your link speed, in units
   * of bits per second.
   */
  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);

  netif->state = ethernetif;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  /* We directly use etharp_output() here to save a function call.
   * You can instead declare your own function an call etharp_output()
   * from it if you have to do some checks before sending (e.g. if link
   * is available...) */
  netif->output = etharp_output;
  netif->linkoutput = low_level_output;
  
  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
  
  /* initialize the hardware */
  low_level_init(netif);

  return ERR_OK;
}

#endif /* 0 */

ping 192.168.1.88时,串口输出如下:

 


通过串口打印的信息看,回复的是ARP帧,可电脑好像收不到,导致后面的ICMP一直Ping不通。
求大神帮忙~!谢谢!
  • 上面发的2张图好像看不见,再发一次。。。
    ping 192.168.1.88时,串口输出如下:
     
    
    
     
    
    
    通过串口打印的信息看,回复的是ARP帧,可电脑好像收不到,导致后面的ICMP一直Ping不通。
    求大神帮忙~!谢谢!
  • hello,有大神在吗?没人帮我看看这个问题吗?

    怀疑是驱动问题,可又找不出是哪的问题,求助呀。。。SOS。。。

  • 初始化和收发函数是按官方例子enet_lwip、enet_uip改的,代码如下:

    /*
    ******************************************************************************************************
    **                                          标志位定义                                               **
    ******************************************************************************************************
    */
    uint8_t     ETH_FLAG_RXPKT;     //->0:没收到数据包     1:接收到数据包
    uint8_t     ETH_FLAG_TXPKT;     //->0:数据包发送完成    1:数据包等待发送
    /*
    ******************************************************************************************************
    **                                  描述和状态定义以及EMAC内存分配                                   **
    ******************************************************************************************************
    */
    #define NUM_RX_DESCRIPTORS 3
    #define NUM_TX_DESCRIPTORS 3
    
    #define RX_BUFFER_SIZE 1536
    #define TX_BUFFER_SIZE 1536
    
    tEMACDMADescriptor RxDescriptor[NUM_TX_DESCRIPTORS];
    tEMACDMADescriptor TxDescriptor[NUM_RX_DESCRIPTORS];
    
    uint8_t RxBuffer[NUM_RX_DESCRIPTORS][RX_BUFFER_SIZE];
    uint8_t TxBuffer[NUM_TX_DESCRIPTORS][TX_BUFFER_SIZE];
    
    static  uint32_t    RxDescIndex;
    static  uint32_t    TxDescIndex;
    
    /*
    ******************************************************************************************************
    **                                          设备信息定义                                          **
    ******************************************************************************************************
    */
    typedef struct
    {
        uint8_t     mac[6];         //MAC地址.
        uint8_t     ip[4];          //IP地址.
        uint8_t     mark[4];        //子网掩码.
        uint8_t     gate[4];        //默认网关.
        
    }device_t;
    
    device_t    Device;
    
    static const uint8_t    IP[4]   ={192,168,1,88};                    //本机IP地址.
    static const uint8_t    MARK[4] ={255,255,255,0};                   //子网掩码.
    static const uint8_t    GATE[4] ={192,168,1,1};                     //默认网关.
    
    /*
    ******************************************************************************************************
    **函数名称: void InitDescriptors(void)                                                              **
    **函数描述: 初始化发送、接收描述相关参量(OWN = 1:owned by the DMA  OWN = 0:owned by the CPU)      **
    **参    数:   无                                                                                       ** 
    **返    回:   无                                                                                       **
    ******************************************************************************************************
    */
    void InitDescriptors(void)
    {
        uint32_t ui32Loop;
    
        // Initialize each of the receive descriptors.  
        for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
        {
            RxDescriptor[ui32Loop].ui32CtrlStatus   = 0;
            RxDescriptor[ui32Loop].ui32Count        = (DES1_RX_CTRL_CHAINED | (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));
            RxDescriptor[ui32Loop].pvBuffer1        = RxBuffer[ui32Loop];
            RxDescriptor[ui32Loop].DES3.pLink       = (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ? &RxDescriptor[0] : &RxDescriptor[ui32Loop + 1];
        }
        
        // Initialize each of the transmit descriptors.  Note that we leave the OWN bit clear here since we have not set up any transmissions yet.
        for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
        {
            TxDescriptor[ui32Loop].ui32CtrlStatus   = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS);
            TxDescriptor[ui32Loop].ui32Count        = (DES1_TX_CTRL_SADDR_INSERT | (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
            TxDescriptor[ui32Loop].pvBuffer1        = TxBuffer[ui32Loop];
            TxDescriptor[ui32Loop].DES3.pLink       = (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ? &TxDescriptor[0] : &TxDescriptor[ui32Loop + 1];
        }
    
        // Set the descriptor pointers in the hardware.
        EMACRxDMADescriptorListSet(EMAC0_BASE, RxDescriptor);
        EMACTxDMADescriptorListSet(EMAC0_BASE, TxDescriptor);
    
        // Start from the beginning of both descriptor chains. We actually set the transmit descriptor index to the last descriptor in the chain
        // since it will be incremented before use and this means the first transmission we perform will use the correct descriptor.
        RxDescIndex = 0;
        TxDescIndex = NUM_TX_DESCRIPTORS - 1;
        
        // Mark the first receive descriptor as available to the DMA to start the receive processing.
        RxDescriptor[RxDescIndex].ui32CtrlStatus |= DES0_RX_CTRL_OWN;
    }
    
    /*
    ******************************************************************************************************
    **函数名称: uint32_t PacketReceive(uint8_t *pui8Buf)                                                **
    **函数描述: 从DMA接收缓冲区读取一个数据包                                                            **
    **参    数:   pui8Buf-------数据包存储缓冲区指针                                                        **
    **返    回:   i32FrameLen---数据长度                                                                  **
    ******************************************************************************************************
    */
    uint32_t PacketReceive(uint8_t *pui8Buf)
    {
        uint32_t i32FrameLen, i32Loop;
    
        // Check the arguments.
        ASSERT(pui8Buf != 0);
    
        // By default, we assume we got a bad frame.
        i32FrameLen = 0;
    
        // Make sure that CPU own the receive descriptor. 
        if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN))
        {
            // We own the receive descriptor so check to see if it contains a valid frame.  Look for a descriptor error, 
            // indicating that the incoming packet was truncated or, if this is the last frame in a packet, the receive error bit.
            if(!(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_ERR))
            {
                // We have a valid frame so copy the content to the supplied buffer. First check that the "last descriptor" flag is set.
                // We sized the receive buffer such that it can always hold a valid frame so this flag should never be clear at this point but...
                if(RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_LAST_DESC)
                {
                    i32FrameLen = ((RxDescriptor[RxDescIndex].ui32CtrlStatus & DES0_RX_STAT_FRAME_LENGTH_M) >> DES0_RX_STAT_FRAME_LENGTH_S);
    
                    // Sanity check.
                    if(i32FrameLen > RX_BUFFER_SIZE)
                    {
                        i32FrameLen = RX_BUFFER_SIZE;
                    }
    
                    // Copy the data from the DMA receive buffer into the provided frame buffer.
                    for(i32Loop = 0; i32Loop < i32FrameLen; i32Loop++)
                    {
                        pui8Buf[i32Loop] = RxBuffer[RxDescIndex][i32Loop];
                    }
                }
            }
    
            // Move on to the next descriptor in the chain.
            RxDescIndex++;
            if(RxDescIndex == NUM_RX_DESCRIPTORS)
            {
                RxDescIndex = 0;
            }
    
            // Give this descriptor back to the DMA.
            RxDescriptor[RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;
        }
    
        // Return the Frame Length.
        return(i32FrameLen);
    }
    
    /*
    ******************************************************************************************************
    **函数名称: uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen)                           **
    **函数描述: 发送数据包                                                                               **
    **参    数:   pui8Buf-----待发送数据包缓冲区指针                                                     **
    **          i32BufLen---待发送数据包的长度                                                           **
    **返    回:   i32BufLen---实际发送数据的长度                                                           **
    ******************************************************************************************************
    */
    uint32_t PacketTransmit(uint8_t *pui8Buf, uint32_t i32BufLen)
    {
        uint32_t i32Loop;
    
        // Indicate that a packet is being sent.
        ETH_FLAG_TXPKT = 1;
    printf("ETH_FLAG_TXPKT = 1;\r\n");
        // Wait for the previous packet to be transmitted.
        while(TxDescriptor[TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN);
    printf("ETH_FLAG_TXPKT = 2;\r\n");
        // Sanity check.
        if(i32BufLen > TX_BUFFER_SIZE)
        {
            i32BufLen = TX_BUFFER_SIZE;
        }
    
        // Copy the packet data into the transmit buffer.
        for(i32Loop = 0; i32Loop < i32BufLen; i32Loop++)
        {
            TxBuffer[TxDescIndex][i32Loop] = pui8Buf[i32Loop];
            printf("pui8Buf[%d] = %02X\r\n", i32Loop, pui8Buf[i32Loop]);
        }
    
        // Move to the next descriptor.
        TxDescIndex++;
        if(TxDescIndex == NUM_TX_DESCRIPTORS)
        {
            TxDescIndex = 0;
        }
    
        // Fill in the packet size and tell the transmitter to start work.
        TxDescriptor[TxDescIndex].ui32Count         = (uint32_t)i32BufLen;
        TxDescriptor[TxDescIndex].ui32CtrlStatus    = ( DES0_TX_CTRL_LAST_SEG  | 
                                                        DES0_TX_CTRL_FIRST_SEG | 
                                                        DES0_TX_CTRL_INTERRUPT | 
                                                        DES0_TX_CTRL_IP_ALL_CKHSUMS | 
                                                        DES0_TX_CTRL_CHAINED | 
                                                        DES0_TX_CTRL_OWN);
    
        // Tell the DMA to reacquire the descriptor now that we've filled it in.
        EMACTxDMAPollDemand(EMAC0_BASE);
    printf("ETH_FLAG_TXPKT = 3;\r\n");
        // Return the number of bytes sent.
        return(i32BufLen);
    }
    
    /*
    ******************************************************************************************************
    **函数名称: void HAL_EMAC_Init(void)                                                                **
    **函数描述: 网口初始化                                                                               **
    **参    数:   无                                                                                       **
    **返    回:   无                                                                                       **
    ******************************************************************************************************
    */
    void HAL_EMAC_Init(void)
    {
        // PF0/PF1/PF4 are used for Ethernet LEDs.
        GPIOPinConfigure(GPIO_PF0_EN0LED0);
        GPIOPinConfigure(GPIO_PF4_EN0LED1);
        GPIOPinConfigure(GPIO_PF1_EN0LED2);
    
        GPIOPinTypeEthernetLED(GPIOF_AHB_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4);
        
        // Wait for the MAC to be ready.
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
        
        // Configure for use with the internal PHY.
        EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | EMAC_PHY_AN_100B_T_FULL_DUPLEX);
        
        // Reset the MAC.
        EMACReset(EMAC0_BASE);
        
        // Initialize the MAC and set the DMA mode.
        EMACInit(EMAC0_BASE, SystemCoreClock, EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0);
        
        // Set MAC configuration options.
        EMACConfigSet(EMAC0_BASE,
                     (EMAC_CONFIG_FULL_DUPLEX | 
                      EMAC_CONFIG_CHECKSUM_OFFLOAD |
                      EMAC_CONFIG_7BYTE_PREAMBLE | 
                      EMAC_CONFIG_IF_GAP_96BITS |
                      EMAC_CONFIG_USE_MACADDR0 |
                      EMAC_CONFIG_SA_FROM_DESCRIPTOR |
                      EMAC_CONFIG_BO_LIMIT_1024),
                     (EMAC_MODE_RX_STORE_FORWARD |
                      EMAC_MODE_TX_STORE_FORWARD |
                      EMAC_MODE_TX_THRESHOLD_64_BYTES |
                      EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
        
        // Initialize the Ethernet DMA descriptors.
        InitDescriptors();
        
        // Program the hardware with its MAC address (for filtering).
        EMACAddrSet(EMAC0_BASE, 0, Device.mac);
        
        // Wait for the link to become active.
        //while((EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0);
        
        // Set MAC filtering options.  We receive all broadcast and multicast packets along with those addressed specifically for us.
        EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR | EMAC_FRMFILTER_PASS_MULTICAST | EMAC_FRMFILTER_PASS_NO_CTRL));
    
        // Clear any pending interrupts.
        EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
        
        // Enable the Ethernet MAC transmitter and receiver.
        EMACTxEnable(EMAC0_BASE);
        EMACRxEnable(EMAC0_BASE);
        
        // Enable the Ethernet interrupt.
        IntEnable(INT_EMAC0);
        
        // Enable the Ethernet RX Packet interrupt source.
        EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT);
    }
    
    /*
    ******************************************************************************************************
    **函数名称: void ENET_IRQHandler(void)                                                              **
    **函数描述: 以太网中断服务程序                                                                       **
    **参    数:   无                                                                                       **
    **返    回:   无                                                                                       **
    ******************************************************************************************************
    */
    void ETH_Handler(void)
    {
        uint32_t IntStatus;
    
        // Read and Clear the interrupt.
        IntStatus = EMACIntStatus(EMAC0_BASE, true);
        MAP_EMACIntClear(EMAC0_BASE, IntStatus);
    
        // Check to see if an RX Interrupt has occurred.
        if(IntStatus & EMAC_INT_RECEIVE)
        {
            // Indicate that a packet has been received.
            ETH_FLAG_RXPKT = 1;
        }
    
        // Has the DMA finished transferring a packet to the transmitter?
        if(IntStatus & EMAC_INT_TRANSMIT)
        {
            // Indicate that a packet has been sent.
            ETH_FLAG_TXPKT = 0;
        }
    }
    
    /*
    ******************************************************************************************************
    **函数名称: void Config(void)                                                                       **
    **函数描述: 参数配置函数                                                                          **
    **参    数: 无                                                                                     **
    **返    回: 无                                                                                     **
    ******************************************************************************************************
    */
    void Config(void)
    {
    uint32_t ui32User0, ui32User1;
        
        FlashUserGet(&ui32User0, &ui32User1);
        if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
        {
            //
            // We should never get here.  This is an error if the MAC address has
            // not been programmed into the device.  Exit the program.
            // Let the user know there is no MAC address
            //
            printf("No MAC programmed!\n");
            while(1)
            {
            }
        }
        
        Device.mac[0] = ((ui32User0 >>  0) & 0xff);
        Device.mac[1] = ((ui32User0 >>  8) & 0xff);
        Device.mac[2] = ((ui32User0 >> 16) & 0xff);
        Device.mac[3] = ((ui32User1 >>  0) & 0xff);
        Device.mac[4] = ((ui32User1 >>  8) & 0xff);
        Device.mac[5] = ((ui32User1 >> 16) & 0xff);
        
        
        memcpy(Device.ip,   IP,   4);               //IP
        memcpy(Device.mark, MARK, 4);               //MARK
        memcpy(Device.gate, GATE, 4);               //GATEWAY
    }
    
    /*
    ******************************************************************************************************
    **函数名称: void APP_LWIP_Init(void)                                                                **
    **函数描述: 初始化LWIP所有相关信息                                                                   **
    **参    数:   无                                                                                       **
    **返    回:   无                                                                                       **
    ******************************************************************************************************
    */
    void APP_LWIP_Init(void)
    {
        Config();
        HAL_EMAC_Init();                                    //初始化EMAC.
        lwip_init();                                        //LwIP协议栈初始化.
    
        // add the network interface.
        netif_add(&my_netif, (ip4_addr_t *)&Device.ip, (ip4_addr_t *)&Device.mark, (ip4_addr_t *)&Device.gate, NULL, ethernetif_init, ethernet_input);
    
        // Registers the default network interface.
        netif_set_default(&my_netif);
    
        netif_set_up(&my_netif);
    
    
        
        //HTTP应用层初始化
        //httpd_init();                                     //初始化HTTP服务器监听端口.
        //httpd_cgi_ssi_init();                             //CGI、SSI相关初始化.
    
        //TCP应用层初始化
        //tcp_server_init();                                    //初始化TCP服务器.
        
        //UDP应用层初始化
        //udp_server_init();                                    //初始化UDP服务器.
    
    }

    ethernetif.c代码如下:


    /**
     * @file
     * Ethernet Interface Skeleton
     *
     */
    
    /*
     * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
     * All rights reserved. 
     * 
     * Redistribution and use in source and binary forms, with or without modification, 
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     * 3. The name of the author may not be used to endorse or promote products
     *    derived from this software without specific prior written permission. 
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
     * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
     * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
     * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
     * OF SUCH DAMAGE.
     *
     * This file is part of the lwIP TCP/IP stack.
     * 
     * Author: Adam Dunkels <adam@sics.se>
     *
     */
    
    /*
     * This file is a skeleton for developing Ethernet network interface
     * drivers for lwIP. Add code to the low_level functions and do a
     * search-and-replace for the word "ethernetif" to replace it with
     * something that better describes your network interface.
     */
    
    #include "lwip/opt.h"
    
    #if 1 /* don't build, this is only a skeleton, see previous comment */
    
    #include "lwip/def.h"
    #include "lwip/mem.h"
    #include "lwip/pbuf.h"
    #include "lwip/sys.h"
    #include <lwip/stats.h>
    #include <lwip/snmp.h>
    #include "netif/etharp.h"
    #include "netif/ppp/pppoe.h"
    
    #include "includes.h"       // add by eBoy---2012-10-20
    
    
    /* Define those to better describe your network interface. */
    #define IFNAME0 'e'
    #define IFNAME1 'n'
    
    /**
     * Helper struct to hold private data used to operate your ethernet interface.
     * Keeping the ethernet address of the MAC in this struct is not necessary
     * as it is already kept in the struct netif.
     * But this is only an example, anyway...
     */
    struct ethernetif {
      struct eth_addr *ethaddr;
      /* Add whatever per-interface state that is needed here. */
    };
    
    /* Forward declarations. */
    err_t  ethernetif_input(struct netif *netif);
    
    /**
     * In this function, the hardware should be initialized.
     * Called from ethernetif_init().
     *
     * @param netif the already initialized lwip network interface structure
     *        for this ethernetif
     */
    static void
    low_level_init(struct netif *netif)
    {
      //struct ethernetif *ethernetif = netif->state;
      
      /* set MAC hardware address length */
      netif->hwaddr_len = ETHARP_HWADDR_LEN;
    
      /* set MAC hardware address */
      netif->hwaddr[0] =  Device.mac[0];
      netif->hwaddr[1] =  Device.mac[1];
      netif->hwaddr[2] =  Device.mac[2];
      netif->hwaddr[3] =  Device.mac[3];
      netif->hwaddr[4] =  Device.mac[4];
      netif->hwaddr[5] =  Device.mac[5];
    
      /* maximum transfer unit */
      netif->mtu = 1500;
      
      /* device capabilities */
      /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
      netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
     
      /* Do whatever else is needed to initialize interface. */  
    }
    
    /**
     * This function should do the actual transmission of the packet. The packet is
     * contained in the pbuf that is passed to the function. This pbuf
     * might be chained.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
     * @return ERR_OK if the packet could be sent
     *         an err_t value if the packet couldn't be sent
     *
     * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
     *       strange results. You might consider waiting for space in the DMA queue
     *       to become availale since the stack doesn't retry to send a packet
     *       dropped because of memory failure (except for the TCP timers).
     */
    
    static err_t
    low_level_output(struct netif *netif, struct pbuf *p)
    {
      //struct ethernetif *ethernetif = netif->state;
      struct pbuf *q;
      u16_t len=0;
      u8_t  buffer[1536];
    
      for(q = p; q != NULL; q = q->next) {
        /* Send the data from the pbuf to the interface, one pbuf at a
           time. The size of the data in each pbuf is kept in the ->len
           variable. */
          memcpy((u8_t*)&buffer[len], (u8_t*)q->payload, q->len);
          len = len + q->len;
      }
      
      PacketTransmit(buffer, len);
    
      return ERR_OK;
    }
    
    /**
     * Should allocate a pbuf and transfer the bytes of the incoming
     * packet from the interface into the pbuf.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return a pbuf filled with the received packet (including MAC header)
     *         NULL on memory error
     */
    static struct pbuf *
    low_level_input(struct netif *netif)
    {
      //struct ethernetif *ethernetif = netif->state;
      struct pbuf *p, *q;
      u16_t len=0,i=0;
      u8_t  buffer[1536];
    
      /* Obtain the size of the packet and put it into the "len"
         variable. */
      len = PacketReceive(buffer);
    
      /* We allocate a pbuf chain of pbufs from the pool. */
      p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
      
      if (p != NULL) {
    
        /* We iterate over the pbuf chain until we have read the entire
         * packet into the pbuf. */
        for(q = p; q != NULL; q = q->next) {
          /* Read enough bytes to fill this pbuf in the chain. The
           * available data in the pbuf is given by the q->len
           * variable.
           * This does not necessarily have to be a memcpy, you can also preallocate
           * pbufs for a DMA-enabled MAC and after receiving truncate it to the
           * actually received size. In this case, ensure the tot_len member of the
           * pbuf is the sum of the chained pbuf len members.
           */
          memcpy((u8_t*)q->payload, (u8_t*)&buffer[i], q->len);
          i = i + q->len;
        }
       }
    
      return p;  
    }
    
    /**
     * This function should be called when a packet is ready to be read
     * from the interface. It uses the function low_level_input() that
     * should handle the actual reception of bytes from the network
     * interface. Then the type of the received packet is determined and
     * the appropriate input function is called.
     *
     * @param netif the lwip network interface structure for this ethernetif
     */
    err_t
    ethernetif_input(struct netif *netif)
    {
      //struct ethernetif *ethernetif = netif->state;
      struct pbuf *p;
      err_t err;
    
      /* move received packet into a new pbuf */
      p = low_level_input(netif);
    
      /* no packet could be read, silently ignore this */
      if (p == NULL) return ERR_MEM;
    
      err = netif->input(p, netif);
      if (err != ERR_OK)
      {
        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
        pbuf_free(p);
        p = NULL;
      }
    
      return err;
    }
    
    /**
     * Should be called at the beginning of the program to set up the
     * network interface. It calls the function low_level_init() to do the
     * actual setup of the hardware.
     *
     * This function should be passed as a parameter to netif_add().
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return ERR_OK if the loopif is initialized
     *         ERR_MEM if private data couldn't be allocated
     *         any other err_t on error
     */
    err_t
    ethernetif_init(struct netif *netif)
    {
      struct ethernetif *ethernetif;
    
      LWIP_ASSERT("netif != NULL", (netif != NULL));
        
      ethernetif = mem_malloc(sizeof(struct ethernetif));
      if (ethernetif == NULL) {
        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
        return ERR_MEM;
      }
    
    #if LWIP_NETIF_HOSTNAME
      /* Initialize interface hostname */
      netif->hostname = "lwip";
    #endif /* LWIP_NETIF_HOSTNAME */
    
      /*
       * Initialize the snmp variables and counters inside the struct netif.
       * The last argument should be replaced with your link speed, in units
       * of bits per second.
       */
      NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
    
      netif->state = ethernetif;
      netif->name[0] = IFNAME0;
      netif->name[1] = IFNAME1;
      /* We directly use etharp_output() here to save a function call.
       * You can instead declare your own function an call etharp_output()
       * from it if you have to do some checks before sending (e.g. if link
       * is available...) */
      netif->output = etharp_output;
      netif->linkoutput = low_level_output;
      
      ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
      
      /* initialize the hardware */
      low_level_init(netif);
    
      return ERR_OK;
    }
    
    #endif /* 0 */


    ping 192.168.1.88时,串口输出如下:



    通过串口打印的信息看,回复的是ARP帧,可电脑好像收不到,导致后面的ICMP一直Ping不通。

    求大神帮忙分析一下是什么问题~!谢谢!


  • 没有搞过,如果楼主成功了,希望分享下代码。