Skip to content

fix(stm32h7): poll MDIO completion in microseconds, plus two upstream mdio fixes - #414

Merged
dakejahl merged 3 commits into
px4_firmware_nuttx-12.12.0+from
dakejahl/stm32h7-mdio-poll
Sep 7, 2026
Merged

fix(stm32h7): poll MDIO completion in microseconds, plus two upstream mdio fixes#414
dakejahl merged 3 commits into
px4_firmware_nuttx-12.12.0+from
dakejahl/stm32h7-mdio-poll

Conversation

@dakejahl

@dakejahl dakejahl commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Backports three stm32_mdio.c fixes for STM32H7 ethernet: two already on apache master (private-structure use, RDA field in the Clause 22 write) and apache/nuttx#20067 (merged as 304cbb1), which replaces the 5 ms busy-wait between MDIO completion checks with 10 us polling.

Problem

Every PHY register access on H7 costs a 5 ms up_mdelay() because the transfer (~30 us) is never complete on the first check. stm32_phyinit() issues 6552 of them waiting for link-up, so on any H7 board booting without an ethernet cable (STM32H7_AUTONEG + NETINIT_MONITOR: ark fmu-v6s/v6x, px4 fmu-v6x, ...) netinit pins the core at ~44% for the first ~65 s, priority-inherited to 100, with the net lock held. The UDP MAVLink instance and any other socket user stalls until the link wait times out. Steady state after that is 0.4%, one 5 ms read per poll.

The other two commits are needed for the fix to cherry-pick cleanly and are real bugs: the lower-half cast reads timeout from the wrong object, and the C22 write put the PHY address in the register-address field.

Solution

Poll every 10 us with a 10 ms bound. Measured on ARK FMU-V6X (STM32H753, LAN8742A), no cable, top once every 2 s from power-on (shell up at ~12 s):

before after
netinit CPU, boot to 65 s 44% 1.6% for 2 s, then 0.003%
UDP MAVLink unblocked at ~65 s ~2 s

ppisa and others added 2 commits September 6, 2026 19:05
The struct stm32_mdio_bus_s aka g_stm32_mdio_bus
has not been referenced at all, because  mdio_register()
allocates its own structure. Then lower half drivers
receive only their respective part in mdio_read()
and mdio_write() because MDIO_WRITE/MDIO_READ provides
only d->lower to the specific lower level drivers.

Signed-off-by: Pavel Pisa <pisa@fel.cvut.cz>
(cherry picked from commit b6cb94a)
Use correct register

Signed-off-by: Luchian Mihai <luchiann.mihai@gmail.com>
(cherry picked from commit 85ad737)
@dakejahl
dakejahl requested a review from alexcekay September 7, 2026 01:09
@dakejahl
dakejahl marked this pull request as ready for review September 7, 2026 15:13
…t 5 ms steps

stm32_c22_read() and stm32_c22_write() waited for the MACMDIOAR busy bit
with up_mdelay(5) between checks. A Clause 22 frame takes about 30 us,
so the first check always sees the bus busy and every PHY register
access costs a 5 ms busy-wait, roughly 150 times the transfer.

stm32_phyinit() waits for link-up with PHY_RETRY_TIMEOUT (6552) MSR
reads. With no cable attached that is 33 s of CPU spent in
up_mdelay() inside ifup, with the network lock held: on an STM32H753
the netinit thread pinned the core at 44% for the first 65 s after
boot and every socket operation on other threads blocked until it gave
up. Before the MDIO bus refactor, stm32_phyread() polled the busy bit
in a tight loop.

Poll every 10 us instead, with the timeout expressed in microseconds so
the total bound stays at 10 ms, and report the timeout from the result
rather than the loop counter so a transfer that completes on the last
iteration is not logged as timed out.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

(cherry picked from commit 304cbb1)
@dakejahl
dakejahl force-pushed the dakejahl/stm32h7-mdio-poll branch from d3971c4 to fe4580c Compare September 7, 2026 15:13
@dakejahl
dakejahl merged commit 0288ea6 into px4_firmware_nuttx-12.12.0+ Sep 7, 2026
@dakejahl
dakejahl deleted the dakejahl/stm32h7-mdio-poll branch September 7, 2026 15:29
dakejahl added a commit to PX4/PX4-Autopilot that referenced this pull request Sep 7, 2026
Every PHY register access on STM32H7 spent 5 ms in up_mdelay(), so the
boot-time autonegotiation link wait ran netinit at 44% CPU for 65 s with
the net lock held whenever no ethernet cable was attached (PX4/NuttX#414,
apache/nuttx#20067). Also picks up the two upstream stm32_mdio fixes for
the lower-half cast and the Clause 22 write register field.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants