fix(linker): correct cross-toolchain memory map inconsistencies - #21
fix(linker): correct cross-toolchain memory map inconsistencies#2194xhn wants to merge 2 commits into
Conversation
…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>
ALABSTM
left a comment
There was a problem hiding this comment.
Hi @94xhn,
Thank you for this other thorough review of our linker files. I have a few questions I have to loop back about with our development team. I'll let you know so you can update your pull request accordingly.
Meanwhile, please do not hesitate if you would like to reply to my remarks.
With regards,
| { | ||
| ROM (xrw) : ORIGIN = 0x34000400, LENGTH = 511K | ||
| RAM (xrw) : ORIGIN = 0x34020000, LENGTH = 1536K | ||
| RAM (xrw) : ORIGIN = 0x34080000, LENGTH = 1536K |
There was a problem hiding this comment.
I am also questioning the length of this memory area in secure AXISRAM1. 1536kB in decimal translate to 0x0018'0000B in hexadecimal, making this region extend till address 0x341F'FFFF.
This overlaps with the FSBL in secure AXISRAM2, starting at address 0x3418'0000 according to the REAMD.md (see below), assuming both memories are contiguous. Does it not?
According to Table 2. Memory map and peripheral register boundary addresses of RM0486, rev. 4, the secure AXISRAM1 region ends at address 0x340F'FFFF. This would leave only 512kB room for the RAM region.
STM32CubeN6/Projects/STM32N6570-DK/Examples/PWR/PWR_STANDBY/README.md
Lines 13 to 14 in 8ab3b64
There was a problem hiding this comment.
Hi @ALABSTM, you were right here. I rechecked the example-specific MDK scatter file and the RAM window for this PWR application is 0x34080000-0x340FFFFF, not 1536KB up to 0x341FFFFF. I have now updated both GCC and IAR for PWR_STANDBY and PWR_STANDBY_RTC to the same 512KB range, which also removes the overlap with the FSBL in AXISRAM2.
There was a problem hiding this comment.
Hi @94xhn,
I built the Appli subproject of the PWR_STANDBY example using STM32CubeIDE 2.1.1 and, based on the log, the footprint of the different sections to be located into the RAM region is just a "handful" of bytes, confirming the 512kB length fix.
arm-none-eabi-objcopy -O binary PWR_STANDBY_Appli.elf "PWR_STANDBY_Appli.bin"
text data bss dec hex filename
14312 32 2592 16936 4228 PWR_STANDBY_Appli.elf
Finished building: default.size.stdout
With regards,
There was a problem hiding this comment.
Thank you for checking it with STM32CubeIDE and for the approval. That build result is useful confirmation of the corrected RAM range.
| { | ||
| ROM (xrw) : ORIGIN = 0x34000400, LENGTH = 511K | ||
| RAM (xrw) : ORIGIN = 0x34020000, LENGTH = 1536K | ||
| RAM (xrw) : ORIGIN = 0x34080000, LENGTH = 1536K |
There was a problem hiding this comment.
Same remark about the RAM region's length.
There was a problem hiding this comment.
Applied the same correction to the RTC sibling as well: GCC and IAR now both use RAM 0x34080000-0x340FFFFF, matching the MDK scatter file there too.
| MEMORY | ||
| { | ||
| RAM (xrw) : ORIGIN = 0x241a0000, LENGTH = 256K | ||
| RAM (xrw) : ORIGIN = 0x241a0000, LENGTH = 384K |
There was a problem hiding this comment.
Strange that the memory is not split between ROM and RAM as done for the two other IDEs. It is the case in a similar application, as shown below.
There was a problem hiding this comment.
Thanks, I aligned the GCC script with that split now. The non-secure window is defined as ROM 0x241A0000-0x241BFFFF plus RAM 0x241C0000-0x241FFFFF, matching the example's IAR file, MDK scatter file, and README.
The PWR standby application windows were rechecked against the example-specific MDK scatter files after the review feedback. The earlier 1536K assumption was wrong, so both PWR_STANDBY variants now keep the corrected 0x34080000 RAM origin but stop at 0x340FFFFF in GCC and IAR. The non-secure GCC linker script for CORTEX_InterruptSwitch_TrustZone now also uses the same ROM/RAM split already defined by the example's IAR and MDK files instead of one merged 384K RAM region. Constraint: No local ARM, IAR, or Keil linkers available; verification had to be static interval checks against repo linker metadata Rejected: Keep 1536K and argue AXISRAM2 reuse | The example-specific MDK scatter limits the same PWR application RAM to 512K, so the earlier assumption was incorrect Confidence: high Scope-risk: narrow Directive: For STM32N6 FSBL plus application examples, do not generalize from Template_FSBL_LRUN alone; cross-check the example-specific MDK scatter and security or retention map first Tested: Node-based interval checks for PWR_STANDBY, PWR_STANDBY_RTC, and CORTEX_InterruptSwitch_TrustZone across GCC, IAR, and MDK; git diff --check Not-tested: Local ARM, IAR, or Keil link-load; hardware boot or wakeup
|
Hi @ALABSTM, I pushed commit d7bdc94 addressing the three review points.\n\n- PWR_STANDBY and PWR_STANDBY_RTC: GCC and IAR now use RAM 0x34080000-0x340FFFFF, after rechecking the example-specific MDK scatter files.\n- CORTEX_InterruptSwitch_TrustZone AppliNonSecure: the GCC linker script now uses the same ROM/RAM split as the example's IAR and MDK files.\n\nVerification was done by recomputing the start/end addresses from the updated GCC, IAR, and MDK linker descriptions and confirming the three toolchains now agree for each reviewed example. |
|
ST Internal Reference: 38e6a5aa83920710b42ee9402fda1ed7 |
Summary
I cross-checked the GCC (
STM32CubeIDE/*.ld), IAR (EWARM/*.icf) and Keil (MDK-ARM/*.uvprojx-> real.sctscatter file, not the staleOCR_RVCT*XML placeholders) linker descriptions of the same physical memory for every example underProjects/, 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,Applirole)Projects/STM32N6570-DK/Examples/PWR/PWR_STANDBY/STM32CubeIDE/Appli/STM32N657X0HXQ_LRUN.ldand the_RTCsibling declared:RAMstarts at0x34020000, which is 384 KB beforeROMends (0x3407FFFF), so the two regions overlap by 384 KB — code/rodata placed near the end ofROMwould share physical bytes with.data/.bss.Both
EWARM/Appli/stm32n657xx_LRUN.icf(__ICFEDIT_region_RAM_start__ = 0x34080000) andMDK-ARM/Appli/stm32n657xx_LRUN.sct(__RAM_BASE 0x34080000) start RAM immediately after ROM ends, with no overlap. Fixed GCC'sRAMorigin to0x34080000in both examples.2. RAM under-allocated by 128 KB —
CORTEX_InterruptSwitch_TrustZone(NUCLEO-N657X0-Q,AppliNonSecurerole)Projects/NUCLEO-N657X0-Q/Examples/CORTEX/CORTEX_InterruptSwitch_TrustZone/STM32CubeIDE/AppliNonSecure/STM32N657X0HXQ_FLASH.lddeclared a single mergedRAM (xrw): ORIGIN = 0x241a0000, LENGTH = 256K(0x241a0000-0x241DFFFF).EWARM/AppliNonSecure/stm32n657xx_fsbl_ns.icfdefinesROM_region(0x241A0000-0x241BFFFF, 128K) +RAM_region(0x241C0000-0x241FFFFF, 256K) = 384K total, andMDK-ARM/AppliNonSecure/stm32n657xx_ns.sctagrees (__ROM_SIZE 0x20000+__RAM_SIZE 0x40000= 384K). Both independently authored toolchain files put the usable non-secure window's top at0x241FFFFF, which also matches the well-established top of the same physical AXISRAM2 bank used identically (secure alias0x341FFFFF) 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'sRAMLENGTHfrom256Kto384K(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,FSBLrole)All four
STM32CubeIDE/FSBL/STM32N657XX_AXISRAM2_fsbl.ldfiles declared:RAMatLENGTH = 255Klooks like theROMline's255Kwas copy-pasted down. BothEWARM/FSBL/stm32n657xx_axisram2_fsbl.icf(__ICFEDIT_region_RAM_end__ = 0x341FFFFF, i.e. 256K) andMDK-ARM/FSBL/stm32n657xx_axisram2_fsbl.sct(__RAM_SIZE 0x00040000= 256K) agree the region is a full 256K. Fixed all four toLENGTH = 256K.4. Appli ROM off-by-1KB —
VENC_SDCard(STM32N6570-DK,Applirole)Projects/STM32N6570-DK/Applications/VENC/VENC_SDCard/STM32CubeIDE/Appli/STM32N657XX_LRUN.lddeclaredROM (xr) : ORIGIN = 0x34000400, LENGTH = 256K, one KB larger thanEWARM/Appli/stm32n657xx_LRUN.icf(__ICFEDIT_region_ROM_end__ = 0x3403FFFF-> 255K) andMDK-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+0x400header offset is sized(bank − 1K). Fixed GCC'sROMLENGTHfrom256Kto255K.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:NetXDuo(Nx_*) FSBL examples: GCC keeps one monolithicRAMregion 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/_XIPFSBL/Appliroles: GCC mergesROM+RAMinto one named region whose size equals the split IAR/Keil totals exactly — again a stylistic difference, not a drift.ITCM128K vs 64K in severalVENC_*AppliGCC scripts: theITCMMEMORYentry is declared but never referenced inSECTIONS, so it's dead/unused and carries no functional risk; left untouched.RAMinCORTEX_InterruptSwitch_TrustZone'sFSBLrole, 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:
ORIGIN/LENGTH-> end-address for every changed region and confirmed no more overlap with sibling regions in the same file (issue 1).EWARM/*.icfandMDK-ARM/*.sctfor the same example/role (issues 1-4).0x241FFFFF/0x341FFFFF) used consistently across the rest ofProjects/(issue 2).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.