Skip to content

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

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

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

Conversation

@94xhn

@94xhn 94xhn commented Jul 10, 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 (this repo has a lot of examples that duplicate the same physical memory map across 3 independently-maintained linker script formats, which can drift out of sync).

Five independent findings, each verified against at least one already-correct reference before fixing (never assumed "majority of 3 wins" - see finding 5, where all three toolchains agreed with each other but were all wrong):

1. SubGHz_Phy_PingPong_DualCore (CM0+, both boards) - EWARM FLASH short by 4K

EWARM/*.icf declared __ICFEDIT_region_ROM_end__ = 0x0803EFFF (124K) instead of 0x0803FFFF (128K). MDK-ARM and STM32CubeIDE both already correctly use the full 128K for this core's flash half.

2. CORTEX(M)_MPU (CM4, NUCLEO-WL55JC, Examples and Examples_LL variants) - STM32CubeIDE wrong memory map + overlapping region

STM32CubeIDE's .ld used a DualCore-style half-chip memory map (128K ROM instead of 256K, 16K RAM1/RAM2 instead of 32K/32K) for what is a single-core-only example, and additionally declared an extra RAM region at 0x20002000 that overlapped RAM1 by 8K while leaving another 8K completely unmapped by any region.

Confirmed via the example's own Src/stm32_mpu.c (Src/main.c for the LL variant) MPU configuration macros: EXAMPLE_FLASH_SIZE = MPU_REGION_SIZE_256KB, EXAMPLE_RAM_SIZE = MPU_REGION_SIZE_64KB (i.e. the full RAM1+RAM2), and ARRAY_ADDRESS_START = 0x20002000 - these match EWARM/MDK-ARM's existing correct memory map exactly, proving STM32CubeIDE's map was simply wrong, not an intentional restriction. Fixed to the correct 256K/32K/32K split, and moved .ROarraySection to the required fixed address (0x20002000, matching the IAR #pragma location for the same array) inside the corrected, non-overlapping RAM1 region instead of the separate overlapping region.

3. LocalNetwork_Sensor/Sensor (CM4, B-WL5M-SUBG1) - RAM2 disagreed 3 ways

EWARM declared 16K, MDK-ARM declared 48K (larger than the chip's actual SRAM2 - physically out of range), STM32CubeIDE correctly declared 32K. Fixed EWARM and MDK-ARM to match.

4. LoRaWAN family (LoRaWAN_End_Node_LBM, LoRaWAN_End_Node_Relay_LBM, LoRaWAN_Relay_LBM, both boards, 6 files) - MDK-ARM loses 16K of backup SRAM2

EWARM and STM32CubeIDE both correctly reserve a 4K gap (0x20008000-0x20008FFF, used as NVM_RAM in the GCC script) before a 28K RAM2 starting at 0x20009000. MDK-ARM's RW_IRAM2 instead started immediately at 0x20008000 with only 16K - encroaching on the reserved gap and losing the last 16K of physical SRAM2 entirely. Fixed to start at 0x20009000 with 28K, matching EWARM/GCC.

5. Templates/SingleCore and Templates_LL/SingleCore (CM4, B-WL5M-SUBG1, 6 files) - all 3 toolchains agree, but on the wrong value

This one doesn't show up as a cross-toolchain disagreement (all three already agree with each other), but the agreed-upon value itself is wrong: byte-for-byte identical to this board's Templates/DualCore/CM4 (128K ROM, 16K RAM1, 16K RAM2) instead of the correct full single-core memory map (256K ROM, 32K RAM1, 32K RAM2). Confirmed against the sibling NUCLEO-WL55JC's correct Templates/SingleCore (all 3 toolchains agree there, on the correct 256K/32K/32K) and against this board's own real single-core apps (the LoRaWAN family above, which use the same full split). Fixed all 3 toolchain files in both directories.

Test plan

No local ARM toolchain (arm-none-eabi-gcc/IAR/Keil) available to compile/link-test these, so verification relied on careful address-arithmetic cross-referencing for each finding against at least one already-correct, independently-maintained reference (a sibling toolchain file of the same project, a sibling board's equivalent project, or - for finding 2 - the example's own MPU configuration source code, which happened to make the intended values fully explicit).

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 for the same chip. Five independent issues, all in
Projects/:

1. SubGHz_Phy_PingPong_DualCore (CM0+, both boards): EWARM's .icf
   under-declares FLASH by exactly 4096 bytes (0x0803EFFF instead of
   0x0803FFFF), while MDK-ARM and STM32CubeIDE both correctly use the
   full 128K for this core's flash half.

2. CORTEX(M)_MPU (CM4, NUCLEO-WL55JC, both Examples and Examples_LL
   variants): STM32CubeIDE's .ld used a DualCore-style half-chip memory
   map (128K ROM instead of 256K, 16K RAM1/RAM2 instead of 32K/32K) for
   what is a single-core-only example, and additionally declared an
   extra `RAM` region at 0x20002000 that overlapped RAM1 by 8K while
   leaving another 8K completely unmapped. Confirmed via the example's
   own MPU_Config()/MPU_AccessPermConfig() in Src/stm32_mpu.c (or
   Src/main.c for the LL variant), whose own macros
   (EXAMPLE_FLASH_SIZE=256KB, EXAMPLE_RAM_SIZE=64KB,
   ARRAY_ADDRESS_START=0x20002000) match EWARM/MDK-ARM's existing
   correct values exactly, proving STM32CubeIDE's map was wrong, not a
   deliberate restriction. Fixed by using the correct 256K/32K/32K split
   and placing `.ROarraySection` at the required fixed address
   (0x20002000, matching the IAR #pragma location) inside the
   corrected, non-overlapping RAM1 region instead of a separate
   overlapping region.

3. LocalNetwork_Sensor/Sensor (CM4, B-WL5M-SUBG1): RAM2 disagreed 3
   ways - EWARM declared 16K, MDK-ARM declared 48K (larger than the
   chip's actual SRAM2), STM32CubeIDE correctly declared 32K. Fixed
   EWARM and MDK-ARM to match the correct 32K.

4. LoRaWAN_End_Node_LBM / LoRaWAN_End_Node_Relay_LBM / LoRaWAN_Relay_LBM
   (CM4, both boards, 6 files): MDK-ARM's RW_IRAM2 started immediately
   after RAM1 (0x20008000) with only 16K, while EWARM and STM32CubeIDE
   both correctly reserve a 4K gap (0x20008000-0x20008FFF, used as
   NVM_RAM in the GCC script) before a 28K RAM2 starting at 0x20009000.
   MDK's version both encroached on the reserved gap and lost the last
   16K of physical SRAM2. Fixed to start RAM2 at 0x20009000 with 28K,
   matching EWARM/GCC exactly.

5. Templates/SingleCore and Templates_LL/SingleCore (CM4,
   B-WL5M-SUBG1, 6 files): all three toolchains agreed with each other
   here, but on the wrong value - byte-for-byte identical to this
   board's Templates/DualCore/CM4 (128K ROM, 16K RAM1, 16K RAM2)
   instead of the correct full single-core memory map (256K ROM, 32K
   RAM1, 32K RAM2). Confirmed against the sibling NUCLEO-WL55JC's
   correct Templates/SingleCore (all 3 toolchains agree there) and
   against this board's own real single-core apps (e.g. the LoRaWAN
   family above, which use the full 256K/32K/32K split). Fixed all 3
   toolchain files in both directories to the correct values.

No local ARM toolchain available to compile/link-test these changes,
so verification relied on careful address-arithmetic cross-referencing
against multiple independent, already-correct references for each
finding (sibling toolchain files of the same project, sibling board's
equivalent project, and - for finding 2 - the example's own MPU
configuration source code).

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