Skip to content

fix(linker): correct several cross-toolchain memory map inconsistencies#75

Open
94xhn wants to merge 1 commit into
STMicroelectronics:mainfrom
94xhn:fix/linker-cross-toolchain-audit-u5
Open

fix(linker): correct several cross-toolchain memory map inconsistencies#75
94xhn wants to merge 1 commit into
STMicroelectronics:mainfrom
94xhn:fix/linker-cross-toolchain-audit-u5

Conversation

@94xhn

@94xhn 94xhn commented Jul 11, 2026

Copy link
Copy Markdown

Not tied to a specific existing issue - found by systematically cross-checking each example's GCC (STM32CubeIDE)/IAR (EWARM)/Keil (MDK-ARM) linker scripts against each other and against known-good sibling projects for the same chip, following the same methodology already used for STM32CubeG4 and STM32CubeWB in this repo family.

For every finding below, I determined "which value is actually right" by checking which MEMORY region the project's real SECTIONS (.data/.bss/heap+stack, and _estack) actually target - not just by comparing MEMORY{} declarations. A declared-but-unused region can look like a cross-toolchain mismatch without actually being one; this caught some initial false positives that are called out below rather than silently dropped.

1. ADF_AudioSoundDetector (B-U585I-IOT02A) - EWARM RAM at the wrong address

EWARM's .icf declared RAM at 0x28000000 (the address used elsewhere in this repo for the small 16K "SRAM4" region) but sized it as 768K (the size of the main RAM at 0x20000000) - a copy-paste combining the wrong address with the wrong region's size. This project's own GCC .ld only declares/uses the main 0x20000000/768K RAM (no SRAM4/alias region at all), confirming EWARM's value was simply wrong. Fixed to 0x20000000/768K.

(Three other files were initially flagged for this same pattern - I2C_TwoBoards_ComDMA_LowPower and both SPI_FullDuplex_ComDMA_LowPower_* examples on NUCLEO-U575ZI-Q - but turned out NOT to be bugs on closer inspection: their own GCC .ld files declare an SRAM alias region at the same 0x28000000/768K address and actually place .data/.bss/stack there via explicit >SRAM section directives. EWARM using the same address/size for those three actually matches its sibling GCC file's real behavior, so they were left untouched.)

2. LPTIM_IC_LSE (NUCLEO-U575ZI-Q) and DCACHE_Maintenance (STM32U575I-EV) - Keil RAM restricted to 192K

Keil's RW_IRAM1 only reserved 192K at 0x20000000 while GCC/_estack both target the full 768K RAM at the same address (confirmed via each project's own >RAM-targeted SECTIONS). Fixed Keil to 768K.

3. RTC_ActiveTamper (NUCLEO-U545RE-Q) and RAMCFG_ECC_Error_Generation (NUCLEO-U575ZI-Q) - stray "100K" typo

Both GCC .ld files had a stray LENGTH = 100K RAM size (repo-wide grep confirms these are the only 2 occurrences of this exact value anywhere in the repo) instead of the real chip RAM (256K and 768K respectively, both confirmed via the projects' own IAR files).

4. Fx_File_Edit_Standalone (NUCLEO-U545RE-Q) - EWARM RAM short by 64K

EWARM's RAM was 192K (0x2002FFFF) while GCC/_estack both target the chip's real 256K.

5. Fx_File_Edit_Standalone and Tx_Thread_Creation (STM32U5G9J-DK2) - GCC RAM wrong by an order of magnitude

Both GCC .ld files declared RAM as 256K instead of the chip's real 3008K (confirmed via 19 other correct GCC examples on the same board, and via the board's own Examples/BSP EWARM file).

6. Examples/BSP (STM32U5G9J-DK2) - EWARM RAM only 384K

This exact project's own GCC .ld correctly uses the chip's real 3008K, while EWARM was at 384K (0x2005FFFF).

7. Tx_MPU dual-partition ThreadX MPU demo (STM32U5G9J-DK2 and STM32U5x9J-DK) - overlapping flash partitions

The GCC MODULE-partition linker script set FLASH ORIGIN to 0x08000000 - identical to, and fully overlapping, the MANAGER partition's own flash region (also 0x08000000, 128K) - instead of 0x08020000 (128K past MANAGER), which IAR's module.icf already correctly uses on both boards. Two independently-linked, MPU-isolated firmware images cannot share a flash base address without one corrupting the other. Fixed GCC's MODULE FLASH ORIGIN to 0x08020000 (LENGTH unchanged at 896k, so the region still ends at the same address IAR uses, 0x080FFFFF).

I left the MODULE RAM size alone (GCC 128K vs IAR 64K at the same 0x20020000 origin, no overlap either way in this case) - could not rule out intentional extra headroom without reading the ThreadX MPU application's own memory-partitioning source, so this stays a known open question rather than something I guessed at.

Test plan

No local ARM toolchain (arm-none-eabi-gcc/IAR/Keil) available to compile/link-test these, so verification relied on address-arithmetic cross-referencing for each finding against multiple independent references: sibling toolchain files of the same project, other correct examples on the same board, and - critically - checking which MEMORY region a project's actual SECTIONS target rather than trusting the MEMORY{} declaration alone (this is exactly what ruled out the 3 false positives under finding 1).

