From 62aa3d103fef1d2c7c9bffe689ddde89420cad7a Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Wed, 29 Jul 2020 11:02:59 +0200 Subject: [PATCH] cpu/stm32/periph_eth: RX Timestamps --- cpu/stm32/periph/eth.c | 44 ++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/cpu/stm32/periph/eth.c b/cpu/stm32/periph/eth.c index 8b51995d43..fc83f3454b 100644 --- a/cpu/stm32/periph/eth.c +++ b/cpu/stm32/periph/eth.c @@ -32,6 +32,7 @@ #include "net/eui_provider.h" #include "net/netdev/eth.h" #include "periph/gpio.h" +#include "timex.h" #define ENABLE_DEBUG 0 #define ENABLE_DEBUG_VERBOSE 0 @@ -618,12 +619,12 @@ static void handle_lost_rx_irqs(void) } } -static int stm32_eth_recv(netdev_t *netdev, void *buf, size_t max_len, - void *info) +static int stm32_eth_recv(netdev_t *netdev, void *_buf, size_t max_len, + void *_info) { - (void)info; (void)netdev; - char *data = buf; + netdev_eth_rx_info_t *info = _info; + char *buf = _buf; /* Determine the size of received frame. The frame might span multiple * DMA buffers */ int size = get_rx_frame_size(); @@ -650,20 +651,29 @@ static int stm32_eth_recv(netdev_t *netdev, void *buf, size_t max_len, return -ENOBUFS; } + /* Fetch payload, collect RX timestamp from last descriptor if module periph_ptp is used, and + * hand DMA descriptors back to the DMA */ size_t remain = size; - while (remain) { - size_t chunk = MIN(remain, ETH_RX_BUFFER_SIZE); - memcpy(data, rx_curr->buffer_addr, chunk); - data += chunk; - remain -= chunk; - /* Hand over descriptor to DMA */ - rx_curr->status = RX_DESC_STAT_OWN; - rx_curr = rx_curr->desc_next; - } - - if ((size + ETHERNET_FCS_LEN - 1) % ETH_RX_BUFFER_SIZE < ETHERNET_FCS_LEN) { - /* one additional rx descriptor was needed only for the FCS, hand that - * back to the DMA as well */ + while (1) { + /* there can be one more DMA descriptor than needed for holding the Ethernet + * payload, as the 4 byte FCS will also be stored by DMA */ + if (remain) { + size_t chunk = MIN(remain, ETH_RX_BUFFER_SIZE); + memcpy(buf, rx_curr->buffer_addr, chunk); + buf += chunk; + remain -= chunk; + } + if (rx_curr->status & RX_DESC_STAT_LS) { + /* LS bit set --> reached last DMA descriptor of this frame */ + if (IS_USED(MODULE_PERIPH_PTP)) { + info->timestamp = rx_curr->ts_low; + info->timestamp += (uint64_t)rx_curr->ts_high * NS_PER_SEC; + info->flags |= NETDEV_ETH_RX_INFO_FLAG_TIMESTAMP; + } + rx_curr->status = RX_DESC_STAT_OWN; + rx_curr = rx_curr->desc_next; + break; + } rx_curr->status = RX_DESC_STAT_OWN; rx_curr = rx_curr->desc_next; }