Add STM32 NUCLEO-F429ZI sample - #47
Conversation
|
Hello I've been wanting to try out ThreadX but didn't know where to start. So I though I could "Port" a sample to a new devboard as that could be helpful to someone. I also added some extras that I found useful in the tools folder, but I'm very unsure if they should be merged or not. |
Basically a copy of the STM32F676 implementation for the NUCLEO-F429ZI. It uses the same tasks and IO but for STM32F4 peripherals.
|
Hi @Jaxc. Thank you for this contribution! I somehow did not notice your PR before today. I will review it this week. Thanks again! |
|
Hello @fdesbiens Absolutely no worries! I also pushed my code a bit further and managed to get USBx up with a MSC device. I plan to push that too but it needs cleanup. Would you want that as a separate PR or should I amend this one? |
|
Thank you, @Jaxc. I would prefer a separate PR. I will aim to review this one today. |
fdesbiens
left a comment
There was a problem hiding this comment.
Hi @Jaxc — thanks again for this, and sorry for the slow start. I checked it out and built it locally, and the overall shape is good: the port is faithful, the console/ring-buffer thread is a nice touch, and it compiles with -Werror and no warnings once one path is fixed. A few things to sort out before I can merge.
Three things that need fixing
1. The build doesn't configure on Linux. In cmake/FindSTM32HAL.cmake, the find_path hint on line 70 is Drivers/stm32${STM32_FAMILY}xx_hal_Driver/Inc (lowercase stm32), but fetch_sdk.sh creates Drivers/STM32F4xx_hal_Driver. CMake bails with Could NOT find STM32HAL (missing: STM32HAL_INCLUDE_DIR). It only works on Windows because NTFS is case-insensitive. Could you align everything on STM32F4xx_HAL_Driver — both HINTS lines, fetch_sdk.sh, and fetch_sdk.ps1? That's the spelling both STM32F767ZI-Nucleo and NUCLEO_F401RE already use. With just that change the build finishes cleanly here (GCC 13.2, CMake 4.4, Ninja).
2. Wrong FPU for the part. cmake/arm-gcc-cortex-m4.cmake sets -mfpu=fpv5-d16, which is the Cortex-M7 unit — that got carried over from the F767 toolchain file. The F429's Cortex-M4F has FPv4-SP-D16, single precision only. GCC accepts -mcpu=cortex-m4 -mfpu=fpv5-d16 without complaint and will happily emit vdiv.f64, which the hardware doesn't implement. The current demo contains no double-precision instructions so it won't fault today, but readelf -A on the ELF does report Tag_FP_arch: FPv5/FP-D16 for ARMv8, and the first bit of double math anyone adds would hard-fault. Please use -mfpu=fpv4-sp-d16 — NUCLEO_F401RE already does.
3. The __HAL_UART_CLEAR_PEFLAG call in USART3_IRQHandler drops characters. This one is subtle and entirely the F7's fault. On the F7 that macro writes to ICR. On the F4 it expands to a read of SR followed by a read of DR — a destructive read. Since it runs unconditionally at the end of every interrupt, any byte that arrives between your RXNE read and that line gets consumed and thrown away, and no further interrupt fires for it. Rare at 115200, but real. I'd handle the error flags explicitly instead, e.g. only run the SR/DR clear sequence when ORE/FE/NE/PE is actually set, and push the recovered byte into the ring buffer.
Please retarget to dev
We take PRs against dev rather than main. That matters more than usual here: dev has a refactored F767 sample that moved the app into app/demos/<demo>/ with an ACTIVE_DEMO CMake cache variable and now carries a NetX Duo echo demo and a network station demo. So the layout you copied from main no longer exists upstream. Rebasing onto dev and matching that structure (app/demos/threadx_basic/main.c) would save us a painful reconciliation later — and it's the structure your USBX demo will want to slot into anyway.
Dead hardware init
ethernet_phy_init() and MX_USB_OTG_FS_PCD_Init() are both commented out in board_init(), MPU_Config() is declared but never defined or called, and ethernet_phy.c is compiled but unreachable. Its .RxDecripSection / .TxDecripSection descriptors aren't in the linker script either — that only goes unnoticed because --gc-sections discards them. For this PR I'd drop ethernet_phy.c, the eth component from find_package, and HAL_ETH_MODULE_ENABLED / HAL_PCD_MODULE_ENABLED from stm32f4xx_hal_conf.h, then bring Ethernet in properly when there's a demo that uses it. (Some of this is inherited from the F767 original — not your doing, but I'd rather not propagate it to a third board.)
On the tools/ folder — you asked, so:
- The
.iocI'd definitely keep. None of the other boards have one, and documenting how the pin configuration was produced is genuinely useful. Good precedent to set. - The Ozone
.jdebugI'm happy to take too. I checked and it only uses relative paths (./STM32F429.svd,../build/stm32f429_threadx.elf), so it's portable. Please add a line about it to the README so people know it's there. - The 2.1 MB
STM32F429.svdis the one I'd rather not commit. It's not reachable from any build, and most people get it from their IDE or ST's CMSIS pack. Could you fetch it infetch_sdk.shalongside the HAL and CMSIS clones instead? If that turns out to be awkward, I won't block the PR over it — but then it needs a NOTICE entry.
Which brings me to: NOTICE.md needs updating for the third-party files this PR vendors in. The SVD is ST, Apache-2.0. The .jdebug is SEGGER. And the CubeIDE-generated files committed under app/ — syscalls.c, sysmem.c, startup_stm32f429xx.s, system_stm32f4xx.c, main.h, and the linker script — all carry ST copyright with no accompanying licence text. Right now NOTICE only covers the components fetch_sdk.sh downloads.
Smaller things
board_init(): the comment aboveSystemClock_Config()still says "Configure the system clock to 216 MHz". It's 168.- README: the binary is
build/stm32f429_threadx.bin, notstm32F429_threadx.bin— the capital F will send Linux users looking for a file that isn't there. - README: 250 ms on plus 250 ms off is a 1 Hz blink (2 Hz toggle rate). Worth rewording.
MX_GPIO_Init()configures the user button asGPIO_MODE_IT_RISING, but the EXTI line is never enabled and the button is polled.GPIO_MODE_INPUTis what you want.int __io_getchar(void);is declared inmain.cand never used.- Three threads call
printfconcurrently and it funnels into an unguardedHAL_UART_Transmit, so output can interleave. Same in the F767 sample, so not a blocker — but aTX_MUTEXaround the console would be a real improvement if you feel like it. - Header attribution: you credited yourself in
main.candboard_init.cbut not inconsole.c,ethernet_phy.c/h,CMakeLists.txt, the cmake modules, or the scripts. Please add yourself to everything you touched. Also, new-file headers here should read "Eclipse ThreadX contributors" —console.csays "Eclipse Foundation", inherited from the original. - Commit style: our short descriptions start with a past-tense verb, so "Added the STM32 NUCLEO-F429ZI sample". And the PR body says F676 where it means F767. 😄
None of this is hard to fix and the foundation is solid. Looking forward to the USBX one as a separate PR.
fdesbiens
left a comment
There was a problem hiding this comment.
Marking this as changes-requested to reflect the state accurately — the details are in my review just above. The three blockers are the Linux build break in FindSTM32HAL.cmake, the -mfpu=fpv5-d16 Cortex-M7 flag on an M4, and the destructive __HAL_UART_CLEAR_PEFLAG read in USART3_IRQHandler. Retargeting onto dev is the other must-do. Happy to re-review as soon as you've had a pass at them.
Basically a copy of the STM32F676 implementation for the NUCLEO-F429ZI. It uses the same tasks and IO but for STM32F4 peripherals.