It is impossible to fix this cleanly at run time, because we are talking about the address space available here.
Does your end user end up including the correct stm32f417xx.h/stm32f437xx.h header?
I assume they have to, because how would they access the peripherals correctly otherwise?
The two header files define macros FLASH_BASE (0x08000000), FLASH_END (0x080FFFFF and 0x081FFFFF); and only the '437 defines SRAM3_BASE (0x20020000) and SRAM3_BB_BASE (0x22400000).
So, what I would do, is tell the users to add a specific include, after all other includes in their main source file. That file would contain for example
#ifndef thatfile_H
#define thatfile_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define DEFINE_LINKER_SYMBOL(_name) \
__attribute__ ((externally_visible, used, unavailable, section (".omit"))) \
void _name(void) { }
#if (FLASH_END - FLASH_BASE) == 0x001FFFFF
DEFINE_LINKER_SYMBOL(__device_flash_2048k);
#else
DEFINE_LINKER_SYMBOL(__device_flash_1024k);
#endif
DEFINE_LINKER_SYMBOL(__device_ccmram_64k);
#ifdef SRAM3_BASE
DEFINE_LINKER_SYMBOL(__device_ram_192k);
#else
DEFINE_LINKER_SYMBOL(__device_ram_128k);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* thatfile_H */
and start your linker script with
PROVIDE(FLASH_SIZE = DEFINED(__device_flash_2048k) ? 2048K : DEFINED(__device_flash_1024k) ? 1024K : 0);
ASSERT(FLASH_SIZE > 0, "thatfile_H not included: unknown Flash memory size!");
PROVIDE(CCMRAM_SIZE = DEFINED(__device_ccmram_64k) ? 64K : 0);
ASSERT(CCMRAM_SIZE > 0, "thatfile_H not included: unknown closely-coupled data memory size!");
PROVIDE(RAM_SIZE = DEFINED(__device_ram_192k) ? 192K : DEFINED(__device_ram_128k) ? 128K : 0);
ASSERT(RAM_SIZE > 0, "thatfile_H not included: unknown RAM size!");
MEMORY {
FLASH_BOOT (rx) : ORIGIN = 0x08000000, LENGTH = 32K
FLASH_APP (rx) : ORIGIN = ORIGIN(FLASH_BOOT) + 32K, LENGTH = FLASH_SIZE - 32K
CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = CCMRAM_SIZE
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = RAM_SIZE - 4K
RAM_L (rwx) : ORIGIN = ORIGIN(RAM) + RAM_SIZE - 4K, LENGTH = 4K
}
SECTIONS {
/DISCARD/ { *(.omit) }
}
The .omit section is discarded, so that the flag linker symbols won't use up any room in the actual binary.
Alternatively, you can create header files 32f417.h and 32f437.h, which not only include the proper stm32f4?7xx.h, but also define the symbols used by the linker script to determine the address space ranges as above.
Then, the developer-user includes just that one file (which will also include any other necessary common includes et cetera), and off they go.