Skip to content

Commit 226b8cf

Browse files
committed
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
1 parent 200c49d commit 226b8cf

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

drivers/enc28j60/enc28j60.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -447,15 +447,38 @@ static int nd_init(netdev_t *netdev)
447447
return 0;
448448
}
449449

450+
/**
451+
* PKTIF does not reliably report the status of pending packets.
452+
* Checking EPKTCNT is the suggested workaround.
453+
* Returns the number of pending packets.
454+
*/
455+
static int rx_interrupt(netdev_t *netdev)
456+
{
457+
enc28j60_t *dev = (enc28j60_t *)netdev;
458+
int pkg_cnt = cmd_rcr(dev, REG_B1_EPKTCNT, 1);
459+
int ret = pkg_cnt;
460+
while (pkg_cnt-- > 0) {
461+
DEBUG("[enc28j60] isr: packet received\n");
462+
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
463+
}
464+
return ret;
465+
}
466+
450467
static void nd_isr(netdev_t *netdev)
451468
{
452469
enc28j60_t *dev = (enc28j60_t *)netdev;
470+
453471
/* disable global interrupt enable bit to avoid losing interrupts */
454472
cmd_bfc(dev, REG_EIE, -1, EIE_INTIE);
455-
uint8_t eir = cmd_rcr(dev, REG_EIR, -1);
456473

457-
while (eir != 0) {
474+
uint8_t eir;
475+
int loop;
476+
do {
477+
loop = 0;
478+
eir = cmd_rcr(dev, REG_EIR, -1);
479+
458480
if (eir & EIR_LINKIF) {
481+
loop++;
459482
/* clear link state interrupt flag */
460483
cmd_r_phy(dev, REG_PHY_PHIR);
461484
/* go and tell the new link layer state to upper layers */
@@ -468,27 +491,27 @@ static void nd_isr(netdev_t *netdev)
468491
netdev->event_callback(netdev, NETDEV_EVENT_LINK_DOWN);
469492
}
470493
}
471-
if (eir & EIR_PKTIF) {
472-
do {
473-
DEBUG("[enc28j60] isr: packet received\n");
474-
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
475-
} while (cmd_rcr(dev, REG_B1_EPKTCNT, 1) > 0);
494+
if (rx_interrupt(netdev)) {
495+
loop++;
476496
}
477497
if (eir & EIR_RXERIF) {
498+
loop++;
478499
DEBUG("[enc28j60] isr: incoming packet dropped - RX buffer full\n");
479500
cmd_bfc(dev, REG_EIR, -1, EIR_RXERIF);
480501
}
481502
if (eir & EIR_TXIF) {
503+
loop++;
482504
DEBUG("[enc28j60] isr: packet transmitted\n");
483505
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
484506
cmd_bfc(dev, REG_EIR, -1, EIR_TXIF);
485507
}
486508
if (eir & EIR_TXERIF) {
509+
loop++;
487510
DEBUG("[enc28j60] isr: error during transmission - pkt dropped\n");
488511
cmd_bfc(dev, REG_EIR, -1, EIR_TXERIF);
489512
}
490-
eir = cmd_rcr(dev, REG_EIR, -1);
491-
}
513+
} while (loop);
514+
492515
/* enable global interrupt enable bit again */
493516
cmd_bfs(dev, REG_EIE, -1, EIE_INTIE);
494517
}

0 commit comments

Comments
 (0)