LWIP使用问题,在STM32F407上移植FreeRTOS+LWIP后,利用ICMP实现PING外部设备的功能。如果将校验模式设为硬件校验方式,在PC上ping设备能ping通,但是设备pingPC则ping不通,如果使用软件校验方式则能双向ping通。求答疑解惑。
硬件平台:STM32F407ZGT6+LAN8720A
以下是使用硬件校验的代码:
lwipopts.h中Checksum配置
/*
--------------------------------------
---------- Checksum options ----------
--------------------------------------
*/
/*
* The STM32F4xx allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
* - To use this feature let the following define uncommented.
* - To disable it and process by CPU comment the the checksum.
*/
#define CHECKSUM_BY_HARDWARE
#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
#define CHECKSUM_GEN_ICMP 0
#else
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 1
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 1
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 1
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 1
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/
#define CHECKSUM_GEN_ICMP 1
#endif
STM32_ETH初始化代码:
/**
* @brief 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 err_t low_level_init(struct netif *netif)
{
uint8_t MACAddr[6] = { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };
HAL_ETH_DeInit(&EthHandle);
eth_phy_reeset();
ETH->DMABMR |= ETH_DMABMR_SR;
EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = &MACAddr[0];
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
EthHandle.Init.Speed = ETH_SPEED_100M;
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
//EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
EthHandle.Init.PhyAddress = LAN8720A_PHY_ADDRESS;
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
if (HAL_ETH_Init(&EthHandle) != HAL_OK)
{
logError("ETH init failed\r\n");
return -1;
}
/* Set netif link flag */
netif->flags |= NETIF_FLAG_LINK_UP;
/* Initialize Tx Descriptors list: Chain Mode */
HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
/* Initialize Rx Descriptors list: Chain Mode */
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
/* set netif MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
/* set netif MAC hardware address */
netif->hwaddr[0] = MAC_ADDR0;
netif->hwaddr[1] = MAC_ADDR1;
netif->hwaddr[2] = MAC_ADDR2;
netif->hwaddr[3] = MAC_ADDR3;
netif->hwaddr[4] = MAC_ADDR4;
netif->hwaddr[5] = MAC_ADDR5;
/* set netif maximum transfer unit */
// netif->mtu = 1500;
netif->mtu = ETH_MAX_PACKET_SIZE;
/* Accept broadcast address and ARP traffic */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
/* create a binary semaphore used for informing ethernetif of frame reception */
xSemaphore = xSemaphoreCreateBinary();
/* create the task that handles the ETH_MAC */
if (xTaskCreate(ethernetif_input, "EthInput", INTERFACE_THREAD_STACK_SIZE, netif, 10, NULL) != pdPASS)
{
logError("create Ethif task failed\r\n");
HAL_ETH_DeInit(&EthHandle);
return -1;
}
/* Enable MAC and DMA transmission and reception */
if (HAL_ETH_Start(&EthHandle) != HAL_OK)
{
logError("ETH start failed\r\n");
HAL_ETH_DeInit(&EthHandle);
return -1;
}
return 0;
}
以上配置在运行时,如果在PC端ping设备,没有问题,如果在设备上pingPC则超时。根据wireshark抓包的结果来看,PC端并未收到设备发送的ICMP报文,不知道是哪个环节出了问题。
如果将以上配置中CHECKSUM_BY_HARDWARE注释掉,LWIP使用软件校验,且ETH初始化时配置为EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE,设备和PC就能双向ping通了。
烦请了解的朋友解答一下出现上述问题的原因,不胜感激。
这个我遇到过,大概知道点,部分芯片有个小小的bug,就是ICMP要使用硬件校验和的话,需要把校验和预先填成0.
但是我遇到的情况和你的不一样,就是PC能抓到包,只是校验和错误。有一种可能是你的电脑网卡硬件上直接过滤掉了,如果网卡的高级设置里可以暂时关掉硬件校验和,暂时关掉一下试试看。