Skip to content

Commit

Permalink
Merge pull request #20666 from benpicco/cpu/sam0_common-netdev_new_api
Browse files Browse the repository at this point in the history
sam0_eth: implement .confirm_send() to fix fragmented sending
  • Loading branch information
maribu authored May 24, 2024
2 parents ffc9a3c + d6d7d90 commit b55d79f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 12 deletions.
2 changes: 1 addition & 1 deletion cpu/sam0_common/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cpu/sam0_common/include/periph_cpu_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ typedef enum {
#endif

#ifndef ETH_TX_BUFFER_COUNT
#define ETH_TX_BUFFER_COUNT (4)
#define ETH_TX_BUFFER_COUNT (2)
#endif

#ifndef ETH_RX_BUFFER_SIZE
Expand Down
24 changes: 17 additions & 7 deletions cpu/sam0_common/periph/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
39 changes: 36 additions & 3 deletions cpu/sam0_common/sam0_eth/eth-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down

0 comments on commit b55d79f

Please sign in to comment.