Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sam0_eth: implement .confirm_send() to fix fragmented sending #20666

Merged
merged 2 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -78,8 +78,8 @@
/* GMAC buffer descriptors */
#define GMAC_DESC_ALIGNMENT 8
#define GMAC_BUF_ALIGNMENT 32
static struct eth_buf_desc rx_desc[ETH_RX_BUFFER_COUNT] __attribute__((aligned(GMAC_DESC_ALIGNMENT)));

Check warning on line 81 in cpu/sam0_common/periph/eth.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
static struct eth_buf_desc tx_desc[ETH_TX_BUFFER_COUNT] __attribute__((aligned(GMAC_DESC_ALIGNMENT)));

Check warning on line 82 in cpu/sam0_common/periph/eth.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

static struct eth_buf_desc *rx_curr;
static struct eth_buf_desc *tx_curr;
Expand All @@ -89,8 +89,8 @@
static uint8_t tx_idx;
static uint8_t rx_idx;

static uint8_t rx_buf[ETH_RX_BUFFER_COUNT][ETH_RX_BUFFER_SIZE] __attribute__((aligned(GMAC_BUF_ALIGNMENT)));

Check warning on line 92 in cpu/sam0_common/periph/eth.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
static uint8_t tx_buf[ETH_TX_BUFFER_COUNT][ETH_TX_BUFFER_SIZE] __attribute__((aligned(GMAC_BUF_ALIGNMENT)));

Check warning on line 93 in cpu/sam0_common/periph/eth.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
extern sam0_eth_netdev_t _sam0_eth_dev;

static bool _is_sleeping;
Expand Down Expand Up @@ -237,14 +237,16 @@
}
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 @@
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 @@
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
Loading