From 9620b0fc7fcb63d792e5b68e8c55e3c31b273811 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Mon, 12 Jun 2017 22:10:45 -0500 Subject: [PATCH] STM32 - fix bug were sockets stop receiving data The function _eth_arch_low_level_input() is meant to pass data into LWIP and to prepare the ethernet buffers to receive more data. If the LWIP heap is empty and the call to pbuf_alloc() in _eth_arch_low_level_input returns null, the ethernet receive buffers are not updated to receive data. Because of this the ethernet RX interrupt will not fire. Since the RX interrupt is the only thing that triggers a call to _eth_arch_low_level_input(), the receive buffers will never get cleared, and the device stops receiving data. To prevent this from happening, this patch ensures that the function _eth_arch_low_level_input() clears the receive buffers even if a new pbuf for the data couldn't be allocated. This issue can be reproduce by running the test "features-feature_lwip-tests-mbedmicro-net-udp_echo_parallel" and on the same machine running the below python script to flood the device with UDP broadcast packets: MY_IP = #ADD your local IP here from socket import * s = socket(AF_INET, SOCK_DGRAM) s.bind((MY_IP, 1234)) s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) for _ in range(1000): s.sendto("test data", ('255.255.255.255', 1234)) print("Message sent") --- .../lwip-eth/arch/TARGET_STM/stm32xx_emac.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/stm32xx_emac.c b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/stm32xx_emac.c index 5afb6fcacf..5d3319e446 100644 --- a/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/stm32xx_emac.c +++ b/features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_STM/stm32xx_emac.c @@ -305,20 +305,20 @@ static struct pbuf * _eth_arch_low_level_input(struct netif *netif) memcpy((uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy); bufferoffset = bufferoffset + byteslefttocopy; } - - /* Release descriptors to DMA */ - /* Point to first descriptor */ - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ - for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++) { - dmarxdesc->Status |= ETH_DMARXDESC_OWN; - dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr); - } - - /* Clear Segment_Count */ - EthHandle.RxFrameInfos.SegCount = 0; } + /* Release descriptors to DMA */ + /* Point to first descriptor */ + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++) { + dmarxdesc->Status |= ETH_DMARXDESC_OWN; + dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + EthHandle.RxFrameInfos.SegCount = 0; + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) { /* Clear RBUS ETHERNET DMA flag */