Skip to content

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

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

fix(linker): correct cross-toolchain memory map inconsistencies#11
94xhn wants to merge 2 commits 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) memory maps of every project under
Projects/NUCLEO-U031R8 against each other, using the Templates
project of the same board as the reference ("gold") memory map, and
against sibling projects/repositories where a project-local reference
was not conclusive. Two real, isolated cross-toolchain drifts were
found and fixed. All other apparent mismatches surfaced during the
audit were investigated and confirmed to be false positives (see
"Findings ruled out" below).

1. Examples/FLASH/FLASH_FastProgram — GCC linker script never redirects execution to SRAM

  • readme.html / README.md explicitly states: "All the executable
    code is mapped in SRAM1 area"
    .
  • The IAR project uses a dedicated EWARM/stm32u031xx_sram.icf
    (note the filename) whose ROM_region is 0x200000000x20001FFF
    (SRAM, not Flash).
  • The Keil project (MDK-ARM/FLASH_FastProgram.uvprojx) has its
    active code region OCR_RVCT4 (enabled via Ir1Chk) pointing at
    0x20000000/0x2000, i.e. also SRAM.
  • The STM32CubeIDE linker script
    (STM32CubeIDE/STM32U031R8TX_FLASH.ld) was the only outlier: it
    still places .isr_vector/.text/.rodata in the physical Flash
    region (0x08000000, 64 KB), unchanged from the generic template.

STM32U031 Flash has no read-while-write/dual-bank capability, so a
GCC/STM32CubeIDE build of this example would fetch instructions from
the same Flash bank that the demo itself erases and fast-programs —
undefined behavior on this device (at best a bus fault/lock-up during
the demo, at worst silent corruption). IAR and Keil avoid this by
running from SRAM as documented; GCC did not.

Fix: mirrored the SRAM-execution layout already used for the
identical FLASH_FastProgram example in the STM32G4 family, where
GCC ships a dedicated *_SRAM.ld
(STM32CubeG4/Projects/NUCLEO-G431KB/Examples/FLASH/FLASH_FastProgram/STM32CubeIDE/STM32G431KBTX_SRAM.ld)
using the same "FLASH region aliased into SRAM" trick:

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20002000,   LENGTH = 4K
  FLASH    (rx)    : ORIGIN = 0x20000000,   LENGTH = 8K
}

8 KB (code) + 4 KB (data/stack/heap) = 12 KB, matching the device's
physical SRAM and exactly matching the IAR icf's ROM_region
(8 KB at 0x20000000) and the intended RAM_region size.

While investigating this, I also found the Keil project's IRAM1
data region (OCR_RVCT9) declared 0x4000 (16 KB) at 0x20002000,
which combined with the 8 KB code region exceeds the device's total
12 KB physical SRAM by 12 KB. Corrected to 0x1000 (4 KB) to match
the IAR icf's RAM_region and the physical SRAM size.

2. Examples/PWR/PWR_ModesSelection — Keil project uses a different device's memory map

The Keil project (MDK-ARM/PWR_ModesSelection.uvprojx) declared:

IRAM(0x20000000,0x8000) IRAM2(0x20002000,0x2000) IROM(0x08000000,0x040000)

i.e. 256 KB Flash / 32 KB+8 KB RAM, and a FlashDriverDll pointing at
the STM32U0xx_256k.FLM algorithm with -FL040000 (256 KB). This
exactly matches a different STM32U0 part (e.g. STM32U083, which
does have 256 KB Flash / 32 KB RAM per Templates of
STM32U083C-DK), not the STM32U031R8Tx (<Device> tag) actually
targeted by this project, which has 64 KB Flash / 8 KB usable SRAM.

Every other Keil project for this exact board — Templates,
Templates_LL, and all ~25 other Examples/Examples_LL projects —
uses:

IRAM(0x20000000-0x20001FFF) IROM(0x8000000-0x800FFFF) CLOCK(25000000) CPUTYPE("Cortex-M0+") TZ

and an empty (or STM32U0xx_64k.FLM-based) FlashDriverDll. The
GCC and IAR memory maps of this same PWR_ModesSelection example are
already correct (64 KB/8 KB), so this was Keil-only drift, most
likely from copying a Keil project template/OCR block from a
different, larger STM32U0 device without updating the memory size
fields.

Fix: corrected <Cpu>, FlashDriverDll, and the OnChipMemories
IRAM/IROM/OCR_RVCT4/OCR_RVCT9 entries to 0x08000000/64 KB
and 0x20000000/8 KB, matching every sibling example for this board.

