fix(linker): correct several cross-toolchain memory map inconsistencies#113
Open
94xhn wants to merge 1 commit into
Open
fix(linker): correct several cross-toolchain memory map inconsistencies#11394xhn 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 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>
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 (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 4KEWARM/*.icfdeclared__ICFEDIT_region_ROM_end__ = 0x0803EFFF(124K) instead of0x0803FFFF(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,ExamplesandExamples_LLvariants) - STM32CubeIDE wrong memory map + overlapping regionSTM32CubeIDE's
.ldused 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 extraRAMregion at0x20002000that overlappedRAM1by 8K while leaving another 8K completely unmapped by any region.Confirmed via the example's own
Src/stm32_mpu.c(Src/main.cfor 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), andARRAY_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.ROarraySectionto the required fixed address (0x20002000, matching the IAR#pragma locationfor the same array) inside the corrected, non-overlappingRAM1region instead of the separate overlapping region.3.
LocalNetwork_Sensor/Sensor(CM4, B-WL5M-SUBG1) - RAM2 disagreed 3 waysEWARM 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 SRAM2EWARM and STM32CubeIDE both correctly reserve a 4K gap (
0x20008000-0x20008FFF, used asNVM_RAMin the GCC script) before a 28K RAM2 starting at0x20009000. MDK-ARM'sRW_IRAM2instead started immediately at0x20008000with only 16K - encroaching on the reserved gap and losing the last 16K of physical SRAM2 entirely. Fixed to start at0x20009000with 28K, matching EWARM/GCC.5.
Templates/SingleCoreandTemplates_LL/SingleCore(CM4, B-WL5M-SUBG1, 6 files) - all 3 toolchains agree, but on the wrong valueThis 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 siblingNUCLEO-WL55JC's correctTemplates/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.