From c63594c78a0d7d5992da159833322113c0511dd4 Mon Sep 17 00:00:00 2001 From: 94xhn <87560781+94xhn@users.noreply.github.com> Date: Sat, 11 Jul 2026 21:29:54 +0800 Subject: [PATCH] fix(linker): correct cross-toolchain memory map inconsistencies 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 STM32CubeG0/G4/H5/H7/L0/L4/U5/WB/WBA/WL/F0/F1/ F4/F7 in this repo family. 1. Applications/FreeRTOS/FreeRTOS_MPU (NUCLEO-L552ZE-Q and STM32L552E-EV, STM32L552ZE/QE, 512K flash): Keil's scatter file declared a 2MB (0x00200000) privileged code region starting at 0x08000000, running 1.5MB past the chip's real flash end. GCC's .ld (512K) and IAR's .icf (ROM_end 0x0807FFFF, also 512K) both agree on the real 512K. Fixed Keil's LR_APP size to 0x00080000 (512K) on both boards. 2. Examples/PWR/PWR_LPRUN_SRAM1 (NUCLEO-L552ZE-Q): this demo intentionally executes from SRAM1 in Low-Power Run mode, so GCC and IAR both correctly place code/data inside the SRAM address range (0x20000000+) rather than flash - this part is by design, not a bug. But Keil's scatter file was never updated to match: it still used flash-based addresses (LR_IROM1 0x08000000, 512K) and a RAM region sized for normal full-SRAM use (RW_IRAM1 0x20000000, 192K), i.e. it doesn't exercise the SRAM-execution design the demo is supposed to demonstrate at all. IAR's .icf cleanly splits the 192K SRAM1 into a 128K code region (0x20000000-0x2001FFFF) and 64K data region (0x20020000-0x2002FFFF). Fixed Keil to the same split. GCC's own .ld also targets the SRAM range correctly, but its MEMORY block declared a 125K/65K split (an odd 3K offset from IAR's clean 128K/64K boundary, with a gap between the regions) while its own header comment already said "128Kbytes ROM / 65Kbytes RAM" - fixed GCC's actual MEMORY LENGTH values to 128K/64K to match IAR and the corrected Keil, resolving the comment/code mismatch. 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 (IAR's clean symbolic region boundaries, GCC's own header comments, and this board's own Templates project). Signed-off-by: 94xhn <87560781+94xhn@users.noreply.github.com> --- .../FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct | 2 +- .../PWR/PWR_LPRUN_SRAM1/MDK-ARM/stm32l552xe_flash.sct | 6 +++--- .../PWR_LPRUN_SRAM1/STM32CubeIDE/STM32L552ZETXQ_FLASH.ld | 8 ++++---- .../FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Projects/NUCLEO-L552ZE-Q/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct b/Projects/NUCLEO-L552ZE-Q/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct index 608d7ec9e..c291e5568 100644 --- a/Projects/NUCLEO-L552ZE-Q/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct +++ b/Projects/NUCLEO-L552ZE-Q/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct @@ -18,7 +18,7 @@ ; | Unprivileged Data | ; --------------------- -LR_APP 0x08000000 0x00200000 ; load region size_region +LR_APP 0x08000000 0x00080000 ; load region size_region { ER_IROM_PRIVILEGED 0x08000000 { diff --git a/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/MDK-ARM/stm32l552xe_flash.sct b/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/MDK-ARM/stm32l552xe_flash.sct index a2c35683b..cba9f2df4 100644 --- a/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/MDK-ARM/stm32l552xe_flash.sct +++ b/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/MDK-ARM/stm32l552xe_flash.sct @@ -2,14 +2,14 @@ ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* -LR_IROM1 0x08000000 0x00080000 { ; load region size_region - ER_IROM1 0x08000000 0x00080000 { ; load address = execution address +LR_IROM1 0x20000000 0x00020000 { ; load region size_region + ER_IROM1 0x20000000 0x00020000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } - RW_IRAM1 0x20000000 0x00030000 { ; RW data + RW_IRAM1 0x20020000 0x00010000 { ; RW data .ANY (+RW +ZI) } } diff --git a/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/STM32CubeIDE/STM32L552ZETXQ_FLASH.ld b/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/STM32CubeIDE/STM32L552ZETXQ_FLASH.ld index 190248e25..964109281 100644 --- a/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/STM32CubeIDE/STM32L552ZETXQ_FLASH.ld +++ b/Projects/NUCLEO-L552ZE-Q/Examples/PWR/PWR_LPRUN_SRAM1/STM32CubeIDE/STM32L552ZETXQ_FLASH.ld @@ -6,8 +6,8 @@ ** Author : Auto-generated by STM32CubeIDE ** ** Abstract : Linker script for STM32L5x2xE Device from STM32L5 series -** 125Kbytes ROM -** 65Kbytes RAM +** 128Kbytes ROM +** 64Kbytes RAM ** ** Set heap size, stack size and stack location according ** to application requirements. @@ -44,8 +44,8 @@ _Min_Stack_Size = 0x400 ; /* required amount of stack */ /* Memories definition */ MEMORY { - RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 65K - ROM (rx) : ORIGIN = 0x20000000, LENGTH = 125K + RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 64K + ROM (rx) : ORIGIN = 0x20000000, LENGTH = 128K } /* Sections */ diff --git a/Projects/STM32L552E-EV/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct b/Projects/STM32L552E-EV/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct index 608d7ec9e..c291e5568 100644 --- a/Projects/STM32L552E-EV/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct +++ b/Projects/STM32L552E-EV/Applications/FreeRTOS/FreeRTOS_MPU/MDK-ARM/stm32l552xe_flash.sct @@ -18,7 +18,7 @@ ; | Unprivileged Data | ; --------------------- -LR_APP 0x08000000 0x00200000 ; load region size_region +LR_APP 0x08000000 0x00080000 ; load region size_region { ER_IROM_PRIVILEGED 0x08000000 {