From 200c49deadcc9fa696534279364d9117032b6747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alain=20P=C3=A9teut?= Date: Mon, 10 Apr 2023 14:15:40 +0200 Subject: [PATCH 1/2] drivers/enc28j60: do not block in ISR ctx. --- drivers/enc28j60/enc28j60.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/enc28j60/enc28j60.c b/drivers/enc28j60/enc28j60.c index e8232008426a..fddf6e334e7c 100644 --- a/drivers/enc28j60/enc28j60.c +++ b/drivers/enc28j60/enc28j60.c @@ -249,9 +249,6 @@ static void mac_set(enc28j60_t *dev, uint8_t *mac) static void on_int(void *arg) { - /* disable global interrupt enable bit to avoid losing interrupts */ - cmd_bfc((enc28j60_t *)arg, REG_EIE, -1, EIE_INTIE); - netdev_trigger_event_isr(arg); } @@ -453,6 +450,8 @@ static int nd_init(netdev_t *netdev) static void nd_isr(netdev_t *netdev) { enc28j60_t *dev = (enc28j60_t *)netdev; + /* disable global interrupt enable bit to avoid losing interrupts */ + cmd_bfc(dev, REG_EIE, -1, EIE_INTIE); uint8_t eir = cmd_rcr(dev, REG_EIR, -1); while (eir != 0) { From 226b8cff52abe526d5bdb8bb61301872af903739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alain=20P=C3=A9teut?= Date: Mon, 10 Apr 2023 14:16:54 +0200 Subject: [PATCH 2/2] drivers/enc28j60: fix PKTIF issue. The PKTIF does not reliably report the status of pending packags. Apply the proposed workaround [1]. [1] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/Errata/80349c.pdf --- drivers/enc28j60/enc28j60.c | 41 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/enc28j60/enc28j60.c b/drivers/enc28j60/enc28j60.c index fddf6e334e7c..e5da1ad658f4 100644 --- a/drivers/enc28j60/enc28j60.c +++ b/drivers/enc28j60/enc28j60.c @@ -447,15 +447,38 @@ static int nd_init(netdev_t *netdev) return 0; } +/** + * PKTIF does not reliably report the status of pending packets. + * Checking EPKTCNT is the suggested workaround. + * Returns the number of pending packets. + */ +static int rx_interrupt(netdev_t *netdev) +{ + enc28j60_t *dev = (enc28j60_t *)netdev; + int pkg_cnt = cmd_rcr(dev, REG_B1_EPKTCNT, 1); + int ret = pkg_cnt; + while (pkg_cnt-- > 0) { + DEBUG("[enc28j60] isr: packet received\n"); + netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); + } + return ret; +} + static void nd_isr(netdev_t *netdev) { enc28j60_t *dev = (enc28j60_t *)netdev; + /* disable global interrupt enable bit to avoid losing interrupts */ cmd_bfc(dev, REG_EIE, -1, EIE_INTIE); - uint8_t eir = cmd_rcr(dev, REG_EIR, -1); - while (eir != 0) { + uint8_t eir; + int loop; + do { + loop = 0; + eir = cmd_rcr(dev, REG_EIR, -1); + if (eir & EIR_LINKIF) { + loop++; /* clear link state interrupt flag */ cmd_r_phy(dev, REG_PHY_PHIR); /* go and tell the new link layer state to upper layers */ @@ -468,27 +491,27 @@ static void nd_isr(netdev_t *netdev) netdev->event_callback(netdev, NETDEV_EVENT_LINK_DOWN); } } - if (eir & EIR_PKTIF) { - do { - DEBUG("[enc28j60] isr: packet received\n"); - netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); - } while (cmd_rcr(dev, REG_B1_EPKTCNT, 1) > 0); + if (rx_interrupt(netdev)) { + loop++; } if (eir & EIR_RXERIF) { + loop++; DEBUG("[enc28j60] isr: incoming packet dropped - RX buffer full\n"); cmd_bfc(dev, REG_EIR, -1, EIR_RXERIF); } if (eir & EIR_TXIF) { + loop++; DEBUG("[enc28j60] isr: packet transmitted\n"); netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); cmd_bfc(dev, REG_EIR, -1, EIR_TXIF); } if (eir & EIR_TXERIF) { + loop++; DEBUG("[enc28j60] isr: error during transmission - pkt dropped\n"); cmd_bfc(dev, REG_EIR, -1, EIR_TXERIF); } - eir = cmd_rcr(dev, REG_EIR, -1); - } + } while (loop); + /* enable global interrupt enable bit again */ cmd_bfs(dev, REG_EIE, -1, EIE_INTIE); }