From 4d1a5aa62cfd0fb0a4764c62c0182342c7d82d19 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 26 Apr 2024 18:30:59 +0200 Subject: [PATCH] cpu/sam0_common: eth: port to new netdev API --- cpu/sam0_common/Makefile.dep | 2 +- cpu/sam0_common/periph/eth.c | 24 ++++++++++++----- cpu/sam0_common/sam0_eth/eth-netdev.c | 39 ++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/cpu/sam0_common/Makefile.dep b/cpu/sam0_common/Makefile.dep index e284a37a48..199b1c9f5b 100644 --- a/cpu/sam0_common/Makefile.dep +++ b/cpu/sam0_common/Makefile.dep @@ -20,7 +20,7 @@ USEMODULE += sam0_common_periph ifneq (,$(filter sam0_eth,$(USEMODULE))) USEMODULE += iolist USEMODULE += netdev_eth - USEMODULE += netdev_legacy_api + USEMODULE += netdev_new_api USEMODULE += netopt FEATURES_REQUIRED += periph_eth FEATURES_REQUIRED += periph_gpio_irq diff --git a/cpu/sam0_common/periph/eth.c b/cpu/sam0_common/periph/eth.c index d1eb9dc615..812505db21 100644 --- a/cpu/sam0_common/periph/eth.c +++ b/cpu/sam0_common/periph/eth.c @@ -237,14 +237,16 @@ int sam0_eth_send(const struct iolist *iolist) } if (len == tx_len) { /* Clear and set the frame size */ - tx_curr->status &= ~DESC_TX_STATUS_LEN_MASK; - tx_curr->status |= (len & DESC_TX_STATUS_LEN_MASK); + tx_curr->status = (len & DESC_TX_STATUS_LEN_MASK) /* Indicate this is the last buffer and the frame is ready */ - tx_curr->status |= DESC_TX_STATUS_LAST_BUF | DESC_TX_STATUS_USED; + | DESC_TX_STATUS_LAST_BUF; /* Prepare next buffer index */ - tx_idx = (tx_idx < ETH_TX_BUFFER_COUNT-1) ? tx_idx+1 : 0; - __DSB(); - tx_curr->status &= ~DESC_TX_STATUS_USED; + if (++tx_idx == ETH_TX_BUFFER_COUNT) { + /* Set WRAP flag to indicate last buffer */ + tx_curr->status |= DESC_TX_STATUS_WRAP; + tx_idx = 0; + } + __DMB(); /* Start transmission */ GMAC->NCR.reg |= GMAC_NCR_TSTART; /* Set the next buffer */ @@ -256,6 +258,12 @@ int sam0_eth_send(const struct iolist *iolist) return len; } +unsigned _sam0_eth_get_last_len(void) +{ + unsigned idx = tx_idx ? tx_idx - 1 : ETH_TX_BUFFER_COUNT - 1; + return tx_desc[idx].status & DESC_TX_STATUS_LEN_MASK; +} + static int _try_receive(char* data, unsigned max_len, int block) { (void)block; @@ -382,8 +390,10 @@ int sam0_eth_init(void) GMAC->IDR.reg = 0xFFFFFFFF; /* clear flags */ GMAC->RSR.reg = GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA; + GMAC->TSR.reg = 0xFFFF; /* Enable needed interrupts */ - GMAC->IER.reg = GMAC_IER_RCOMP; + GMAC->IER.reg = GMAC_IER_RCOMP + | GMAC_IER_TCOMP | GMAC_IER_TFC | GMAC_IER_RLEX; GMAC->NCFGR.reg = GMAC_NCFGR_MTIHEN | GMAC_NCFGR_RXCOEN | GMAC_NCFGR_MAXFS | GMAC_NCFGR_CAF diff --git a/cpu/sam0_common/sam0_eth/eth-netdev.c b/cpu/sam0_common/sam0_eth/eth-netdev.c index 75f1af8693..3b1ce6166a 100644 --- a/cpu/sam0_common/sam0_eth/eth-netdev.c +++ b/cpu/sam0_common/sam0_eth/eth-netdev.c @@ -205,10 +205,36 @@ static int _sam0_eth_send(netdev_t *netdev, const iolist_t *iolist) /* TODO: use a specific netdev callback here ? */ return -EOVERFLOW; } - netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); return ret; } +static int _sam0_eth_confirm_send(netdev_t *netdev, void *info) +{ + (void)netdev; + (void)info; + + uint32_t tsr = GMAC->TSR.reg; + GMAC->TSR.reg = tsr; /* clear flags */ + + /* transmit is active */ + if (tsr & GMAC_TSR_TXGO) { + return -EAGAIN; + } + + /* Retry Limit Exceeded */ + if (tsr & GMAC_TSR_RLE) { + return -EBUSY; + } + + /* Transmit Frame Corruption, Collision Occurred */ + if (tsr & (GMAC_TSR_TFC | GMAC_TSR_COL)) { + return -EIO; + } + + extern unsigned _sam0_eth_get_last_len(void); + return _sam0_eth_get_last_len(); +} + static int _sam0_eth_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) { int res = -1; @@ -278,6 +304,7 @@ static int _sam0_eth_set(netdev_t *netdev, netopt_t opt, const void *val, size_t static const netdev_driver_t _sam0_eth_driver = { .send = _sam0_eth_send, + .confirm_send = _sam0_eth_confirm_send, .recv = _sam0_eth_recv, .init = _sam0_eth_init, .isr = _sam0_eth_isr, @@ -301,15 +328,21 @@ void isr_gmac(void) { uint32_t isr; uint32_t rsr; + netdev_t* netdev = _sam0_eth_dev.netdev; isr = GMAC->ISR.reg; rsr = GMAC->RSR.reg; - (void)isr; + + /* TX done, signal it to netdev */ + if (isr & GMAC_ISR_TCOMP) { + netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); + } /* New frame received, signal it to netdev */ if (rsr & GMAC_RSR_REC) { - netdev_trigger_event_isr(_sam0_eth_dev.netdev); + netdev_trigger_event_isr(netdev); } + /* Buffers Not Available, this can occur if there is a heavy traffic on the network. In this case, disable the GMAC reception, flush our internal buffers and re-enable the reception. This will drop