Skip to content

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

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

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

Conversation

@94xhn

@94xhn 94xhn commented Jul 11, 2026

Copy link
Copy Markdown

Summary

I cross-checked the GCC (STM32CubeIDE/*.ld), IAR (EWARM/*.icf) and Keil (MDK-ARM/*.uvprojx -> real .sct scatter file, not the stale OCR_RVCT* XML placeholders) linker descriptions of the same physical memory for every example under Projects/, and found 4 GCC-only drifts across 8 linker scripts, each confirmed by IAR and Keil independently agreeing with each other and disagreeing with GCC.

1. RAM/ROM overlap — PWR_STANDBY / PWR_STANDBY_RTC (STM32N6570-DK, Appli role)

Projects/STM32N6570-DK/Examples/PWR/PWR_STANDBY/STM32CubeIDE/Appli/STM32N657X0HXQ_LRUN.ld and the _RTC sibling declared:

ROM (xrw) : ORIGIN = 0x34000400, LENGTH = 511K   // ends at 0x3407FFFF
RAM (xrw) : ORIGIN = 0x34020000, LENGTH = 1536K  // starts INSIDE the ROM region

RAM starts at 0x34020000, which is 384 KB before ROM ends (0x3407FFFF), so the two regions overlap by 384 KB — code/rodata placed near the end of ROM would share physical bytes with .data/.bss.

Both EWARM/Appli/stm32n657xx_LRUN.icf (__ICFEDIT_region_RAM_start__ = 0x34080000) and MDK-ARM/Appli/stm32n657xx_LRUN.sct (__RAM_BASE 0x34080000) start RAM immediately after ROM ends, with no overlap. Fixed GCC's RAM origin to 0x34080000 in both examples.

2. RAM under-allocated by 128 KB — CORTEX_InterruptSwitch_TrustZone (NUCLEO-N657X0-Q, AppliNonSecure role)

Projects/NUCLEO-N657X0-Q/Examples/CORTEX/CORTEX_InterruptSwitch_TrustZone/STM32CubeIDE/AppliNonSecure/STM32N657X0HXQ_FLASH.ld declared a single merged RAM (xrw): ORIGIN = 0x241a0000, LENGTH = 256K (0x241a0000-0x241DFFFF).

EWARM/AppliNonSecure/stm32n657xx_fsbl_ns.icf defines ROM_region (0x241A0000-0x241BFFFF, 128K) + RAM_region (0x241C0000-0x241FFFFF, 256K) = 384K total, and MDK-ARM/AppliNonSecure/stm32n657xx_ns.sct agrees (__ROM_SIZE 0x20000 + __RAM_SIZE 0x40000 = 384K). Both independently authored toolchain files put the usable non-secure window's top at 0x241FFFFF, which also matches the well-established top of the same physical AXISRAM2 bank used identically (secure alias 0x341FFFFF) across dozens of other examples in the repo. GCC's file stopped 128 KB short of that boundary with nothing else claiming the missing space. Widened GCC's RAM LENGTH from 256K to 384K (origin unchanged) to reclaim the missing 128 KB and match both other toolchains.

3. FSBL RAM off-by-1KB — VENC_RTSP_Server / VENC_SDCard / VENC_SDCard_ThreadX / VENC_USB (STM32N6570-DK, FSBL role)

All four STM32CubeIDE/FSBL/STM32N657XX_AXISRAM2_fsbl.ld files declared:

ROM (xr) : ORIGIN = 0x34180400, LENGTH = 255K
RAM (rw) : ORIGIN = 0x341C0000, LENGTH = 255K   // should be 256K

RAM at LENGTH = 255K looks like the ROM line's 255K was copy-pasted down. Both EWARM/FSBL/stm32n657xx_axisram2_fsbl.icf (__ICFEDIT_region_RAM_end__ = 0x341FFFFF, i.e. 256K) and MDK-ARM/FSBL/stm32n657xx_axisram2_fsbl.sct (__RAM_SIZE 0x00040000 = 256K) agree the region is a full 256K. Fixed all four to LENGTH = 256K.

4. Appli ROM off-by-1KB — VENC_SDCard (STM32N6570-DK, Appli role)

Projects/STM32N6570-DK/Applications/VENC/VENC_SDCard/STM32CubeIDE/Appli/STM32N657XX_LRUN.ld declared ROM (xr) : ORIGIN = 0x34000400, LENGTH = 256K, one KB larger than EWARM/Appli/stm32n657xx_LRUN.icf (__ICFEDIT_region_ROM_end__ = 0x3403FFFF -> 255K) and MDK-ARM/Appli/stm32n657xx_LRUN.sct (__ROM_SIZE 0x0003FC00 -> 255K). This is inconsistent with the convention used everywhere else in the repo, where a ROM window starting at a +0x400 header offset is sized (bank − 1K). Fixed GCC's ROM LENGTH from 256K to 255K.

Notes on false positives excluded

While auditing I found several automated size mismatches that turned out not to be bugs after reading the actual SECTIONS/scatter placement, and excluded them:

  • Several NetXDuo (Nx_*) FSBL examples: GCC keeps one monolithic RAM region and places the NetX packet pool at an absolute address inside it, while IAR carves out a separate named region (NXApp_region) at the exact same address — same physical layout, different linker-script idiom.
  • Template_FSBL_LRUN / Template_Isolation_LRUN/_XIP FSBL/Appli roles: GCC merges ROM+RAM into one named region whose size equals the split IAR/Keil totals exactly — again a stylistic difference, not a drift.
  • ITCM 128K vs 64K in several VENC_* Appli GCC scripts: the ITCM MEMORY entry is declared but never referenced in SECTIONS, so it's dead/unused and carries no functional risk; left untouched.
  • One region (RAM in CORTEX_InterruptSwitch_TrustZone's FSBL role, secure side) where GCC and Keil agree with each other and only IAR differs by 4x — inconclusive without a datasheet cross-check, so left unchanged rather than guess.

Test plan

No local ARM toolchain (armclang/armcc/IAR) available, so verification was done purely via address arithmetic:

  • Recomputed ORIGIN/LENGTH -> end-address for every changed region and confirmed no more overlap with sibling regions in the same file (issue 1).
  • Confirmed the new GCC region boundaries land exactly on the addresses independently declared by both EWARM/*.icf and MDK-ARM/*.sct for the same example/role (issues 1-4).
  • Cross-checked the corrected boundaries against the physical AXISRAM2 bank top (0x241FFFFF/0x341FFFFF) used consistently across the rest of Projects/ (issue 2).
  • Grepped the whole repo for each buggy pattern to make sure every affected file was found and fixed (issue 3: exactly 4 files; issue 4: 1 file).

Disclosure

This audit and patch were prepared with Claude (Anthropic) assistance — automated cross-toolchain diffing to surface candidate mismatches, with every flagged case then manually re-verified by hand (reading the actual SECTIONS/scatter-file placement, computing region boundaries, and cross-referencing all three toolchains) before deciding whether to fix it. All changes have been reviewed by me before submission.

…M32N6 GCC linker scripts

Cross-checked the GCC (STM32CubeIDE .ld), IAR (EWARM .icf) and Keil
(MDK-ARM .sct, the real scatter file referenced by <ScatterFile> in
.uvprojx, not the stale OCR_RVCT placeholders) linker descriptions of
the same physical memory for every Projects/* example and found four
GCC-only drifts, all confirmed by both other toolchains agreeing with
each other and disagreeing with GCC:

1. PWR_STANDBY / PWR_STANDBY_RTC (STM32N6570-DK, Appli role): the GCC
   RAM region started at 0x34020000 while ROM (511K @ 0x34000400) ends
   at 0x3407FFFF, so RAM overlapped the last 384 KB of ROM. IAR and
   Keil both start RAM at 0x34080000 (immediately after ROM). Moved
   the GCC RAM origin to 0x34080000 to remove the overlap.

2. CORTEX_InterruptSwitch_TrustZone (NUCLEO-N657X0-Q, AppliNonSecure
   role): GCC declared only 256 KB of non-secure RAM (0x241A0000-
   0x241DFFFF) while IAR (ROM_region + RAM_region) and Keil
   (ROM_SIZE + RAM_SIZE) both cover the full 384 KB non-secure window
   up to 0x241FFFFF, which is also the well-established top of that
   AXISRAM2 bank used consistently across the rest of the repository
   (secure alias 0x341FFFFF). Widened GCC's RAM LENGTH from 256K to
   384K to match.

3. VENC_RTSP_Server / VENC_SDCard / VENC_SDCard_ThreadX / VENC_USB
   (STM32N6570-DK, FSBL role): GCC declared the FSBL RAM region as
   255K instead of 256K (looks like the adjacent ROM line's 255K was
   copy-pasted into the RAM line). Both IAR (__ICFEDIT_region_RAM_end__
   = 0x341FFFFF) and Keil (__RAM_SIZE = 0x00040000) agree the region
   is the full 256K. Fixed GCC RAM LENGTH from 255K to 256K in all
   four FSBL linker scripts.

4. VENC_SDCard (STM32N6570-DK, Appli role): the same project's ROM
   region was declared as a round 256K, one KB larger than IAR
   (__ICFEDIT_region_ROM_end__ = 0x3403FFFF -> 255K) and Keil
   (__ROM_SIZE = 0x0003FC00 -> 255K), inconsistent with the repo-wide
   convention that a ROM window starting at a +0x400 header offset is
   sized (bank - 1K). Fixed GCC ROM LENGTH from 256K to 255K.

No local ARM toolchain available; verified purely via address
arithmetic (region overlap / boundary matching) cross-referenced
against the independently-authored IAR and Keil files for the same
example.

Several other automated mismatches were investigated and excluded as
false positives, e.g. GCC merging ROM+RAM into a single named region
where IAR/Keil split them (same total physical span, just a different
MEMORY block style), and NetXDuo examples where GCC uses an absolute-
address sub-section for the packet pool while IAR carves out a
separate named region at the same address (same physical layout,
different linker-script idiom).

Signed-off-by: 94xhn <87560781+94xhn@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant