Skip to content

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

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

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

Conversation

@94xhn

@94xhn 94xhn commented Jul 11, 2026

Copy link
Copy Markdown

Not tied to a specific existing issue - found by systematically cross-checking each example's GCC (SW4STM32)/IAR (EWARM)/Keil (MDK-ARM) linker scripts against each other and against known-good Templates/Templates_LL sibling projects for the same chip, following the same methodology already used for STM32CubeG4, STM32CubeWB, and STM32CubeU5 in this repo family.

1. STM32F769I-Discovery and STM32F769I_EVAL (STM32F769NIH6, 2MB flash / 512KB RAM) - 18 examples, EWARM alone wrong

EWARM's .icf declared only 1MB flash (ROM_end=0x080FFFFF) and either 320K or 64K RAM instead of the chip's real 2MB / 512K, across 18 ordinary HAL peripheral examples on both boards. GCC and Keil both already correctly use the full 2MB/512K for the same projects - confirmed via _estack (computed as 0x20080000 = 0x20000000 + 512K) and each project's own GCC MEMORY block. Fixed all 18 EWARM files to ROM_end=0x081FFFFF, RAM_end=0x2007FFFF.

2. STM32F769I_EVAL FatFs example family (6 project identities, 18 files) - EWARM and GCC both wrong

Both EWARM (.icf) and GCC (.ld, across the USB-host-mode SW4STM32 variants) declared only 1MB flash / 320K RAM - only Keil (via its .uvprojx <Cpu> line, IRAM(0x20000000-0x2007FFFF) IROM(0x8000000-0x81FFFFF)) correctly used the full 2MB flash / 512K RAM. This is a "2-of-3-toolchains-wrong" pattern - a naive majority vote across toolchains would have picked the wrong answer here, similar to what was already found once in STM32CubeWB. Fixed EWARM's ROM/RAM end symbols and GCC's FLASH/RAM LENGTH to 2048K/512K in all 6 EWARM .icf + 12 GCC .ld files.

3. NUCLEO-F767ZI (STM32F767ZIT6, 2MB flash / 512KB RAM) - 25 examples, Keil alone wrong

Keil ships no explicit .sct scatter file for these projects - the project's own <Cpu> device-descriptor line in Project.uvprojx is what it actually links against - and that line declared only 320K RAM (IRAM(0x20000000-0x2004FFFF)) instead of the chip's real 512K. Confirmed against GCC/IAR agreement on 512K for the same projects, and cross-checked across two different Keil device-pack versions used by different examples on this board (2.3.3 and 2.7.5), ruling out a pack-specific fluke rather than a real content bug. Fixed the IRAM range to 0x20000000-0x2007FFFF in all 25 files.

The same board's plain Templates project (as opposed to Templates_LL, which already agrees on 512K across all 3 toolchains and served as the gold standard for this finding) had this exact same bug in both its GCC .ld and Keil .uvprojx, with only its own IAR .icf correct - fixed those 2 files too.

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: Templates/Templates_LL gold standards, sibling toolchain files of the same project, and checking _estack/actual linker symbol usage rather than trusting MEMORY{}/Cpu-line declarations alone.

Note on scope

A 4th candidate was found (STM32F7308-DISCO / STM32F7508-DISCO, flash-less QSPI-execute-in-place parts where Keil ships with no scatter file at all and falls back to a non-functional 64KB internal-flash default) but is not included in this PR - fixing it would require authoring a new Keil scatter file for QSPI XIP from scratch rather than correcting an existing value, which is a larger, more design-heavy change that deserves its own separate scrutiny/PR rather than being bundled here.

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 (SW4STM32)/IAR (EWARM)/Keil
(MDK-ARM) linker scripts against each other and against known-good
Templates/Templates_LL sibling projects, following the same audit
already done for STM32CubeG4/STM32CubeWB/STM32CubeU5 in this repo
family.

1. STM32F769I-Discovery and STM32F769I_EVAL (STM32F769NIH6, 2MB
   flash/512KB RAM), 18 ordinary HAL peripheral examples: EWARM's .icf
   declared only 1MB flash (ROM_end=0x080FFFFF) and 320K or 64K RAM
   instead of the chip's real 2MB/512K. GCC and Keil both already
   correctly use the full 2MB/512K for the same projects (confirmed via
   `_estack` and the GCC MEMORY block in each project). Fixed all 18
   EWARM files to ROM_end=0x081FFFFF, RAM_end=0x2007FFFF.

2. STM32F769I_EVAL FatFs example family (6 project identities, 18
   files: 6 EWARM .icf + 12 SW4STM32 .ld across USB host mode
   variants): both EWARM AND GCC declared only 1MB flash / 320K RAM -
   only Keil (via its .uvprojx Cpu line) correctly used the full 2MB
   flash / 512K RAM. This is the "2-of-3-toolchains-wrong" pattern
   already seen once in STM32CubeWB - majority vote across toolchains
   would have picked the wrong answer here. Fixed EWARM ROM/RAM ends
   and GCC FLASH/RAM LENGTH to 2048K/512K.

3. NUCLEO-F767ZI (STM32F767ZIT6, 2MB flash/512KB RAM), 25 example/
   application projects: Keil (no explicit .sct shipped; the project's
   own <Cpu> device-descriptor line in Project.uvprojx is what it
   actually links against) declared only 320K RAM
   (IRAM(0x20000000-0x2004FFFF)) instead of the chip's real 512K.
   Confirmed against GCC/IAR agreement on 512K for the same projects,
   and cross-checked across two different Keil device-pack versions
   used by different examples on this board (2.3.3 and 2.7.5), ruling
   out a pack-specific fluke. Fixed the IRAM range to
   0x20000000-0x2007FFFF in all 25 files.

   Same board's plain Templates project (as opposed to Templates_LL,
   which already agrees on 512K across all 3 toolchains and served as
   the gold standard here) had this exact same bug in both its GCC .ld
   and Keil .uvprojx, with only its own IAR .icf correct - fixed those
   2 files too.

No local ARM toolchain (arm-none-eabi-gcc/IAR/Keil) available to
compile/link-test these changes; verification relied on
address-arithmetic cross-referencing against multiple independent
references per finding (Templates/Templates_LL gold standards, sibling
toolchain files of the same project, and `_estack`/actual linker
symbol usage, not just MEMORY{}/Cpu-line declarations).

A 4th candidate (STM32F7308-DISCO/STM32F7508-DISCO, flash-less
QSPI-execute-in-place parts where Keil ships with no scatter file at
all and falls back to a non-functional 64KB internal-flash default) is
not included here - fixing it would require authoring a new Keil
scatter file for QSPI XIP rather than correcting an existing value, a
larger and more design-heavy change that needs more scrutiny before a
PR.

Signed-off-by: 94xhn <87560781+94xhn@users.noreply.github.com>
@ALABSTM ALABSTM added bug Something isn't working projects Projects-related (demos, applications, examples) issue or pull-request. labels Jul 13, 2026
@ASAHSTM ASAHSTM moved this from To do to Analyzed in stm32cube-mcu-fw-dashboard Jul 17, 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