移植 lwip 2.0.2到stm32f407的

1、從官網下載lwip2.0.2壓縮包 

2、將解壓後的lwip中的代碼依次添加到工程中去

3、修改lwip_v2.0.2\src\netif 裏面的ethernetif.c源代碼文件:

 ethernetif.c是做初始化網卡、發送數據包、接收數據包等最底層的操作。

移植的主要工作就是將ethernetif.c中的low_level_init,low_level_output,low_level_input這三個函數(橙色標記爲修改部分)進行修改,以及定義相關的數據結構和宏。

 

static void low_level_init(struct netif *netif)
{
#ifdef CHECKSUM_BY_HARDWARE
  int i; 
#endif

#if 1   //在MylwIP_Init()中已經設置了MAC地址
  uint8_t macaddress[6]={IMT407G_MAC_ADDR};    

  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

//根據硬件mac地址,初始化netif結構體的硬件地址信息。該模塊mac地址可以由用戶定義。

  /* set MAC hardware address */
  netif->hwaddr[0] =  macaddress[0];
  netif->hwaddr[1] =  macaddress[1];
  netif->hwaddr[2] =  macaddress[2];
  netif->hwaddr[3] =  macaddress[3];
  netif->hwaddr[4] =  macaddress[4];
  netif->hwaddr[5] =  macaddress[5];

  
  /* initialize MAC address in ethernet MAC */ 
  ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); 
#endif
  /* 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;

  /* Initialize Tx Descriptors list: Chain Mode */
  ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
  /* Initialize Rx Descriptors list: Chain Mode  */
  ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
  
#ifdef CHECKSUM_BY_HARDWARE
  /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
  for(i=0; i<ETH_TXBUFNB; i++)
    {
      ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
    }
#endif

   /* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */

  /* Enable MAC and DMA transmission and reception */
  ETH_Start();

}

定義接收發送緩衝區uint8_t SendDataBuf[1500 + 20];uint8_t RecvDataBuf[1500 + 20];

緩衝區的長度爲mtu(1500)+ 地址 +類型 +CRC等(小於20)

low_level_output函數的主要功能將數據包發送出去

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
  struct pbuf *q;
  int framelength = 0;
  u8 *buffer =  (u8 *)(DMATxDescToSet->Buffer1Addr);
  
  /* copy frame from pbufs to driver buffers */
  for(q = p; q != NULL; q = q->next) 
  {

//將pbuf所指向鏈表的數據複製到數據緩衝區中
    memcpy((u8_t*)&buffer[framelength], q->payload, q->len);

    framelength = framelength + q->len;
  }
  
  /* Note: padding and CRC for transmitted frame 
     are automatically inserted by DMA */

  /* Prepare transmit descriptors to give to DMA*/ 
  ETH_Prepare_Transmit_Descriptors(framelength);

  return ERR_OK;
}

low_level_input該函數的主要功能是將接收到的數據並且分配到一個pbuf鏈表中

因爲該工程是輪詢的,在週期調用ethernetif_input的時候,ethernetif_input會調用該函數看是否有接收到的數據。

 

static struct pbuf * low_level_input(struct netif *netif)
{
  struct pbuf *p, *q;
  u16_t len;
  int l =0;
  FrameTypeDef frame;
  u8 *buffer;
  uint32_t i=0;
  __IO ETH_DMADESCTypeDef *DMARxNextDesc;
  
  
  p = NULL;
  
  /* get received frame */
  frame = ETH_Get_Received_Frame();
  
  /* Obtain the size of the packet and put it into the "len" variable. */
  len = frame.length;
  buffer = (u8 *)frame.buffer;
  
  /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
//申請與接收到數據大小相匹配的數據pbuf鏈表
  
  /* copy received frame to pbuf chain */
  if (p != NULL)
  {
    for (q = p; q != NULL; q = q->next)
    {
      memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
//將接收到的數據分配到p指向的pbuf鏈表中
      l = l + q->len;
    }    
  }

  
  /* Release descriptors to DMA */
  /* Check if frame with multiple DMA buffer segments */
  if (DMA_RX_FRAME_infos->Seg_Count > 1)
  {
    DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
  }
  else
  {
    DMARxNextDesc = frame.descriptor;
  }
  
  /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
  {  
    DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
    DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
  }
  
  /* Clear Segment_Count */
  DMA_RX_FRAME_infos->Seg_Count =0;
  
  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)  
  {
    /* Clear RBUS ETHERNET DMA flag */
    ETH->DMASR = ETH_DMASR_RBUS;
    /* Resume DMA reception */
    ETH->DMARPDR = 0;
  }
  return p;
}

 

參考:

https://blog.csdn.net/mcu_tian/article/details/49786375

https://blog.csdn.net/Firefly_cjd/article/details/79805977

https://blog.csdn.net/q361750389/article/details/52788005?locationNum=8&fps=1

https://blog.csdn.net/qq_26093511/article/details/52529275

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章