Findings ruled out (false positives / not fixed)

  • Applications/ROT/OEMiSB_Appli and OEMiSB_Boot (NUCLEO-U031R8):
    Keil OCR mismatches are inert — both projects set
    <ScatterFile>stm32u0xx_app.sct</ScatterFile>, so the real memory
    map comes from the .sct scatter file (which is correct), not the
    OCR_RVCT fields. The IAR "1-byte ROM" discrepancy my scanning
    script initially reported is a parsing artifact: the .icf uses
    expression-based addresses (e.g.
    0x08000000 + FLASH_BOOT_AREA_SIZE - SHA_AREA_SIZE) that a naive
    regex can't evaluate; the real region sizes match the GCC .ld
    exactly once the arithmetic is evaluated by hand.
  • Applications/ROT/OEMiROT_Appli and Templates_ROT
    (NUCLEO-U083RC): same expression-parsing artifact
    (CODE_OFFSET/CODE_SIZE computed from the paired
    OEMiROT_Boot project); the secure/non-secure partitioning is
    intentional and internally consistent.
  • Demonstration/Demo (STM32U083C-DK): the scan matched an unused,
    orphaned EWARM/stm32u083xx_sram.icf file. The actual active IAR
    build configuration (STM32U083C_DK_Demo.ewp
    IlinkIcfFile = stm32u083xx_flash.icf) matches GCC/Keil/gold
    exactly; the sram icf is not referenced by any build configuration.
  • Applications/OpenBootloader (STM32U083C-DK): IAR restricts the
    bootloader to 32 KB Flash / 13 KB RAM while GCC/Keil use the full
    256 KB/32 KB. This is a genuine, active discrepancy, but I could
    not establish with confidence which side is correct: precedent
    from sibling repositories is contradictory (STM32CubeC0's
    OpenBootloader restricts all three toolchains identically to a
    small partition, while STM32CubeG4's NUCLEO-G491RE
    OpenBootloader leaves GCC and IAR both unrestricted), and this
    application links USBX (DFU over USB), which could plausibly
    exceed 32 KB, making a blind "shrink GCC/Keil to match IAR" fix
    potentially a build-breaking regression. I'm leaving this out of
    the PR and flagging it here in case a maintainer with the actual
    build size numbers wants to resolve it.

Test plan

No ARM toolchain (GCC/IAR/Keil) is available in this environment, so
I could not compile/link either project to confirm the map file
output. Verification was done by:

  • Address/size arithmetic on every changed region, cross-checked
    against the device's total Flash/RAM as documented in this
    repository's own Templates linker scripts and the
    STM32CubeIDE .ld header comments (64Kbytes FLASH /
    12Kbytes RAM for STM32U031R8Tx).
  • Cross-referencing every one of the ~25 other Keil Examples/
    Examples_LL projects for NUCLEO-U031R8 to confirm the
    "correct" memory values used in the fix.
  • Cross-referencing the equivalent FLASH_FastProgram example in
    STM32CubeG4 (NUCLEO-G431KB/NUCLEO-G431RB), which already
    ships a working GCC *_SRAM.ld for the same kind of demo, to
    confirm the linker-script structure used in the fix.
  • Confirmed both edited .uvprojx files remain well-formed XML
    (xml.etree.ElementTree.parse).

Disclosure

I used Claude (Anthropic) as an AI coding assistant to help scan,
cross-reference, and draft this fix. I (the human submitter)
personally reviewed every file mentioned above, verified the address
arithmetic by hand, and take responsibility for the correctness of
this PR.

…CLEO-U031R8

Cross-checked the GCC (STM32CubeIDE), IAR (EWARM) and Keil (MDK-ARM)
memory maps of every NUCLEO-U031R8 project against each other and
against the STM32U031R8Tx datasheet (64 KB Flash / 12 KB SRAM). Two
real drifts were found and fixed:

1. Examples/FLASH/FLASH_FastProgram
   The README explicitly states "All the executable code is mapped
   in SRAM1 area", and both the IAR linker script
   (EWARM/stm32u031xx_sram.icf) and the Keil project
   (MDK-ARM/FLASH_FastProgram.uvprojx, OCR_RVCT4) place the code
   region at 0x20000000/8 KB in SRAM instead of at 0x08000000 in
   Flash. The STM32CubeIDE linker script
   (STM32U031R8TX_FLASH.ld) was never updated to match: it still
   places .isr_vector/.text/.rodata in the physical Flash region.
   Since STM32U031 Flash has no read-while-write capability, a GCC
   build of this example would execute from Flash while the demo
   itself erases/programs that same Flash bank, which is invalid
   on this device. Fixed by mirroring the SRAM execution layout
   already used by GCC in the equivalent FLASH_FastProgram example
   of the STM32G4 family (STM32CubeG4 NUCLEO-G431KB/G431RB,
   *_SRAM.ld): FLASH region moved to 0x20000000/8 KB (code),
   RAM region moved to 0x20002000/4 KB (data/stack/heap), for a
   total of 12 KB matching the device's physical SRAM.

   The Keil project's IRAM1 data region (OCR_RVCT9) was also wrong:
   it declared 0x4000 (16 KB) at 0x20002000, which together with
   the 8 KB code region exceeds the device's total 12 KB physical
   SRAM. Corrected to 0x1000 (4 KB) to match the IAR icf and the
   device's real SRAM size.

