diff --git a/cpu/sam0_common/periph/eth.c b/cpu/sam0_common/periph/eth.c index 3b06ce21aa..c00c89b61e 100644 --- a/cpu/sam0_common/periph/eth.c +++ b/cpu/sam0_common/periph/eth.c @@ -323,6 +323,11 @@ int sam0_eth_receive_blocking(char *data, unsigned max_len) return _try_receive(data, max_len, 1); } +bool sam0_eth_has_queued_pkt(void) +{ + return _try_receive(NULL, 0, 0) > 0; +} + int sam0_eth_init(void) { /* Enable clocks */ diff --git a/cpu/sam0_common/sam0_eth/eth-netdev.c b/cpu/sam0_common/sam0_eth/eth-netdev.c index 48a1aa2fe8..6dbb605f06 100644 --- a/cpu/sam0_common/sam0_eth/eth-netdev.c +++ b/cpu/sam0_common/sam0_eth/eth-netdev.c @@ -40,6 +40,7 @@ extern void sam0_eth_poweron(void); extern void sam0_eth_poweroff(void); extern int sam0_eth_send(const struct iolist *iolist); extern int sam0_eth_receive_blocking(char *data, unsigned max_len); +extern bool sam0_eth_has_queued_pkt(void); extern void sam0_eth_set_mac(const eui48_t *mac); extern void sam0_eth_get_mac(char *out); extern void sam0_clear_rx_buffers(void); @@ -68,6 +69,12 @@ static int _sam0_eth_recv(netdev_t *netdev, void *buf, size_t len, void *info) (void)info; (void)netdev; unsigned ret = sam0_eth_receive_blocking((char *)buf, len); + + /* frame received, check if another frame is queued */ + if (buf && sam0_eth_has_queued_pkt()) { + netdev_trigger_event_isr(netdev); + } + return ret; } diff --git a/drivers/dose/dose.c b/drivers/dose/dose.c index 72ef94448b..cf17d128bf 100644 --- a/drivers/dose/dose.c +++ b/drivers/dose/dose.c @@ -431,6 +431,7 @@ static void _isr(netdev_t *netdev) static int _recv(netdev_t *dev, void *buf, size_t len, void *info) { + int res; dose_t *ctx = container_of(dev, dose_t, netdev); (void)info; @@ -446,10 +447,18 @@ static int _recv(netdev_t *dev, void *buf, size_t len, void *info) } if (crb_consume_chunk(&ctx->rb, buf, len)) { - return len; + res = len; } else { - return -1; + res = -1; } + + size_t dummy; + if (crb_get_chunk_size(&ctx->rb, &dummy)) { + DEBUG("dose: %u byte pkt in rx queue\n", (unsigned)dummy); + netdev_trigger_event_isr(&ctx->netdev); + } + + return res; } static uint8_t wait_for_state(dose_t *ctx, uint8_t state) diff --git a/drivers/include/slipdev.h b/drivers/include/slipdev.h index 9c9c6984b6..85a467aa4e 100644 --- a/drivers/include/slipdev.h +++ b/drivers/include/slipdev.h @@ -98,6 +98,8 @@ typedef struct { * @see [Device state definitions](@ref drivers_slipdev_states) */ uint8_t state; + uint8_t rx_queued; /**< pkt queued in inbuf */ + uint8_t rx_done; /**< pkt processed */ } slipdev_t; /** diff --git a/drivers/slipdev/slipdev.c b/drivers/slipdev/slipdev.c index 6cb7cd78a0..e120b8deb9 100644 --- a/drivers/slipdev/slipdev.c +++ b/drivers/slipdev/slipdev.c @@ -67,6 +67,7 @@ static void _slip_rx_cb(void *arg, uint8_t byte) check_end: if (byte == SLIPDEV_END) { if (dev->state == SLIPDEV_STATE_NET) { + dev->rx_queued++; netdev_trigger_event_isr(&dev->netdev); } dev->state = SLIPDEV_STATE_NONE; @@ -207,6 +208,11 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) return -ENOBUFS; } } while (byte != SLIPDEV_END); + + if (++dev->rx_done != dev->rx_queued) { + DEBUG("slipdev: pkt still in queue"); + netdev_trigger_event_isr(&dev->netdev); + } } return res; }