!reorganize and unify STM32 ports - #19004
Conversation
|
It would be good to pinging everyone who uses stm32 with nuttx |
08fef3a to
65180d0
Compare
|
I will port it to 13.0 |
|
FYI to all people who have contributed to stm32 recently or I know that in the past they were interested in stm32 with nuttx. This PR will be a breaking change for most stm32 users. For those who are not interested in nuttx - sorry for the pinging :) In short, the goal of this PR is simple: unification of STM32 ports. No more unnecessary code duplication, incompatible Kconfig options and arch specific API. Ultimately, maintaining the code, applying changes, and adding new stm32 ports should be easier. However, this requires a hard breaking change that unifies and standardizes many things. The changes in this PR are the first step that contains most of the necessary breaking changes and these changes should be part of the upcoming release 13.0. With this PR all architecture API is unified and uses @alexcekay @ImBonkers @patrickelectric @csanchezdll @cjj66619 @dlizewski @shizacat @ppisa @pbarada @neilberkman @matiamic @vrmay23 @kywwilson11 @zdebanos @rzsa @davids5 @antmerlino @fjpanag @hartmannathan @michi-jung @juniskane @onegray @mlyszczek @stbenn @daniel-p-carvalho @rcsim |
|
Hi @raiden00pl In the summary of changes you wrote:
That is an excellent idea, but may I ask where you get the IP core versions from? When I asked an FAE from STMicroelectronics I was told that they do not publish the IP core version number per STM32 type. Thanks! |
|
This is a huge change and I will need some time to dig deep in and understand all the consequences. Just some initial thoughts.
So far I am sceptical towards this. One of the greatest NuttX design characteristics is the simplicity of source code and its arch section. Having a directory with common drivers with various compile time or runtime conditions deciding what code should be run breaks this simplicity. Yes, the current approach can bring some duplicity, but I still think it's a better approach. I would cite NuttX principles here: We need to really consider this, because the architectural design is what makes NuttX accessible. It's super easy to explain someone the driver's organization and the relation between boards and arch section. You just call
This on the other hand is something I agree with. I will need to take a detailed look, but I like the idea BSPs would serve mainly for pin definitions and would call the common init functions. After all, these functions are nothing more than arch init call and character device driver registration.
+1 this is great, searching in or editing one large Kconfig file is a pain. Maybe I would just move all those |
|
@michi-jung This is the hardest part, it has to be done by ourself. I used to do it manually, now the comparison can be easily automated with LLM. ChibiOS might provide some guidance: https://github.com/ChibiOS/ChibiOS/tree/master/os/hal/ports/STM32/LLD |
@michallenc Some code duplication makes sense. Code duplication across ~20 families and all posbile peripherals is pointless and difficult to maintain, especially when IP core implementations are shared between families. The problem here is that ST doesn't provide this information in an easy and readable way. Therefore, we can use ChibiOS whose author is or was an ST employee: https://github.com/ChibiOS/ChibiOS/tree/master/os/hal/ports/STM32/LLD
That's why documentation was created that directly indicates which IP core is used by which family. Regarding the STM32L4 - this port was created based on the principle that "code duplication is not a bad thing." Currently, this code has drifted from the rest of the ports to the point that it's the worst to generalize, and it uses essentially the same peripherals as other STM32 M4s. If we're duplicating code, we should duplicate it for all families, not as currently, where some are done this way, some are done that way ( |
65180d0 to
50a8628
Compare
|
It appears that CODEOWNERS is still keeping |
0413304 to
319feeb
Compare
hartmannathan
left a comment
There was a problem hiding this comment.
Hi, @raiden00pl thanks for taking this HUGE task upon yourself! I have sometimes been frustrated by the stm32 support being disjoint because of the different families being treated as different archs. This is a substantial change so I just want to kindly ask you to bear with me, because it will take me some time to review and test.
Yes, although STM doesn't document the actual version numbers of the peripheral IP blocks, we can ascertain this information based on the functionality they expose via registers and register bits. We can think of the registers and bits as the API of the peripherals. If the APIs match, we can consider the peripherals to be the same version. It's possible that the register addresses may be different, or that the bits within the register might be in a different position or order. So we might need some kind of "fuzzy matching". |
@raiden00pl, I am an AI skeptic. :-) Out of curiosity, would you be willing to share the prompts you used? It could be a blog post or something like that, to document how the changes were made as well as a learning resource for others who are trying to wrap their heads around this new way of working. |
|
How can I support with testing stm32h7 and F7 family?
…On Mon, Jun 1, 2026, 20:31 hartmannathan ***@***.***> wrote:
*hartmannathan* left a comment (apache/nuttx#19004)
<#19004 (comment)>
For all AI skeptics here - this PR was created with AI assistance and
burned hundreds of dollars worth of tokens. There is no other way to do it,
doing it manually is unrealistic, especially if you do it alone and for
free :) This PR doesn't add new code, it only organizes the old code, so
the code license remains the same as the original code
@raiden00pl <https://github.com/raiden00pl>, I am an AI skeptic. :-) Out
of curiosity, would you be willing to share the prompts you used? It could
be a blog post or something like that, to document how the changes were
made as well as a learning resource for others who are trying to wrap their
heads around this new way of working.
—
Reply to this email directly, view it on GitHub
<#19004?email_source=notifications&email_token=BO3QXU27YGTA4RXDT3EMOIL45XDXXA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINJZGUZTSMJZGA42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4595391909>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BO3QXU7XKYUTKHVIXIQ4ORL45XDXXAVCNFSM6AAAAACZUL6Y4GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DKOJVGM4TCOJQHE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
@hartmannathan I had an idea and plan for this reorganisation for years in my private notes, but it was not possible to do it manually without investing months of work. This wasn't a task that could be solved with a few prompts. The AI has too small context for this and isn't able to think outside the box very well. AI was used here more like an "intelligent tool" for things that I would have had to do manually. I don't have a single master prompt but used many simple prompts in an interactive workflow. I just instructed AI how I would do it step by step, like: "rename all public STM32 arch API to use common prefix stm32_", "move all stm32f0l0g0 files to common/stm32 and rename them to use the m0 suffix", "build set of configuration after each step" and so on. In fact, the order of commits exactly reflects my plan from the beginning. With such a huge change, keeping git history clean manually is a really big challenge, but for AI this is a really simple job. Moving files, fixups, squashing commits, and resolving conflicts is something that takes hours for a human, but can be easily done by AI. There were more issues that AI was not able to solve without manual intervention, like optimizing complex dependencies in Kconfig or even merge similar header files. There are still many complex conditions in Kconfig that must be simplified, but this is work for a human and careful analysis; AI has no idea how to properly solve it. |
|
@vrmay23 Any compilation of externally maintained boards and configurations will be useful. Upstream configurations should be OK now (CI pass), but upstream boards don't provide full coverage for stm32 architectures features, so the more out-of-tree configurations we compile, the greater the certainty that there will be no regressions. F7 and H7 have no functional changes, so if the code compiles - it should work. Unless some Kconfig option was not migrated correctly - with such a big change there's always a chance of that |
I agree the support for STM32 is quite messy and STM doesn't make it easy with their naming convention. We don't need duplicate implementations for f1, f2, f3 and so on though. These can be in one common folder, if the chips are the same (or with really little changes). We also have imxrt1060 and imxrt1170 in common But with this change, we would not only mix different IP core implementations in one directory but also different Cortex versions if I understand it correctly. And this is something I think we should duplicate. From my point of view the unification abandons the way we wrote the code for many years and I am afraid we open a Pandora box leading to more messy and unclear code. It also forces us to assign IP core versions to chips - yes, we can automate it by relying on 3rd party project which may end in a year or two or on LLM, which is even worse, because we can't trust that thing. So we have to do it manually by comparing registers and hoping we got it right. But that's a minor issue we can handle. |
7e59a65 to
a265c0a
Compare
Drop the L4 1-Wire copy and build the shared common/stm32/stm32_1wire_m3m4_v1.c for L4. L4's USART is the standard V3 IP, so make its headers follow the same conventions the common families already use: alias the legacy SR status names onto ISR (as stm32_uart_v3.h does) and add the canonical APB1ENR clock-enable aliases (as the G4 RCC header does). The shared driver then needs no per-chip special-casing. Signed-off-by: raiden00pl <raiden00@railab.me>
Merge the per-family LSI oscillator drivers into a single core-agnostic common/stm32/stm32_lsi.c. To let a common/stm32 driver resolve RCC register definitions for every family without a central chip enumeration, the common/stm32/hardware/stm32_rcc.h dispatcher is removed and each family now provides its own hardware/stm32_rcc.h. Signed-off-by: raiden00pl <raiden00@railab.me>
Collapse the per-IP and per-family STM32 timer drivers into a single
implementation under arch/arm/src/common/stm32 shared by all 18 families
(M0, M3/M4, and the formerly self-contained F7/H7/H5/L4/L5/U5/
WL5/WB chips).
This step allows you to unify all other drivers that depend on stm32_tim.
Changes for timer drivers:
- stm32_tim_m3m4_v1v2v3.c -> common/stm32/stm32_tim.c (single driver) and
stm32_tim_m0_v1_lowerhalf.c -> common/stm32/stm32_tim_lowerhalf.c.
- Delete stm32_tim_m0_v1.{c,h}, stm32_tim_m3m4_v1v2v3.h and the per-family
drivers/headers; M0 now uses the same driver as everyone else.
- Build it from the common build system with a single gate
(CONFIG_STM32_TIM); no chip Make.defs/CMakeLists lists it.
- Per-family RCC clock-enable register/bit differences are handled by
define aliases in common/stm32/stm32_tim_clk.h.
WB register unification:
- Delete arch/arm/src/stm32wb/hardware/stm32wb_tim.h (non-standard TIMn_*
names). WB selects STM32_HAVE_IP_TIMERS_M3M4_V2 and uses the common
GTIM_*/ATIM_* register header like every other M3/M4 family.
Boards reach the common timer header via the existing STM32_COMMON_SRCDIR
pattern in boards/arm/<family>/common/Makefile (added for WB).
The per-family/per-IP timer drivers and headers (stm32_tim_m0_v1.*,
stm32_tim_m3m4_v1v2v3.*, <chip>/stm32_tim.*, and
stm32wb/hardware/stm32wb_tim.h) are removed; include the common
arch/arm/src/common/stm32/stm32_tim.h instead.
Signed-off-by: raiden00pl <raiden00@railab.me>
Merge the per-IP and per-family free-running timer wrappers into a single
common/stm32/stm32_freerun.c, following the timer-driver unification.
- Rename stm32_freerun_m3m4_v1.c -> common/stm32/stm32_freerun.c (the most
complete variant: CONFIG_CLOCK_TIMEKEEPING handling, timer-width based
period, GTIM_SR_UIF/GTIM_DIER_UIE).
- Delete the stm32l4_freerun.{c,h} and stm32wb_freerun.{c,h} copies
Signed-off-by: raiden00pl <raiden00@railab.me>
Merge the per-IP and per-family one-shot timer wrappers (driver + lower-half)
into a single common/stm32/stm32_oneshot.c and stm32_oneshot_lowerhalf.c,
following the timer-driver and free-run unification.
- Rename stm32_oneshot_m3m4_v1{,_lowerhalf}.c -> common/stm32/stm32_oneshot
{,_lowerhalf}.c (the most complete variant: full counter/period cancel
logic).
- Delete the stm32h7/stm32_oneshot*, stm32l4_oneshot* and stm32wb_oneshot*
copies
Signed-off-by: raiden00pl <raiden00@railab.me>
…ilies The TIM1 and TIM8 interrupt vectors are the same interrupts on every family, but were named inconsistently: - 21 families: STM32_IRQ_TIM1UP / TIM1BRK / TIM1TRGCOM / TIM1CC - H5/L5/U5/N6: STM32_IRQ_TIM1_UP / _BRK / _TRG_COM / _CC - Cortex-M0 (C0/F0/G0): combined STM32_IRQ_TIM1_BRK (BRK_UP_TRG_COM) Standardize on the majority no-underscore form so a driver can refer to e.g. STM32_IRQ_TIM1UP on any family. Signed-off-by: raiden00pl <raiden00@railab.me>
Merge the per-IP (m0_v1, m3m4_v1v2v3) and per-family (f7/h7/l4) quadrature encoder drivers into a single common/stm32/stm32_qencoder.c, generalized for every STM32 family: - RCC clock-enable and reset use the common stm32_tim_clk.h aliases instead of per-chip register blocks. - 16/32-bit timer width is selected via STM32_HAVE_TIM2_32BITS / STM32_HAVE_TIM5_32BITS instead of per-chip-line #ifdefs. - The TIM1/TIM8 update interrupt uses the unified STM32_IRQ_TIM1UP / TIM8UP names (no per-family fallback). - GPIO input-float configuration is F1 vs. every other family. Signed-off-by: raiden00pl <raiden00@railab.me>
…config files Replace STM32_COMMON_* composite symbols with capability flags in Kconfig.memory, Kconfig.sai, Kconfig.dfsdm, Kconfig.i2c, Kconfig.ltdc and Kconfig.dma: - STM32_COMMON_SRAM2_OPTIONS -> STM32_HAVE_SRAM2_HEAP; the STM32_SRAM2_INIT select condition folds away because the U5 leg of the new flag already requires STM32_SRAM2 - SAI PLL options -> STM32_HAVE_SAI1PLL / STM32_HAVE_SAI2PLL - DFSDM filter options -> STM32_HAVE_IP_DFSDM_V1 - I2C v1-only options (I2C_ALT, DUTY16_9) -> STM32_HAVE_IP_I2C_M3M4_V1; this drops F37x/G4 from the visibility set, which select the I2C v2 IP and never build the v1 driver these options belong to - LTDC_REGDEBUG -> STM32_HAVE_IP_LTDC_M3M4_V1 / new STM32_HAVE_IP_LTDC_M7_V1; LTDC_USE_DSI composite dropped as DSIHOST is only selectable on F7 - STM32_DMACAPABLE -> new STM32_HAVE_DMACAPABLE driver-feature flag; ASSUME_CACHE_ALIGNED composite dropped as ARMV7M_DCACHE already implies F7/H7 within STM32 Verified .config equivalence with olddefconfig on F3/F4/G4/F7/H7/H5/ L4/U5/WB/WL5 boards: only the new capability symbols appear.
….eth - legacy-only PTP/enhanced-descriptor options -> existing STM32_HAVE_IP_ETHMAC_M3M4_V1 (selected by all legacy families with ETHMAC) - H7/H5 descriptor-count and NO_PHY options -> new STM32_HAVE_IP_ETHMAC_V2 (the newer Synopsys MAC shared by H7/H5) - MII/RMII MCO1/MCO2 clock options -> new STM32_HAVE_MCO1/STM32_HAVE_MCO2 hardware-capability flags - STM32_PHYADDR default inverted to key off STM32_HAVE_IP_ETHMAC_V2 - STM32_PHY_POLLING composite dropped: STM32_PHY_HAVE_POLLED is only selected for non-legacy chips, so the family condition was redundant Verified .config equivalence with olddefconfig on eth-enabled F4/F7/H7 configs and the full board matrix: only the new capability symbols appear.
…HAVE_ETHMAC Three overlapping flags described the same capability: STM32_HAVE_ETHMAC (legacy families), STM32_HAVE_ETHRNET (F7, typo) and STM32_HAVE_ETHERNET (H7/H5 + bridge selects from the other two). Keep STM32_HAVE_ETHMAC as the canonical flag: F7/H7/H5 chips now select it directly, the legacy bridge selects are dropped, the STM32_ETHMAC gate in Kconfig.periph and the chip.h STM32_NETHERNET definitions use it, and the two redundant flags are deleted. Verified .config equivalence on eth-enabled F4/F7/H7 configs plus the full board matrix: only the flag rename appears. Built nucleo-f767zi:netnsh and nucleo-h743zi:netnsh.
…c/usb/system/flash Kconfig - Kconfig.sdio: legacy SDIO options need no family gate (STM32_SDIO is only selectable on legacy chips); SDMMC options move to new STM32_SDMMC_HAVE_DMA / _HAVE_IDMA / _HAVE_SDIO_MODE feature flags - Kconfig.rtc: MAGIC_REG range keyed to the RTCC IP flags; LSE drive capability options move to new STM32_HAVE_RTC_LSE_AUTO_DRV / STM32_HAVE_RTC_LSE_DRV / STM32_HAVE_RTC_LSE_DRV_LOWER; redundant legs folded (the AUTO option can only be enabled where implemented) - Kconfig.usb: host debug options gate on STM32_USBHOST (legacy-only symbol) or new STM32_USBHOST_HAVE_DEBUG; USBFS/USBDEV REGDEBUG and OTG ID-pin options move to per-driver feature flags; host menus drop the redundant LEGACY condition - Kconfig.system: idle-sleep option -> STM32_HAVE_DISABLE_IDLE_SLEEP; DFU -> DFUMODE IP flags (new M0_V1 for the Cortex-M0 group); tickless timer/channel -> STM32_HAVE_TICKLESS_UPTO_TIM14/_TIM17 (encode both the family set and the timer-number range); SysTick clock choice keys off ARCH_CORTEXM0 per the naming rules - Kconfig.flash: override/prefetch/progmem conditions move to STM32_HAVE_FLASH_OVERRIDE / _PREFETCH / _PROGMEM / _PROGMEM_MTD Verified .config equivalence with olddefconfig on 13 configs across F3/F4/G4/F7/H7/H5/L4/U5/WB/WL5: only new capability symbols appear.
….spi - STM32_SPI_INTERRUPTS -> new STM32_HAVE_SPI_INTERRUPTS - SPIn DMA buffer options -> new STM32_HAVE_SPI_DMA_BUFFER (plus a per-instance STM32_SPI6_HAVE_DMA_BUFFER, since SPI6 DMA is reachable on F4 but its buffer option was F7/H7/H5-only) - SPI4/5/6 DMA gates collapse onto the existing STM32_HAVE_SPI_DMA_FAMILY, whose family set is identical - Cortex-M0 group DMA legs -> new STM32_HAVE_SPI_DMA_M0 - COMMTYPE options -> new STM32_HAVE_SPI_COMMTYPE - I2S options: LEGACY legs -> existing STM32_HAVE_IP_I2S_M3M4_V1 (the F7 legs stay until the F7 I2S driver is unified) The undefined STM32_SPI_INTERRUPT (singular) references are left untouched; they predate this change. Verified .config equivalence with olddefconfig on 13 configs: only new capability symbols appear.
…/periph Kconfig
- Kconfig.adc: F7/H7/H5/L5/U5 composites expand to explicit family
names (they die when the remaining family ADC drivers are unified);
the L4_L5_U5 tails collapse onto STM32_HAVE_ADC_L4, since L5 cannot
reach STM32_ADCn and U5 never sets STM32_ADC
- DAC DMA-timer options -> new STM32_HAVE_DAC_DMA_TIMER
- Kconfig.periph:
- I2S/I2S3 selects key off STM32_HAVE_IP_I2S_M3M4_V1
- DMA2D FB selects drop the redundant LEGACY and HAVE_DMA2D terms
- BBSRAM -> new STM32_HAVE_BBSRAM (BBSRAM IP flag or F7/H7)
- AES ALGTEST selects simplify to STM32_HAVE_AES && CRYPTO_ALGTEST;
this now also covers L4, which uses the same common AES driver but
was left out of the family lists
- drop the USBFS 'select USBDEV if ...' line shadowed by the
unconditional select above it
- STM32_USBHOST gates on the OTG host IP flags instead of LEGACY
- STM32_SDIO gates on STM32_HAVE_IP_SDIO_M3M4_V1; this removes the
dead SDIO option from G4, which has no SDIO hardware (the F1
connectivity/value-line exclusions are encoded at the select)
- USARTn_SERIALDRIVER selects -> new STM32_HAVE_USART_SERIALDRIVER
- PHY_HAVE_POLLED select keys off the ETHMAC IP flag; LCD USBDEV
select keys off ARCH_CORTEXM0
Verified .config equivalence on 13 configs: only new capability
symbols appear, plus the intended STM32_SDIO removal on G4.
….tim Replace all 160 STM32_COMMON_* references with capability flags: - wrappers: STM32_PULSECOUNT/ONESHOT/FREERUN/PWM_LL_OPS gate on new STM32_HAVE_PULSECOUNT / STM32_HAVE_TIM_ONESHOT / STM32_HAVE_TIM_FREERUN / STM32_HAVE_PWM_LL_OPS; the L4-lineage tickless defaults use new STM32_HAVE_TICKLESS_ONESHOT; the ONESHOT_MAXTIMERS family condition is dropped as it repeats the STM32_ONESHOT availability set - per-channel polarity/idle options (76 lines) -> new STM32_HAVE_TIM_PWM_POLARITY; the redundant STM32_TIM term is dropped since CHxOUT already implies it through TIMn_PWM -> STM32_TIMn - TIM12-14 and TIM15-17 option groups -> new STM32_HAVE_TIM_PWM_TIM12_14 / STM32_HAVE_TIM_PWM_TIM15_17 - channel 5/6 (internal) -> new STM32_HAVE_TIM_PWM_CHANNEL5/_CHANNEL6; the L5/U5 channel-mode quirk pairs reuse STM32_HAVE_TIM_PWM_CHMODE_LIMITED (equivalent: the M0 members of that flag cannot enable TIMn_CHANNEL5) - GP-timer extended channel-mode ranges -> new STM32_HAVE_TIM_PWM_CHMODE_GP_EXTENDED - capture options -> new STM32_HAVE_TIM_CAP; remaining L4/L5/U5/H7/H5-only capture and LPTIM legs expand to explicit family names that die when those family drivers are unified Verified .config equivalence with olddefconfig on 18 configs including PWM/FOC/capture-heavy ones (nucleo-h743zi:pwm, nucleo-f302r8:ihm07m1_f32, nucleo-l432kc:spwm, b-g474e-dpow1:buckboost, nucleo-f302r8:qenco): only the new capability symbols appear. Built nucleo-h743zi:pwm and nucleo-f302r8:ihm07m1_f32.
Complete the composite removal: - expand the remaining STM32_COMMON_* references inside Kconfig.have and Kconfig.qspi to explicit ARCH_CHIP_* lists (family names are tolerated in the capability-flag definitions, which are the single family->capability map) - gate the legacy Cortex-M3/M4 system-core source block in Make.defs / CMakeLists.txt with new STM32_HAVE_IP_SYSCORE_M3M4_V1 instead of STM32_COMMON_LEGACY, and switch the stm32_dma2d.h / stm32_exti_pwr.h / stm32_usbhost.h facade dispatch to the same flag - delete the composite definitions from the common Kconfig; 'grep -r STM32_COMMON_ arch/ boards/' is now clean (modulo the STM32_COMMON_SRCDIR make variable) - update the stm32_ports.rst Kconfig-simplification section Verified .config equivalence on 18 configs: only the composite symbols disappear and STM32_HAVE_IP_SYSCORE_M3M4_V1 appears on legacy families. Built stm32f4discovery:nsh (make and CMake/ninja) and nucleo-f722ze:nsh.
… names Pure renames per the Kconfig naming rules (STM32_HAVE_* must describe capabilities or IP versions, not families): - STM32_HAVE_ADC_L4 -> STM32_HAVE_IP_ADC_M3M4_V3 - STM32_HAVE_ADC_H5 -> STM32_HAVE_IP_ADC_M33_V1 - STM32_HAVE_FDCAN_H7 -> STM32_HAVE_IP_FDCAN_M7_V1 - STM32_HAVE_OTG_H7 -> STM32_HAVE_IP_OTG_M7_V1 The flags still mark not-yet-unified family drivers; the final IP mapping is decided when each driver moves to common/stm32. STM32_HAVE_I2C_H5 and STM32_HAVE_USART_H5 are intentionally left: they die with the I2C and serial unifications. STM32_HAVE_IP_CRYPTO_H7 is renamed together with the CRYP driver move. Verified .config equivalence on 18 configs (rename-only diffs); built nucleo-h743zi:nsh, b-l475e-iot01a:nsh, nucleo-h563zi:nsh.
…IP names These IP blocks are about to be selected by Cortex-M7 (F7/H7) and Cortex-M33 (H5) families as their local drivers are retired into common/stm32. An IP version names the silicon only and must not encode the CPU core it sits next to, so drop the transitional m3m4 prefix before extending them: - STM32_HAVE_IP_RNG_M3M4_V1 -> STM32_HAVE_IP_RNG_V1 - STM32_HAVE_IP_WDG_M3M4_V1 -> STM32_HAVE_IP_WDG_V1 - STM32_HAVE_IP_DMA2D_M3M4_V1 -> STM32_HAVE_IP_DMA2D_V1 - STM32_HAVE_IP_I2C_M3M4_V2 -> STM32_HAVE_IP_I2C_V2 with the matching source renames (stm32_rng_v1.c, stm32_iwdg_v1.c, stm32_wwdg_v1.c, stm32_dma2d_v1.c/h, stm32_i2c_v2.c, stm32_i2c_v2_slave.c). IP names still carrying a core prefix remain used by a single core class only; each drops the prefix when it first crosses cores, at which point the per-core version spaces are merged deliberately.
Retire the F7/H5/H7/L4 copies of the RNG driver in favor of common/stm32/stm32_rng_v1.c. The H7 copy was byte-identical except the header comment; F7/H5/L4 differed only in naming style, interrupt-enable placement, and the ISR error handling. The common ISR now adopts the F7/H5/L4 error recovery unconditionally: clock error (CEIS) is cleared and retried, and seed error (SEIS) is cleared with an RNGEN toggle, instead of silently discarding the sample. The L4 copy also ignored the nxsem_wait() return value; the common driver's handling is kept. The four families select STM32_HAVE_IP_RNG_V1 (if STM32_HAVE_RNG) from their family peripheral block. The common Make.defs/CMakeLists RNG gate moves out of the STM32_HAVE_IP_SYSCORE_M3M4_V1 legacy block to the top level so non-legacy families reach it. stm32l4/hardware/stm32l4_rng.h is renamed to stm32_rng.h to match the include used by the common driver. Built nucleo-l496zg:nsh (make and CMake), stm32f769i-disco:netnsh, stm32f4discovery:nsh, and nucleo-h743zi/nucleo-h563zi with RNG force-enabled.
Retire the H7 IWDG/WWDG and L4 IWDG copies in favor of common/stm32/stm32_iwdg_v1.c / stm32_wwdg_v1.c. The deltas were naming style and the DBGMCU freeze-in-debug write. The freeze block now dispatches on the DBGMCU register macros instead of chip-line names, covering all four DBGMCU layouts (H7 APB4LFZ1/ APB3FZ1, V3 APB1_FZ1, V2 APB1_FZ, V1 CR). This fixes two latent bugs: G4 (DBGMCU v3) wrote the freeze bit to the v1 CR register, and the old H7 code referenced APB4_FZ1/WDGLSD1 macros that exist nowhere in the tree (compile error whenever JTAG was enabled with IWDG). Plumbing: H7 selects new STM32_HAVE_IP_DBGMCU_M7_V1 (its DBGMCU register block moves to common hardware/stm32_dbgmcu_m7_v1.h); L4 selects STM32_HAVE_IP_DBGMCU_M3M4_V3, whose register layout it matches exactly. The common WDG register header aliases the H7 IWDG1/WWDG1 instance names; l4 hardware/stm32l4_wdg.h is renamed to stm32_wdg.h and the L4/H7 stm32_wdg.h source facades are dropped in favor of the common one. The common IWDG/WWDG build gates move out of the SYSCORE_M3M4_V1 legacy block so H7/L4 reach them. The dead stm32l4/hardware/stm32_rng.h left over from the RNG move is removed. Built with IWDG+WWDG+JTAG forced on: nucleo-h743zi (M7/H7 path), nucleo-l496zg (make and CMake, V3 path), nucleo-g474re (V3 path), stm32f4discovery (V2 path). stm32f103-minimum fails on a pre-existing missing STM32_LSI_FREQUENCY in board.h, unrelated to this change. Verified .config equivalence on 18 configs.
The F7 stm32_dma2d.c/h were formatting-only forks of common/stm32/stm32_dma2d_m3m4_v1.c/h. F7 now selects STM32_HAVE_IP_DMA2D_V1 (if STM32_HAVE_DMA2D), the common facade and build gates dispatch on that IP flag instead of the legacy SYSCORE flag, and the gate moves out of the legacy-only Make.defs block. Built stm32f746g-disco:fb with DMA2D force-enabled and stm32f429i-disco:fb as the F4 regression control.
stm32h7/stm32_aes.c drives the CRYP peripheral (not the AES IP); move it to common/stm32/stm32_aes_cryp_v1.c with its register definitions relocated to common hardware/stm32_cryp_v1.h, and rename STM32_HAVE_IP_CRYPTO_H7 to STM32_HAVE_IP_CRYP_V1 accordingly. The common stm32_aes.h facade dispatches on the new flag. The cryptodev wrapper stm32_crypto_m3m4_v1.c adopts the H7 version: it takes the IV from crp->crp_iv, which is where NuttX cryptodev delivers the user IV (the old crd->crd_iv read an unset field), and it accepts 192/256-bit AES-CTR keys, which the backend validates. Built nucleo-h753zi:crypto (exercises both moved files); .config equivalence verified on 18 configs.
Prepare the common I2C v2 master and slave drivers for multi-family use and retire the H7 copy (a formatting-level fork): - the RCC clock-enable/reset registers are parameterized through the config structure, with the register/bit names resolved by macro presence (H7-style APB1L/APB4 vs legacy APB1), instead of being hardcoded to the legacy APB1 names - the H7 I2C kernel-clock sanity checks (D2CCIP2R/D3CCIPR must select HSI) join the per-family validation chain - the drivers include the family aggregate stm32.h for the GPIO API instead of the common stm32_gpio.h facade, which only covers families using the common GPIO driver - H7 selects STM32_HAVE_IP_I2C_V2 and the common I2C build gates move out of the SYSCORE_M3M4_V1 legacy block Built stm32h745i-disco:touchtest and linum-stm32h753bi:lvglterm (H7, I2C1-4 paths) and nucleo-f303ze:nxlines_oled (F3 regression).
…2 I2C v2 The F7 stm32_i2c.c was a fork of the common I2C v2 driver differing only in log strings and the instance-wrapper structure. F7's kernel clock sanity checks (DCKCFGR2 I2CxSEL must be HSI) join the per-family validation chain; F7's I2C1-4 all sit on APB1, covered by the existing register map. F7 selects STM32_HAVE_IP_I2C_V2. Built stm32f746g-disco:lvgl (I2C3 touch) and stm32f769i-disco:netnsh.
a265c0a to
3d14248
Compare
Summary
This PR is the first step toward unification and reorganisation of STM32 ports. This is a huge, breaking change that impacts many users. It also introduces the standard for STM32 ports described in the documentation page. Any new STM32 port or new STM32 feature should adhere to these rules.
This reorganization allows for the separation of STM32 families with minimal code duplication. Ultimately, we'll be able to eliminate most of the duplication between STM32 families, but this is a long-term task. Subsequent changes won't be as invasive, and most won't require breaking changes.
This PR focuses on the first step in the STM32 redesign, which is the most invasive and includes a lot of breaking changes.
Summary of changes:
What is not done yet:
The stm32f7, stm32h7, and stm32l4 should be easy. The rest, based on the Cortex-M33, will require more time because I'm not familiar with these chips yet. After this migration, support for the missing stm32 families should be much easier.
This change will later enable us to solve another problem - the standardization of ST boards, so all nucleo board follows the same patterns and provide the same features.
I know this PR is huge, but it can't really be done in smaller steps. This is an attempt to fix a problem that's been building for over a decade. I will create a separate PR so it is easier to review, this PR is to show the final effect . The best way to review this change is to download the entire branch and view it locally. Github is unable to render changes well and misses many git rename operations.
If the community deems this change desirable, it should be included in version 13.0, as it's a significant change that's causing a lot of disruption. I think this is the best time for this reorganization, even if it will upset many users and likely break something.
For all AI skeptics here - this PR was created with AI assistance and burned hundreds of dollars worth of tokens. There is no other way to do it, doing it manually is unrealistic, especially if you do it alone and for free :) This PR doesn't add new code, it only organizes the old code, so the code license remains the same as the original code
References:
#18894
#16172
Impact
Breaking change that impacts many users. There should be no functional changes; users should only need to update defconfig options in theory, but this is a huge change done mostly with AI assistance, so there is some chance that things will be broken.
The larger the PR, the greater the chance that something will break uncontrollably. Therefore, if this change is to be implemented upstream, it should be in release 13.0, which already contains a lot of breaking changes.
I tried to preserve the git history as much as possible, but for Kconfig it was not possible.
What we gain from this PR:
No more questions about how to create new STM32 ports, everything is set in advance and the user has to comply.
Testing
CI
upstream build and test on HW:
Later I will do tests with my Dawn project (https://github.com/railab/dawn) where I have a lot of HW automated tests based on NTFC, so it should catch most of the regressions.
PRs
These needs to go to release 13.0 as these are major breaking changes that completely reorganize STM32 ports.
Done:
#19066
#19067
#19069
#19114
#19125
#19136
#19143
Pending:
Next in line, separated PRs:
bf58190 !arch/arm/src/stm32: unify timer driver and STM32_TIMn_CLKIN across all families
e310ecb !arch/stm32: Unify and commonize stm32_uid for all STM32 families.
Can be merged after release 13.0:
2797fe0 arch/arm/src/stm32: unify quadrature encoder driver into common/stm32
eb46a77 arch/arm/src/stm32: unify TIM1/TIM8 interrupt vector names across families
194fd55 arch/arm/src/stm32: unify TIM one-shot wrapper into common/stm32
786bc83 arch/arm/src/stm32: unify TIM free-running wrapper into common/stm32
59df038 arch/arm/src/stm32: unify LSI driver and make RCC headers per-family
f371090 arch/arm/src/stm32l4: use common/stm32 1-Wire driver
cae71ff arch/arm/src/stm32: unify pulse count driver into common/stm32
baddb20 boards/arm/stm32{l5,u5,wb,wl5,n6}: switch board common to stm32 common
bf7e64f boards/arm/stm32h7: switch board common to boards/arm/common/stm32
833cd9e boards/arm/stm32h5: switch board common to boards/arm/common/stm32
fc4e631 boards/arm/stm32{f1,f4}: drop duplicated reset.c/romfs, use common board logic
a33eac8 boards/arm/stm32f7: switch board common to boards/arm/common/stm32
8099cb0 boards/arm/stm32f4: drop duplicated STM32_ROMFS, use common board logic
c5d4945 arch/arm/stm32f7: add stm32.h peripheral header
30dbca3 arch/stm32: Commonize stm32_waste across all STM32 families.