fix(linker): correct cross-toolchain memory map inconsistencies#38
Open
94xhn wants to merge 1 commit into
Open
fix(linker): correct cross-toolchain memory map inconsistencies#3894xhn wants to merge 1 commit into
94xhn wants to merge 1 commit into
Conversation
Cross-checked GCC (STM32CubeIDE .ld), IAR (EWARM .icf) and Keil (MDK-ARM .uvprojx OCR_RVCTx) memory declarations against each other and against the true per-device Flash/RAM capacity (verified from each board's own Templates/TrustZoneDisabled project). Fixed 8 confirmed drift bugs across 6 boards: 1. STM32H5F5J-DK/Applications/OpenBootloader GCC .ld reserved 90K Flash for the bootloader while IAR .icf and the enabled Keil OCR_RVCT4 both reserve 70K (0x11800), matching the established OpenBootloader footprint convention used elsewhere in ST's Cube ecosystem (e.g. STM32CubeU5/B-U585I-IOT02A also uses 70K). Reduced GCC's declared length to 70K. 2. NUCLEO-H563ZI/Examples/FLASH/FLASH_SwapBanks GCC .ld declared the full 2048K (2MB) Flash region for a single bank image, while IAR .icf and the enabled Keil OCR_RVCT4 both correctly reserve only 1024K (one bank of the 2MB dual-bank device), matching the analogous FLASH_SwapBanks example on NUCLEO-H5E5ZJ where all three toolchains agree on half the flash per bank. Reduced GCC's ROM length to 1024K. 3. NUCLEO-H503RB/Examples/RAMCFG/RAMCFG_WriteProtection GCC .ld declared only 10K RAM while IAR .icf and Keil (enabled OCR_RVCT9) both declare the full 32K RAM available on this device. The equivalent example on sibling boards (NUCLEO-H533RE, NUCLEO-H563ZI) also declares the full per-device RAM in its GCC linker script, confirming 10K is a stray/incorrect value. Raised GCC's RAM length to 32K. 4. NUCLEO-H563ZI/Examples/RAMCFG/RAMCFG_ECC_Error_Generation Same pattern as STMicroelectronics#3: GCC .ld declared only 100K RAM while IAR/Keil declare the full 640K RAM of the device, and the same example on NUCLEO-H533RE/NUCLEO-H5E5ZJ declares full RAM in GCC too. Raised GCC's RAM length to 640K. 5. STM32H573I-DK/Applications/FileX/FX_IAP/IAP_binary_template This IAP application image is linked to start mid-flash at 0x08100000 (after a bootloader region). GCC .ld and the enabled Keil OCR_RVCT4 both declared a 2048K (2MB) length from that offset, which extends to 0x08300000 -- 1MB past the device's actual flash end at 0x08200000 (2MB total flash from 0x08000000). Only IAR .icf correctly bounds the region at 0x081FFFFF (1024K remaining). This is the classic "offset correctly shifted, length not shrunk to match" IAP bug pattern. Reduced both GCC and Keil to 1024K. 6. NUCLEO-H553ZG: 5 Keil applications (Fx_File_Edit_Standalone, Nx_UDP_Echo_Client, Nx_UDP_Echo_Server, Tx_LowPower, Tx_Thread_Creation) These .uvprojx files declare IROM/OCR_RVCT4 = 4096K Flash and IRAM/OCR_RVCT9 = 1536K RAM -- the memory profile of a different, larger H5 device (matches STM32H5E5ZJ/H5F5J exactly). The actual NUCLEO-H553ZG device has 1024K Flash / 304K RAM, confirmed by this board's own Templates/TrustZoneDisabled, Templates_Board, Templates_LL and every USBX example on the same board (all correctly use IROM=0x100000, IRAM=0x4c000), and matching GCC's own .ld for these same 5 applications. A Keil build of any of these 5 apps would link successfully against phantom Flash/RAM addresses that do not exist on the real NUCLEO-H553ZG hardware. Corrected the Cpu device-map string, IRAM/IROM defaults and OCR_RVCT4/OCR_RVCT9 to the verified 1024K/304K values. 7. STM32H573I-DK: Nx_Iperf_wifi and Nx_Network_Basics_wifi GCC .ld and IAR .icf both expose the device's full 640K RAM as one contiguous region. In these two Keil projects the equivalent OCR_RVCT6/OCR_RVCT7 entries already describe the correct continuation banks (0x20040000+64K, 0x20050000+320K, together with OCR_RVCT9's 256K completing exactly 640K) but Ra1Chk/Ra2Chk were left disabled, so Keil only linked against the first 256K bank. Every other NetXDuo example on this same board (Nx_MQTT_Client, Nx_TCP_Echo_Client/Server, Nx_WebServer) instead exposes the full 640K as a single IRAM entry and is unaffected. Enabled Ra1Chk/Ra2Chk to restore access to the full 640K RAM, matching GCC/IAR and the sibling examples. Not fixed (documented, left as-is): STM32H573I-DK/Applications/OpenBootloader: GCC .ld uses the full 2048K/640K (clearly an un-customized copy of the generic Template), while IAR (64K Flash/64K RAM) and Keil (128K Flash/64K RAM) agree on RAM but disagree with each other on the exact reserved Flash size. Left untouched: no reliable way to determine whether 64K or 128K is the intended bootloader Flash footprint without ST engineering input, and this project touches the TrustZone-adjacent secure-alias OCR entries, so an incorrect guess here carries more risk than benefit. Signed-off-by: 94xhn <94xhn1@gmail.com> Signed-off-by: 94xhn <87560781+94xhn@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR cross-checks the three toolchain-specific memory descriptions that exist side by side for every project in this repo — GCC (
STM32CubeIDE/*.ld), IAR (EWARM/*.icf) and Keil (MDK-ARM/*.uvprojx,OCR_RVCTxfields) — against each other and against each board's real Flash/RAM capacity (cross-referenced from that board's ownTemplates/TrustZoneDisabledproject). Because these three descriptions are maintained independently, they can drift apart; this PR fixes 8 confirmed drift bugs across 6 boards where the declared memory region for at least one toolchain either exceeded the device's physical capacity or otherwise disagreed with the other two toolchains and with sibling examples on the same board.Findings and fixes
1.
Projects/STM32H5F5J-DK/Applications/OpenBootloaderGCC's
STM32CubeIDE/STM32H5F5LJHXQ_FLASH.ldreserved 90K Flash for the bootloader. IAR'sEWARM/stm32h5f5xx_flash.icfand Keil's enabledOCR_RVCT4both reserve 70K (0x11800). 70K also matches the OpenBootloader footprint convention used elsewhere in ST's Cube ecosystem (e.g.STM32CubeU5/Projects/B-U585I-IOT02A/Applications/OpenBootloaderalso uses 70K on both GCC and IAR). Fixed GCC to 70K.2.
Projects/NUCLEO-H563ZI/Examples/FLASH/FLASH_SwapBanksGCC's
.lddeclared the full 2048K (2MB) Flash region for a single-bank swap image. IAR's.icfand Keil's enabledOCR_RVCT4both correctly reserve 1024K (one bank of this 2MB dual-bank device). The analogousFLASH_SwapBanksexample onNUCLEO-H5E5ZJhas all three toolchains agreeing on half the flash per bank, confirming the intended pattern. Fixed GCC to 1024K.3.
Projects/NUCLEO-H503RB/Examples/RAMCFG/RAMCFG_WriteProtectionGCC's
.lddeclared only 10K RAM. IAR's.icfand Keil's enabledOCR_RVCT9both declare the full 32K RAM of this device. The identical example on sibling boards (NUCLEO-H533RE,NUCLEO-H563ZI) also declares the board's full RAM in its own GCC script, confirming 10K was a stray value with no basis in the source code (the test writes to a second SRAM bank via direct pointer access, not through the linker-managed heap/BSS, so there was never a design reason to shrink the linker's RAM region). Fixed GCC to 32K.4.
Projects/NUCLEO-H563ZI/Examples/RAMCFG/RAMCFG_ECC_Error_GenerationSame pattern as #3: GCC's
.lddeclared only 100K RAM vs the full 640K RAM that IAR/Keil declare and that this device actually has. The same example onNUCLEO-H533RE/NUCLEO-H5E5ZJalso declares full RAM in GCC. Fixed GCC to 640K.5.
Projects/STM32H573I-DK/Applications/FileX/FX_IAP/IAP_binary_templateThis IAP application image links to start mid-flash at
0x08100000(after a reserved bootloader region). GCC's.ldand Keil's enabledOCR_RVCT4both declared a 2048K (2MB) length from that offset — extending to0x08300000, which is 1MB past the device's actual flash end at0x08200000(this device has 2MB total flash starting at0x08000000). Only IAR's.icfcorrectly bounds the region at0x081FFFFF(1024K remaining). This is the classic "start address correctly offset, length not shrunk to match" IAP linker bug — and notably the majority (GCC + Keil) had it wrong while IAR (the minority) was correct, so this was caught by address arithmetic rather than majority vote. Fixed GCC and Keil to 1024K.6.
Projects/NUCLEO-H553ZG: 5 Keil applications —Applications/FileX/Fx_File_Edit_Standalone,Applications/NetXDuo/Nx_UDP_Echo_Client,Applications/NetXDuo/Nx_UDP_Echo_Server,Applications/ThreadX/Tx_LowPower,Applications/ThreadX/Tx_Thread_CreationAll five
.uvprojxfiles declareIROM/OCR_RVCT4= 4096K Flash andIRAM/OCR_RVCT9= 1536K RAM — this is the exact memory profile of a different, larger H5 device (matchesSTM32H5E5ZJ/STM32H5F5Jprecisely). The realNUCLEO-H553ZGdevice has 1024K Flash / 304K RAM, confirmed by this board's ownTemplates/TrustZoneDisabled,Templates_Board,Templates_LLprojects and every one of its USBX examples (all correctly declareIROM=0x100000,IRAM=0x4c000), and matching what these same 5 applications' own GCC.ldfiles already declare. A Keil build of any of these 5 apps would link successfully against Flash/RAM addresses that simply do not exist on realNUCLEO-H553ZGhardware, which is exactly the "declared size exceeds physical capacity → link output is unsafe on real hardware" failure mode this audit targets. Corrected theCpudevice-map string,IRAM/IROMdefaults, andOCR_RVCT4/OCR_RVCT9in all 5 files to the verified 1024K/304K values.7.
Projects/STM32H573I-DK/Applications/NetXDuo:Nx_Iperf_wifiandNx_Network_Basics_wifiGCC's
.ldand IAR's.icfboth expose the device's full 640K RAM as one contiguous region. In these two Keil projects, theOCR_RVCT6/OCR_RVCT7entries already describe the correct continuation banks (0x20040000+64K,0x20050000+320K — together withOCR_RVCT9's 256K, these three exactly complete the device's 640K RAM) butRa1Chk/Ra2Chkwere left disabled, so Keil only ever linked against the first 256K bank. Every other NetXDuo example on this same board (Nx_MQTT_Client,Nx_TCP_Echo_Client,Nx_TCP_Echo_Server,Nx_WebServer) instead exposes the full 640K as a singleIRAMentry and is unaffected — confirming these two are the outliers, not the norm. EnabledRa1Chk/Ra2Chkin both files to restore the full 640K RAM, matching GCC/IAR and the sibling examples.Not fixed (documented, left as-is)
Projects/STM32H573I-DK/Applications/OpenBootloader: GCC's.lddeclares the full 2048K Flash / 640K RAM — apparently an un-customized copy of the genericTemplates/TrustZoneDisabledlinker script. IAR (64K Flash / 64K RAM) and Keil (128K Flash / 64K RAM) agree on RAM but disagree with each other on the Flash size. I could not find a reliable way to determine whether 64K or 128K is the intended bootloader Flash footprint without ST engineering input, and this project also carries a TrustZone-adjacent secure-aliasOCR_RVCT5entry, so I deliberately left this one untouched rather than guess. Flagging it here in case it's useful to a maintainer with more context.Excluded as false positives
While auditing, several apparent mismatches from an automated first pass turned out, on manual inspection, to be intentional and correct:
.icffiles (NUCLEO-H503RB/Applications/ROT/OEMiROT_Appli,Templates_ROT/OEMiROT_Appli) define their ROM region via symbolic macro expressions (CODE_OFFSET,IMAGE_HEADER_SIZE,CODE_SIZE), not literal hex — not a bug, just not naively regex-parseable.NUCLEO-H503RB/Applications/ThreadX/Tx_CMSIS_Wrapperships both a normal Flash-execution.icfand an alternate SRAM-execution.icf(stm32h503xx_sram.icf) for a code-runs-from-RAM build variant — both are intentional.NUCLEO-H5E5ZJ/Examples/FLASH/FLASH_SwapBanksandTemplates/TrustZoneEnabled— bank-swap demos and secure/non-secure TrustZone splits where all three toolchains already agree with each other and correctly sum to the device's full flash; not a bug.Test plan
No local ARM toolchain (GCC/IAR/Keil) was available to build/link these projects. All findings and fixes were verified by manual address arithmetic and cross-referencing against: (a) each board's own
Templates/TrustZoneDisabledproject (ground truth for real device Flash/RAM capacity), (b) sibling/identical examples on other boards of the same family, and (c) other unaffected projects on the same board, to distinguish genuine drift bugs from intentional non-standard memory layouts (bootloaders, bank-swap demos, TrustZone secure/non-secure splits). Every fix in this PR only reduces or corrects a declared memory region to match the other two toolchains and the verified physical device capacity — no region was shrunk below what the other two toolchains already require, and no non-standard/security-related memory layout was altered without independent corroborating evidence (see "Not fixed" above for the one case where I did not have enough confidence to act).Disclosure
This audit and these fixes were carried out with Claude (Anthropic) as an AI coding assistant, following the same GCC/IAR/Keil cross-referencing methodology previously applied across several other STM32Cube repositories. Every finding above was individually investigated and manually verified (reading each project's actual linker/project files and cross-referencing against sibling projects and each device's real memory capacity) before being classified as a genuine bug and fixed; several other automated-tool mismatches were investigated and excluded as false positives (see above) rather than "fixed" for the sake of it. I (the submitter) have reviewed all the changes in this PR and take responsibility for their correctness.