This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2851f1c09e6e45d667e0e3d0e220500a8543392a Author: Daniel P. Carvalho <[email protected]> AuthorDate: Sat Oct 3 19:14:04 2026 -0300 arch/mips/pic32mz: fix the Ethernet driver TX ring, RX buffers and MAC. - Close the TX descriptor ring on the last TX descriptor. It used CONFIG_PIC32MZ_ETH_NRXDESC, so with more RX than TX descriptors the DMA ran past the TX ring and stopped transmitting after two packets. - Decrement ETHSTAT.BUFCNT (ETHCON1.BUFCDEC) for each received descriptor that is processed. - Drop a received packet instead of asserting when no buffer is free to replace the one in the RX descriptor. - Program EMAC1SA0-2 with the MAC address assigned to the device, if any. The driver only read these registers, which are preloaded with a factory address on PIC32MZ EC/EF but reset to zero on PIC32MZ-W1. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Daniel P. Carvalho <[email protected]> --- arch/mips/src/pic32mz/pic32mz_ethernet.c | 84 +++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/arch/mips/src/pic32mz/pic32mz_ethernet.c b/arch/mips/src/pic32mz/pic32mz_ethernet.c index 0687d95e329..130d71bc528 100644 --- a/arch/mips/src/pic32mz/pic32mz_ethernet.c +++ b/arch/mips/src/pic32mz/pic32mz_ethernet.c @@ -393,6 +393,10 @@ uint8_t g_buffers[PIC32MZ_NBUFFERS * PIC32MZ_ALIGNED_BUFSIZE] static struct pic32mz_driver_s g_ethdrvr[CONFIG_PIC32MZ_NINTERFACES]; +/* All-zero MAC address: no address assigned to the device */ + +static const uint8_t g_zeromac[IFHWADDRLEN]; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -801,7 +805,7 @@ static inline void pic32mz_txdescinit(struct pic32mz_driver_s *priv) * creating a ring. */ - if (i == (CONFIG_PIC32MZ_ETH_NRXDESC - 1)) + if (i == (CONFIG_PIC32MZ_ETH_NTXDESC - 1)) { txdesc->nexted = PHYS_ADDR(g_txdesc); } @@ -1403,6 +1407,13 @@ static void pic32mz_rxdone(struct pic32mz_driver_s *priv) pic32mz_dumprxdesc(rxdesc, "RX Complete"); + /* The hardware increments ETHSTAT.BUFCNT for each descriptor that it + * fills; software decrements it once for each descriptor that it + * processes. + */ + + pic32mz_putreg(ETH_CON1_BUFCDEC, PIC32MZ_ETH_CON1SET); + /* Get the packet length */ priv->pd_dev.d_len = (rxdesc->rsv2 & RXDESC_RSV2_BYTECOUNT_MASK) >> @@ -1468,10 +1479,22 @@ static void pic32mz_rxdone(struct pic32mz_driver_s *priv) DEBUGASSERT(priv->pd_dev.d_buf != NULL); - /* Replace the buffer in the RX descriptor with a new one */ + /* Replace the buffer in the RX descriptor with a new one. If + * there is no free buffer, drop the packet and give the + * descriptor back to the hardware with its current buffer. + */ rxbuffer = pic32mz_allocbuffer(priv); - DEBUGASSERT(rxbuffer != NULL); + if (rxbuffer == NULL) + { + nwarn("WARNING: No free buffer, packet dropped\n"); + NETDEV_RXDROPPED(&priv->pd_dev); + priv->pd_dev.d_buf = NULL; + priv->pd_dev.d_len = 0; + pic32mz_rxreturn(rxdesc); + continue; + } + rxdesc->address = PHYS_ADDR(rxbuffer); /* And give the RX descriptor back to the hardware */ @@ -2192,37 +2215,41 @@ static int pic32mz_ifup(struct net_driver_s *dev) pic32mz_putreg(CONFIG_NET_ETH_PKTSIZE, PIC32MZ_EMAC1_MAXF); /* Configure the MAC station address in the EMAC1SA0, EMAC1SA1 and - * EMAC1SA2 registers (these registers are loaded at reset from the - * factory preprogrammed station address). + * EMAC1SA2 registers. On PIC32MZ EC/EF these registers are loaded at + * reset from the factory preprogrammed station address; on PIC32MZ-W1 + * they reset to zero. Use the address assigned to the device (e.g. with + * SIOCSIFHWADDR) if there is one, otherwise keep the factory address. */ -#if 0 - regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[5] << 8 | - (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[4]; - pic32mz_putreg(regval, PIC32MZ_EMAC1_SA0); + if (memcmp(priv->pd_dev.d_mac.ether.ether_addr_octet, g_zeromac, + sizeof(g_zeromac)) != 0) + { + regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[5] << 8 | + (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[4]; + pic32mz_putreg(regval, PIC32MZ_EMAC1_SA0); - regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[3] << 8 | - (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[2]; - pic32mz_putreg(regval, PIC32MZ_EMAC1_SA1); + regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[3] << 8 | + (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[2]; + pic32mz_putreg(regval, PIC32MZ_EMAC1_SA1); - regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[1] << 8 | - (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[0]; - pic32mz_putreg(regval, PIC32MZ_EMAC1_SA2); -#else - regval = pic32mz_getreg(PIC32MZ_EMAC1_SA0); - priv->pd_dev.d_mac.ether.ether_addr_octet[4] = (uint32_t)(regval & 0xff); - priv->pd_dev.d_mac.ether.ether_addr_octet[5] = (uint32_t)((regval >> 8) & - 0xff); + regval = (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[1] << 8 | + (uint32_t)priv->pd_dev.d_mac.ether.ether_addr_octet[0]; + pic32mz_putreg(regval, PIC32MZ_EMAC1_SA2); + } + else + { + regval = pic32mz_getreg(PIC32MZ_EMAC1_SA0); + priv->pd_dev.d_mac.ether.ether_addr_octet[4] = regval & 0xff; + priv->pd_dev.d_mac.ether.ether_addr_octet[5] = (regval >> 8) & 0xff; - regval = pic32mz_getreg(PIC32MZ_EMAC1_SA1); - priv->pd_dev.d_mac.ether.ether_addr_octet[2] = (uint32_t)(regval & 0xff); - priv->pd_dev.d_mac.ether.ether_addr_octet[3] = (uint32_t)((regval >> 8) & - 0xff); + regval = pic32mz_getreg(PIC32MZ_EMAC1_SA1); + priv->pd_dev.d_mac.ether.ether_addr_octet[2] = regval & 0xff; + priv->pd_dev.d_mac.ether.ether_addr_octet[3] = (regval >> 8) & 0xff; - regval = pic32mz_getreg(PIC32MZ_EMAC1_SA2); - priv->pd_dev.d_mac.ether.ether_addr_octet[0] = (uint32_t)(regval & 0xff); - priv->pd_dev.d_mac.ether.ether_addr_octet[1] = (uint32_t)((regval >> 8) & - 0xff); + regval = pic32mz_getreg(PIC32MZ_EMAC1_SA2); + priv->pd_dev.d_mac.ether.ether_addr_octet[0] = regval & 0xff; + priv->pd_dev.d_mac.ether.ether_addr_octet[1] = (regval >> 8) & 0xff; + } ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", dev->d_mac.ether.ether_addr_octet[0], @@ -2231,7 +2258,6 @@ static int pic32mz_ifup(struct net_driver_s *dev) dev->d_mac.ether.ether_addr_octet[3], dev->d_mac.ether.ether_addr_octet[4], dev->d_mac.ether.ether_addr_octet[5]); -#endif /* Continue Ethernet Controller Initialization ****************************/
