Add PIC32MZ EF bare-metal wolfIP port: clocks, UART2, wolfCrypt RNG, LAN8740 PHY#140
Add PIC32MZ EF bare-metal wolfIP port: clocks, UART2, wolfCrypt RNG, LAN8740 PHY#140dgarske wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new bare-metal PIC32MZ EF architecture port under src/port/pic32mz/, providing early bring-up infrastructure (clocks, UART console, timebase), a wolfCrypt hardware TRNG self-test configuration, and initial Ethernet EMAC MDIO + LAN8740 PHY link bring-up scaffolding.
Changes:
- Introduces PIC32MZ EF device configuration and 200 MHz clock/flash setup, plus a CP0-based millisecond timebase.
- Adds UART2 console support with XC32
printfretargeting and a standalone wolfCrypt RNG self-test usingWOLFSSL_PIC32MZ_RNG. - Adds initial EMAC MII-management (MDIO) routines and a MAC-agnostic LAN8740 PHY bring-up module, with a command-line XC32 Makefile build/flash flow.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/port/pic32mz/.gitignore | Ignores XC32/MDB build and flash artifacts for the new port. |
| src/port/pic32mz/Makefile | XC32-based command-line build/flash rules and wolfCrypt source inclusion for self-test. |
| src/port/pic32mz/board.h | Board- and clock-related constants (SYSCLK/PBCLK, UART pins, LEDs). |
| src/port/pic32mz/cache.h | MIPS KSEG address helpers intended for coherent DMA/EMAC access patterns. |
| src/port/pic32mz/clock_init.c | Flash wait-state and prefetch configuration for 200 MHz operation. |
| src/port/pic32mz/clock_init.h | Declares clock/flash init routine for the port. |
| src/port/pic32mz/device_config.c | PIC32MZ DEVCFG0-3 configuration word settings for the target board. |
| src/port/pic32mz/main.c | Bring-up application tying together clock, UART, timebase, RNG self-test, and PHY init. |
| src/port/pic32mz/phy_lan8740.c | LAN8740 PHY scanning/reset/autoneg/link reporting via MDIO function pointers. |
| src/port/pic32mz/phy_lan8740.h | PHY driver API and link-status struct definitions. |
| src/port/pic32mz/pic32mz_eth.c | EMAC module enable/reset and clause-22 MDIO read/write primitives. |
| src/port/pic32mz/pic32mz_eth.h | EMAC/MDIO init and accessor function declarations. |
| src/port/pic32mz/rng_selftest.c | Standalone RNG self-test using wolfCrypt WC_RNG + coarse sanity checks. |
| src/port/pic32mz/rng_selftest.h | Declares the RNG self-test entrypoint. |
| src/port/pic32mz/timebase.c | CP0 Count-derived 64-bit extended counter and millis()/delay_ms(). |
| src/port/pic32mz/timebase.h | Declares millis()/delay_ms() timebase API. |
| src/port/pic32mz/uart_console.c | UART2 init, TX/RX helpers, and XC32 _mon_putc retarget. |
| src/port/pic32mz/uart_console.h | UART console API declarations and usage notes. |
| src/port/pic32mz/user_settings.h | wolfCrypt feature selection for PIC32MZ RNG self-test (trimmed algorithms, no FS/sockets). |
| src/port/pic32mz/wolf_compat.c | wolfCrypt min/max shim functions for the bare-metal environment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e8db0cf to
4e409fe
Compare
…LAN8740 PHY, EMAC/RMII DMA, DHCP, TCP echo
| #pragma config FMIIEN = OFF /* RMII (LAN8740 PHY daughter board) */ | ||
| /* FETHIO selects the default (ON) vs alternate (OFF) Ethernet I/O pins; it | ||
| * also moves the RMII reference-clock input (EREFCLK: RB4 default / RJ11 | ||
| * alternate). Set to the board's routing for the 50 MHz PHY REFCLK. */ | ||
| #pragma config FETHIO = ON /* default Ethernet I/O pin set */ |
There was a problem hiding this comment.
device_config.c and pic32mz_eth.c disagree about which pin carries EREFCLK under FETHIO = ON
This comment says the default pin set puts the RMII reference clock on RB4, with RJ11 as the alternate:
/* FETHIO selects the default (ON) vs alternate (OFF) Ethernet I/O pins; it
* also moves the RMII reference-clock input (EREFCLK: RB4 default / RJ11
* alternate). Set to the board's routing for the 50 MHz PHY REFCLK. */
#pragma config FETHIO = ON /* default Ethernet I/O pin set */
But pic32mz_eth.c:362-366 states the opposite for the same FETHIO = ON setting, and the code acts on it:
/* On the 144-pin default (FETHIO=ON) pinout the 50 MHz
* reference clock EREFCLK is on RJ11, which is also AN4/C1INB: left
* analog, the MAC data path gets no clock, so TX stalls mid-frame and RX
* never clocks in (MDIO/link still work on their own MDC clock). */
ANSELJCLR = (1u << 11) | (1u << 8) | (1u << 9); /* RJ11 EREFCLK, RJ8/RJ9 ETXD0/1 */
Both cannot be right, and pic32mz_eth.c is the one the hardware validates: the PR reports working DHCP/ICMP/TCP echo, which by that same comment's reasoning is only possible if the ANSELJ11 clear is hitting the actual EREFCLK pin. If device_config.c were right, RB4 would still be analog and nothing would clock in. So the code is correct and this comment is wrong.
| /* LAN8740 link (fills speed/duplex even if the link is currently down). */ | ||
| ret = phy_lan8740_bringup(pic32mz_mdio_read, pic32mz_mdio_write, 5000u, |
There was a problem hiding this comment.
The comment's premise is false. phy_lan8740_bringup() zeroes speed_100 and full_duplex at entry (phy_lan8740.c:114-115) and only fills them from the SCSR read at phy_lan8740.c:158-178, which is reached after the link-up wait. The timeout path returns -2 at phy_lan8740.c:153, before that read — so on link-down both fields are still 0.
pic32mz_eth_init() then commits those zeros to hardware: EMAC1CFG2 without FULLDPLX, EMAC1IPGT = 0x12 (the half-duplex gap), and EMAC1SUPPbits.SPEEDRMII = 0 (10 Mbps RMII). main.c:203 prints "PHY link down at startup (check cable) - continuing", and the main loop at main.c:252-292 never re-reads the PHY or reconfigures the MAC. So a cable inserted after boot negotiates 100BASE-TX full duplex at the PHY while the MAC stays in 10 Mbps half-duplex RMII — link LED on, no traffic, and no path back short of a reset. The -2-is-non-fatal design and the "continuing" message both promise a recovery the code doesn't implement.
This is invisible to the hardware verification in the PR description, since all of it was done with the cable already connected.
Minimal fix — assume the case a later insert will almost certainly negotiate, so the MAC is at least configured correctly when the link does come up:
| /* LAN8740 link (fills speed/duplex even if the link is currently down). */ | |
| ret = phy_lan8740_bringup(pic32mz_mdio_read, pic32mz_mdio_write, 5000u, | |
| /* LAN8740 link. A -2 (link-down) result leaves speed/duplex unresolved, | |
| * and the MAC is configured once here and never revisited, so assume | |
| * 100BASE-TX full duplex: that is what a later cable insert will | |
| * negotiate in practice. */ | |
| ret = phy_lan8740_bringup(pic32mz_mdio_read, pic32mz_mdio_write, 5000u, | |
| &link); | |
| if (ret == -2) { | |
| link.speed_100 = 1; | |
| link.full_duplex = 1; | |
| } |
The complete fix is a pic32mz_eth_link_update() that re-reads BMSR/SCSR and re-applies EMAC1CFG2 / EMAC1IPGT / EMAC1SUPP.SPEEDRMII on change, called from the existing 1 Hz heartbeat in main.c:273. That also fixes the symmetric case this port has today: a cable unplugged and moved to a 10 Mbps switch is equally stuck. If you'd rather defer that, the honest interim is the snippet above plus dropping "check cable - continuing" from main.c:204, since recovery is reset-only.
Summary
New bare-metal wolfIP port for the Microchip PIC32MZ EF Starter Kit (PIC32MZ2048EFM144, MIPS32 M-class) with a LAN8740 PHY daughter board over RMII. This is a brand-new architecture for wolfIP (first MIPS/PIC32 target) and also verifies wolfCrypt's built-in hardware TRNG (
WOLFSSL_PIC32MZ_RNG). Early bring-up code is factored so a future wolfBoot PIC32MZ port can reuse it. All new code lives undersrc/port/pic32mz/.Features
make,xc32-gcc), matching the other wolfIP ports; no MPLAB X project required. Targets32MZ2048EFM144via the PIC32MZ-EF DFP,-O1(free XC32 tier).device_config.c,clock_init.c): DEVCFG0-3 config words (POSC EC 24 MHz -> SPLL 200 MHz SYSCLK, PBCLK2/PBCLK5 = 100 MHz, RMII selected), flash wait-states and prefetch. Isolated for wolfBoot reuse.uart_console.c): 115200 8N1 on RPB14 (U2TX) / RPG6 (U2RX) with PPS mapping, plus XC32_mon_putcretarget soprintfgoes to the serial console.timebase.c): 64-bitmillis()derived from the CP0 core-timer with software wrap extension; drives the wolfIP poll loop.rng_selftest.c,user_settings.h): exercisesWOLFSSL_PIC32MZ_RNG, generating and sanity-checking random blocks; a failing self-test is treated as fatal. Compiles the needed wolfcrypt sources directly from the sibling wolfssl checkout; keeps the crypto engine hash/AES acceleration off so SHA-256 (DRBG) stays software for this milestone.pic32mz_eth.c): EMAC + RMII + MII-management bring-up, clause-22 MDIO read/write primitives, PBCLK5 / PMD6 module enable before EMAC access, and full RX/TX DMA descriptor rings (coherent/uncached buffers) wired to the wolfIPpoll/senddevice ops.phy_lan8740.c): MAC-agnostic (function-pointer MDIO), scans for the PHY, resets, advertises 10/100 full/half, runs auto-negotiation, and reports resolved link speed/duplex. Distinguishes a non-fatal "link down" result from real MDIO/PHY errors.cache.h): KSEG0/KSEG1 and virtual/physical macros for coherent EMAC descriptor/buffer access.main.c): TRNG self-test, DHCP client, and a TCP echo server on port 7 (or a throughput server on port 9 in theSPEED_TESTbuild). Fatal bring-up failures (RNG, Ethernet, socket setup) halt the board rather than continue in a partial state.make flash): programs the hex via MDB (MPLAB X v6.30), erase-before-program, on the ICSP/debug header; the tool is overridable withMDB=/MDB_TOOL=. (Headlessipecmdcannot resolve device packs; MDB can.)Hardware verification status
Verified on hardware (PIC32MZ EF Starter Kit, LAN8740 over RMII, flashed via MPLAB ICD 5):
RNG self-test: PASS, distinct entropy each boot.