Skip to content

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

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#113
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 (STM32CubeIDE)/IAR (EWARM)/Keil (MDK-ARM) linker scripts against each other, following the same methodology already used for STM32CubeG4, STM32CubeWB, STM32CubeWL, STM32CubeU5, STM32CubeF7, and STM32CubeF4 in this repo family.

1. IAP_Binary_Template (STM32L476G-EVAL) - Keil offsets the start but forgets to shrink the length

Keil's .uvprojx correctly offsets the app's flash start address to 0x08008000 to leave room for the bootloader, but never shrinks the length to compensate - OCR_RVCT4 still declares 1MB as if starting from 0x08000000, running 32K past the chip's actual end of flash. IAR and GCC in the same project both correctly use 992K. Fixed Keil's OCR_RVCT4 Size to 0xF8000 (992K).

2. IAP_Main (STM32L476G-EVAL, the bootloader itself)

Keil's .uvprojx OCR_RVCT4 declares the full 1MB flash instead of the 32K bootloader budget that IAR/GCC both correctly use. If the bootloader's own build ever grows close to or past 32K, Keil wouldn't catch it linking straight into the application region it's supposed to hand off to. Fixed to 0x8000 (32K).

3. PWR_RUN_SMPS (NUCLEO-L4R5ZI-P, STM32L4R5, 2MB flash) - reserved region copied from the wrong board

GCC's .ld places the reserved 6K ROM_While1 region (used by whileloop1() in main.c, explicitly placed there via #pragma/section attributes in all three toolchains) at 0x080FE800 - the correct address for a 1MB-flash board, not this 2MB one - and never shrinks the main FLASH region to make room, so the two regions overlap in address space.

IAR's .icf correctly places the same reserved region at 0x081FE800 (near the true end of 2MB flash) with FLASH shrunk to 2042K. I cross-checked against three sibling "-P" boards (NUCLEO-L433RC-P, NUCLEO-L452RE-P, NUCLEO-L496ZG-P) that all correctly compute this reserved region's address relative to their own flash size - only NUCLEO-L4R5ZI-P copied the wrong constant, most likely from a 1MB-flash board's version of this same example.

Fixed GCC's ROM_While1 origin to 0x081FE800 and FLASH length to 2042K.

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 against each project's own IAR/GCC files and, for finding 3, sibling boards' equivalent examples.

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, following the same
audit already done for STM32CubeG4/WB/WL/U5/F7/F4 in this repo family.

1. IAP_Binary_Template (STM32L476G-EVAL): Keil's `.uvprojx` correctly
   offsets the app's flash start address to 0x08008000 to leave room
   for the bootloader, but never shrinks the length to compensate -
   OCR_RVCT4 still declares 1MB as if starting from 0x08000000,
   running 32K past the chip's actual end of flash. IAR/GCC in the
   same project both correctly use 992K. Fixed Keil's OCR_RVCT4 Size
   to 0xF8000 (992K).

2. IAP_Main (STM32L476G-EVAL, the bootloader itself): Keil's
   `.uvprojx` OCR_RVCT4 declares the full 1MB flash instead of the
   32K bootloader budget that IAR/GCC both correctly use. If the
   bootloader's own build ever grows close to or past 32K, Keil
   wouldn't catch it linking straight into the application region it's
   supposed to hand off to.

3. PWR_RUN_SMPS (NUCLEO-L4R5ZI-P, STM32L4R5, 2MB flash): GCC's `.ld`
   copies the reserved 6K `ROM_While1` region (used by `whileloop1()`
   in `main.c`, explicitly placed there via `#pragma`/`section`
   attributes in all three toolchains) at `0x080FE800` - the correct
   address for a 1MB-flash board, not this 2MB one - and never
   shrinks the main FLASH region to make room, so the two regions
   overlap. IAR's `.icf` correctly places the same reserved region at
   `0x081FE800` (near the true end of 2MB flash) with FLASH shrunk to
   2042K. Cross-checked against three sibling "-P" boards (L433RC-P,
   L452RE-P, L496ZG-P) that all correctly compute this reserved
   region's address relative to their own flash size - only
   NUCLEO-L4R5ZI-P copied the wrong constant. Fixed GCC's `ROM_While1`
   origin to `0x081FE800` and FLASH length to 2042K.

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 each project's own
IAR/GCC files and, for finding 3, sibling boards' equivalent examples.

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
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