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?
No need to. The 437 is a superset of the 417 in every way except one: the Vbat measurement using ADC1, where the resistor divider is 1/4 versus 1/2.
But the user's won't be able to exploit the additional features of the '437, like the 2D DMA engine, I2C FLTR register for controlling I2C analog and digital noise filter, Serial Audio Interface (SAI), RCC PLLSAICFGR or DCKCFGR for additional clocks (including PLLSAI oscillator), 1024k of additional Flash, SPI4, SPI5, SPI6, UART7, UART8, GPIOJ, GPIOK, AES_GCM and AES_CCM hash modes, additional HASH digest registers (8 instead of 5, so 256 bits instead of 160 bits), additional 8 Flash ACR wait latency options, voltage regulator over- and under-drive options (PWR_CSR_ODRDY, PWR_CSR_URDY), some SYSCFG_MEMRMP and SYSCFG_PMC flags (see AN4073), and increased maximum frequency from 168MHz to 180MHz?
Seems.. wasteful to me, especially because everything the user would need to do is to include the proper header file, depending on their MCU model, that can then include the corresponding stm32f?7xx.h and export the functions defined in the always-accessible boot Flash.
As discussed before, this would be much easier if split into parts, so that when the master boot loader is built, it also produces a skeleton project with correct linker script for the next level code, including user-accessible symbols for the exported functions and variables in the master boot loader. These are simple assignments of form
symbolname = runtimeaddress;. If used within an output section definition, then the address is relative to the start of that output section; if used outside the SECTIONS command, the address is absolute.
For example, if your master boot loader code exports a function named
reboot(), which is executed at address 0x08000120 (offset 0x120 from the beginning of the FLASH region), then the header file you provide needs to declare it,
extern void reboot(void) __attribute__((noreturn));and in the linker script, for the user C code to execute it, you have
reboot = 0x8000120;outside any command blocks. This does mean that each user project would need the particular headers and linker script for the currently installed master boot loader.
You can also do a jump table at a fixed address in Flash, each being exactly 4 bytes long and resolving to an unconditional branch instruction,
b.w label.
Each entry in the jump table then corresponds to a jump to a specific function exported by the master boot loader, for example the first one could be the abovementioned
reboot(). This costs one unconditional branch instruction, or four bytes, per function exported from the master boot loader to user programs, but this way their location in the Flash isn't fixed.
Then, the user can compile their code for any master boot loader version, because the actual function entry points are always the same in the jump table; the jump table itself may vary, as it is part of the master boot loader.
If you need some read-only configuration values (including the bootloader version), I recommend you put a structure at a fixed address in Flash, that contains the values, and export the structure symbol in the linker script. Pad the structure with some zeroes, so that later versions of the master boot loader can export new values, and the user code detect if their master boot loader is too old to export that value.