1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

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
This commit is contained in:
Alain Péteut 2023-04-10 14:16:54 +02:00
parent 200c49dead
commit 226b8cff52

View File

@ -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);
}