2. Examples/PWR/PWR_ModesSelection
   The Keil project (MDK-ARM/PWR_ModesSelection.uvprojx) declared
   the device memory map of a different, larger STM32U0 part:
   IROM 0x08000000/256 KB and IRAM 0x20000000/32 KB, along with a
   FlashDriverDll pointing at the STM32U0xx_256k.FLM algorithm.
   STM32U031R8Tx only has 64 KB Flash / 8 KB usable SRAM, as
   confirmed by every other Keil project for this same board
   (Templates, all other ~25 Examples/Examples_LL projects) and by
   the GCC/IAR linker scripts of this same example, which
   correctly use 64 KB/8 KB. Corrected the <Cpu> tag,
   FlashDriverDll (now STM32U0xx_64k.FLM / -FL010000), and the
   OnChipMemories IRAM/IROM/OCR_RVCT4/OCR_RVCT9 entries to the
   correct 0x08000000/64 KB and 0x20000000/8 KB values, matching
   every sibling example project.

No local ARM toolchain was available to rebuild the projects; the
fix was verified purely by address/size arithmetic and by
cross-referencing sibling example projects and precedent from the
equivalent example in the STM32CubeG4 repository.

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
@MKISTM MKISTM moved this from To do to Analyzed in stm32cube-mcu-fw-dashboard Jul 17, 2026
@MKISTM

MKISTM commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Hello @94xhn,

Thank you for your report, after deep investigation and our documentations reviewing, I believe that the original RAM and Flash memories and their size is correct.

According to the documentations:

  • the initial Flash address is 0x0800 0000 with memory size = 64Kbytes
  • the initial SRAM address is 0x2000 0000 with memory size = 8Kbytes because using (SRAM1)

You can find the evidence below extracted from the following documents: (Reference manual & Datasheet)

image image

Also, there is a simple way to know the flash memory size through ordering information section in the Datasheet for each device reference:
image

Therefore, would you mind allowing to close this issue.
Thank you for your cooperation as well as your understanding.

Best Regards,
KIWA Mohamed Chaker.

@MKISTM MKISTM closed this Jul 21, 2026
@github-project-automation github-project-automation Bot moved this from Analyzed to Done in stm32cube-mcu-fw-dashboard Jul 21, 2026
@MKISTM MKISTM added the invalid This doesn't seem right label Jul 21, 2026
@MKISTM MKISTM reopened this Jul 21, 2026
@MKISTM MKISTM closed this Jul 21, 2026
@MKISTM MKISTM reopened this Jul 24, 2026
@MKISTM

MKISTM commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Hello @94xhn,

I have returned to the second point in Examples/PWR/PWR_ModesSelection, and I noticed that your point seems to make sense only partially, because according to the SRAM size, there are two SRAMs, SRAM1 and SRAM2, and we should maintain both of them.

Best Regards,
KIWA Mohamed Chaker.

@MKISTM MKISTM closed this Jul 24, 2026
@MKISTM MKISTM reopened this Jul 24, 2026
@MKISTM MKISTM removed the invalid This doesn't seem right label Jul 24, 2026
The STM32U031R8 exposes an 8 KiB SRAM1 bank and a 4 KiB SRAM2 bank. Align the PWR example device metadata and on-chip memory regions with the repository's canonical U031R8 template while retaining the corrected 64 KiB Flash definition.

Constraint: Match the same-device MDK template and the PWR example's SRAM2 retention scenario
Rejected: Keep only SRAM1 | the project explicitly exercises SRAM2 retention and the device template exposes both banks
Confidence: high
Scope-risk: narrow
Directive: Keep the two physical SRAM banks distinct in MDK memory metadata
Tested: XML parse, exact field comparison with Templates/MDK-ARM, SRAM interval arithmetic, git diff --check
Not-tested: MDK-ARM build is unavailable locally
@94xhn

94xhn commented Jul 28, 2026

Copy link
Copy Markdown
Author

Thanks for catching that, @MKISTM. You're right: the STM32U031R8 has 8 KiB SRAM1 at 0x20000000 and 4 KiB SRAM2 at 0x20002000. I updated the MDK device metadata and second RAM region to match the repository's U031R8 template while keeping the corrected 64 KiB Flash definition; the XML and address-range checks pass.

@MKISTM

MKISTM commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

ST Internal Reference: 59cee5dd83da4f102ea7dbb0ecda1e86

@MKISTM MKISTM added the internal bug tracker Issue confirmed and logged into the internal bug tracking system label Jul 28, 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 internal bug tracker Issue confirmed and logged into the internal bug tracking system projects Projects-related (demos, applications, examples) issue or pull-request.

Projects

Development

Successfully merging this pull request may close these issues.

3 participants