I often use with success a simple way to implement a bootloader:
#define START_MAGIC 0xAA55AA55 uint32_t start_application __attribute__((section=".noinit"));
void main(void) { ... if (start_application == START_MAGIC) { start_application = ~START_MAGIC; launch_application(); } /* Stay in bootloader and wait for new application from * USART, SPI, USB, whatever. */ ... start_application = START_MAGIC; ResetMCU(); /* It's NVIC_SystemReset() */ }
I don't use launch_application() after download, because I think it isn't good to start the application with some already configured peripherals (USART, SPI, USB). I know I can deinitialize peripherals and clocks before launch_application(), but the technique above it's much more simple. Of course, start_application variable shouldn't be touched after a reset, so I put it in noinit section.
Recently I tried to implement a bootloader on a LPC546XX from NXP and I noticed it didn't work. After some investigation I found that start_application variable is reset to zero immediately after ResetMCU(). After other investigation I noticed that the first 4kB space of SRAM doesn't change after a reset, while the next 4kB space is really put to zero. I changed the location of start_application variable to the first 4kB space and the bootloader started working perfectly.
This is the first time I see this behaviour, so my question.
When can you trust that internal SRAM content isn't changed when the MCU core is reset?