@@ -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+
450467static 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