fix(linker): correct several cross-toolchain memory map inconsistencies#75
Open
94xhn wants to merge 1 commit into
Open
fix(linker): correct several cross-toolchain memory map inconsistencies#7594xhn wants to merge 1 commit into
94xhn wants to merge 1 commit into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 addressEWARM's
.icfdeclared RAM at0x28000000(the address used elsewhere in this repo for the small 16K "SRAM4" region) but sized it as 768K (the size of the main RAM at0x20000000) - a copy-paste combining the wrong address with the wrong region's size. This project's own GCC.ldonly declares/uses the main0x20000000/768K RAM (no SRAM4/alias region at all), confirming EWARM's value was simply wrong. Fixed to0x20000000/768K.(Three other files were initially flagged for this same pattern -
I2C_TwoBoards_ComDMA_LowPowerand bothSPI_FullDuplex_ComDMA_LowPower_*examples on NUCLEO-U575ZI-Q - but turned out NOT to be bugs on closer inspection: their own GCC.ldfiles declare anSRAMalias region at the same0x28000000/768K address and actually place.data/.bss/stack there via explicit>SRAMsection 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) andDCACHE_Maintenance(STM32U575I-EV) - Keil RAM restricted to 192KKeil's
RW_IRAM1only reserved 192K at0x20000000while GCC/_estackboth 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) andRAMCFG_ECC_Error_Generation(NUCLEO-U575ZI-Q) - stray "100K" typoBoth GCC
.ldfiles had a strayLENGTH = 100KRAM 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 64KEWARM's RAM was 192K (
0x2002FFFF) while GCC/_estackboth target the chip's real 256K.5.
Fx_File_Edit_StandaloneandTx_Thread_Creation(STM32U5G9J-DK2) - GCC RAM wrong by an order of magnitudeBoth GCC
.ldfiles 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 ownExamples/BSPEWARM file).6.
Examples/BSP(STM32U5G9J-DK2) - EWARM RAM only 384KThis exact project's own GCC
.ldcorrectly uses the chip's real 3008K, while EWARM was at 384K (0x2005FFFF).7.
Tx_MPUdual-partition ThreadX MPU demo (STM32U5G9J-DK2 and STM32U5x9J-DK) - overlapping flash partitionsThe GCC MODULE-partition linker script set FLASH
ORIGINto0x08000000- identical to, and fully overlapping, the MANAGER partition's own flash region (also0x08000000, 128K) - instead of0x08020000(128K past MANAGER), which IAR'smodule.icfalready 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 FLASHORIGINto0x08020000(LENGTHunchanged 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
0x20020000origin, 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.