Disclosure

Generative AI (Claude) was used to help investigate this (systematic cross-toolchain linker script comparison) and implement/verify the fixes. All changes were reviewed by me before submission.

Found by cross-checking each example's GCC (STM32CubeIDE)/IAR (EWARM)/
Keil (MDK-ARM) linker scripts against each other and against known-good
sibling projects, following the same audit already done for
STM32CubeG4/STM32CubeWB in this session. For every finding, the "which
value is actually right" call was made by checking which MEMORY region
the project's real SECTIONS (.data/.bss/heap+stack, and _estack) target
- not just by comparing MEMORY{} declarations, since a declared-but-unused
region can look like a mismatch while not actually being one (this cost
some initial false positives that were caught and dropped, see below).

1. ADF_AudioSoundDetector (B-U585I-IOT02A): EWARM's .icf declared RAM at
   0x28000000 (SRAM4's address, used elsewhere in this repo as a small
   16K region) but sized it as 768K (the size of the *main* RAM at
   0x20000000) - a copy-paste combining the wrong address with the wrong
   region's size. This project's own GCC .ld only declares/uses the main
   0x20000000/768K RAM (no SRAM4/alias region at all), confirming EWARM's
   value was simply wrong. Fixed to 0x20000000/768K.

   (Three other files initially flagged for this same pattern -
   I2C_TwoBoards_ComDMA_LowPower and both SPI_FullDuplex_ComDMA_LowPower_*
   examples on NUCLEO-U575ZI-Q - turned out NOT to be bugs on closer
   inspection: their own GCC .ld files declare an `SRAM` alias region at
   the same 0x28000000/768K address and *actually place* .data/.bss/stack
   there (confirmed via the `>SRAM` section directives), so EWARM using
   the same address/size for those three actually matches its sibling
   GCC file's real behavior. Left untouched.)

2. LPTIM_IC_LSE (NUCLEO-U575ZI-Q) and DCACHE_Maintenance (STM32U575I-EV):
   Keil's RW_IRAM1 only reserved 192K at 0x20000000 while GCC/`_estack`
   both target the full 768K RAM at the same address (confirmed via each
   project's own `>RAM`-targeted SECTIONS). Fixed Keil to 768K.

3. RTC_ActiveTamper (NUCLEO-U545RE-Q) and RAMCFG_ECC_Error_Generation
   (NUCLEO-U575ZI-Q): both GCC .ld files had a stray "LENGTH = 100K" RAM
   size (repo-wide grep confirms these are the only 2 occurrences of this
   exact value in the whole repo) instead of the real chip RAM (256K and
   768K respectively, both confirmed via the projects' own IAR files).

4. Fx_File_Edit_Standalone (NUCLEO-U545RE-Q): EWARM's RAM was 192K
   (0x2002FFFF) while GCC/`_estack` both target the chip's real 256K.

5. Fx_File_Edit_Standalone and Tx_Thread_Creation (STM32U5G9J-DK2): both
   GCC .ld files declared RAM as 256K instead of the chip's real 3008K
   (confirmed via 19 other correct GCC examples on the same board, and
   via the board's own Examples/BSP EWARM file).

6. Examples/BSP (STM32U5G9J-DK2): EWARM's RAM was 384K (0x2005FFFF)
   while this exact project's own GCC .ld correctly uses the chip's
   real 3008K.

7. Tx_MPU dual-partition ThreadX MPU demo (STM32U5G9J-DK2 and
   STM32U5x9J-DK): the GCC MODULE-partition linker script set FLASH
   ORIGIN to 0x08000000 - identical to, and fully overlapping, the
   MANAGER partition's own flash region (also 0x08000000, 128K) -
   instead of 0x08020000 (128K past MANAGER), which IAR's module.icf
   already correctly uses on both boards. Two independently-linked,
   MPU-isolated firmware images cannot share a flash base address.
   Fixed GCC's MODULE FLASH ORIGIN to 0x08020000 (LENGTH unchanged at
   896k, so the region still ends at the same address IAR uses,
   0x080FFFFF). Left the MODULE RAM size (GCC 128K vs IAR 64K at the
   same 0x20020000 origin, no overlap either way) untouched - could not
   rule out intentional extra headroom without reading the ThreadX MPU
   application's own memory-partitioning source.

No local ARM toolchain available to compile/link-test these changes;
verification relied on address-arithmetic cross-referencing against
multiple independent references per finding (sibling toolchain files of
the same project, other correct examples on the same board, and -
critically - checking which MEMORY region a project's actual SECTIONS
target, not just what's declared).

Signed-off-by: yi chen <94xhn1@gmail.com>
@ALABSTM ALABSTM added bug Something isn't working projects Projects-related (demos, applications, examples) issue or pull-request. labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working projects Projects-related (demos, applications, examples) issue or pull-request.

Projects

Development

Successfully merging this pull request may close these issues.

3 participants