bootloader: use magic value in RAM instead of peripheral

This commit is contained in:
King Kévin 2019-12-21 19:48:00 +01:00
parent 20ad271b6a
commit 1ea8b44b2b
5 changed files with 27 additions and 7 deletions

View File

@ -1,13 +1,14 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000 + 8K, LENGTH = 128K-8K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
rom (rx) : ORIGIN = 0x08000000 + 8K, LENGTH = 64K - 8K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom));
/* only provide application_end and/or flash_end if you want to force a flash size
@ -21,5 +22,7 @@ PROVIDE(__flash_end = 0);
PROVIDE(__application_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__flash_end = ORIGIN(rom) + LENGTH(rom));
PROVIDE(__dfu_magic = ORIGIN(ram) - 4);
/* include rest of the definitions for the STM32F1 family */
INCLUDE libopencm3_stm32f1.ld

View File

@ -36,9 +36,14 @@ void main(void)
{
// check of DFU mode is forced
bool dfu_force = false; // to remember if DFU mode is forced
// check if a soft boot has been used
if (0 == (RCC_CSR & 0xfc000000)) { // no reset flag present -> this was a soft reset using scb_reset_core() after clearing the flags using RCC_CSR_RMVF, very probably to start the DFU mode
// check if DFU magic DFU! has been written to RAM (e.g. by application to indicate we want to start the DFU bootloader)
if ('D' == __dfu_magic[0] && 'F' == __dfu_magic[1] && 'U' == __dfu_magic[2] && '!' == __dfu_magic[3]) { // verify if the DFU magic is set
dfu_force = true;
// clear DFU magic
__dfu_magic[0] = 0;
__dfu_magic[1] = 0;
__dfu_magic[2] = 0;
__dfu_magic[3] = 0;
} else { // check if the force DFU mode input is set
// disable SWJ pin to use as GPIO
#if (GPIO(B) == GPIO(DFU_FORCE_PORT)) && (GPIO(4) == GPIO(DFU_FORCE_PIN))

View File

@ -1,13 +1,14 @@
/* linker script for application running on STM32F103x8 micro-controller
* the STM32F103xB has 128 KB of flash starting at 0x0800 0000, and 20 KB of RAM starting at 0x2000 0000
* the USB DFU bootloader will take the first 8 KB of flash, followed by the application
* the first 4 bytes of the RAM is reserved for the DFU magic word (DFU! to start DFU bootloader)
*/
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 20K - 4
}
PROVIDE(__application_beginning = ORIGIN(rom) + LENGTH(rom));
/* only provide application_end and/or flash_end if you want to force a flash size
@ -21,5 +22,7 @@ PROVIDE(__flash_end = 0);
PROVIDE(__application_end = __application_beginning + 128K - 8K);
PROVIDE(__flash_end = __application_beginning + 128K - 8K);
PROVIDE(__dfu_magic = ORIGIN(ram) - 4);
/* include rest of the definitions for the STM32F1 family */
INCLUDE libopencm3_stm32f1.ld

View File

@ -701,6 +701,11 @@ extern char __application_end;
extern char __flash_end;
/** flag set when board user button has been pressed/released */
extern volatile bool button_flag;
/** symbol for the DFU magic word
* @note this symbol will be provided by the linker script
*/
extern char __dfu_magic[4];
/** flag set when user input is available */
extern volatile bool user_input_available;

View File

@ -280,9 +280,13 @@ static void usb_dfu_detach(usbd_device *usbd_dev, struct usb_setup_data *req)
{
(void)usbd_dev; // variable not used
(void)req; // variable not used
RCC_CSR |= RCC_CSR_RMVF; // clear reset flag for the bootloader to detect the core reset
usb_disconnect(); // USB detach (disconnect to force re-enumeration)
scb_reset_core(); // reset device (only the core, to the peripheral stay configured)
// set DFU magic
__dfu_magic[0] = 'D';
__dfu_magic[1] = 'F';
__dfu_magic[2] = 'U';
__dfu_magic[3] = '!';
scb_reset_system(); // reset system (core and peripherals)
while (true); // wait for the reset to happen
}