From 00ef5d9344bc4359e239f780b12106bae885867e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Tue, 24 Nov 2020 16:18:17 +0100 Subject: [PATCH] bootloader: update to work with F4 --- bootloader.c | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/bootloader.c b/bootloader.c index 6aa3416..f4ac26b 100644 --- a/bootloader.c +++ b/bootloader.c @@ -2,7 +2,7 @@ * @file * @author King Kévin * @copyright SPDX-License-Identifier: GPL-3.0-or-later - * @date 2017-2019 + * @date 2017-2020 */ /* standard libraries */ #include // standard integer types @@ -17,6 +17,11 @@ #include "global.h" // board definitions #include "usb_dfu.h" // USB DFU utilities +/** symbol for beginning of the application + * @note this symbol will be provided by the bootloader linker script + */ +extern char __application_beginning; + /** bootloader entry point */ void main(void); void main(void) @@ -31,38 +36,20 @@ void main(void) __dfu_magic[1] = 0; __dfu_magic[2] = 0; __dfu_magic[3] = 0; - } else 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, this was the legacy way to start the DFU mode - dfu_force = true; } else { // check if the force DFU mode input is set // disable SWJ pin to use as GPIO #if (defined(DFU_FORCE_PIN) && defined(DFU_FORCE_VALUE)) -#if ((GPIO(B) == GPIO_PORT(DFU_FORCE_PIN)) && (GPIO(4) == GPIO_PIN(DFU_FORCE_PIN))) - // JNTRST pin is used as DFU pin - rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function domain - gpio_primary_remap(AFIO_MAPR_SWJ_CFG_FULL_SWJ_NO_JNTRST, 0); // keep SWJ enable bit don't use JNTRST -#elif ((GPIO(B) == GPIO_PORT(DFU_FORCE_PIN)) && (GPIO(3) == GPIO_PIN(DFU_FORCE_PIN))) || ((GPIO(A) == GPIO_PORT(DFU_FORCE_PIN)) && (GPIO(15) == GPIO_PIN(DFU_FORCE_PIN))) - // JTAG but not SWD pin used as DFU pin - rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function domain - gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 0); // disable JTAG but keep SWD -#elif ((GPIO(A) == GPIO_PORT(DFU_FORCE_PIN)) && (GPIO(14) == GPIO_PIN(DFU_FORCE_PIN))) || ((GPIO(A) == GPIO_PORT(DFU_FORCE_PIN)) && (GPIO(13) == GPIO_PIN(DFU_FORCE_PIN))) - // JTAG and SWD pin used as DFU pin - rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function domain - gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, 0); // disable JTAG and SWD -#endif // DFU_FORCE_PIN - rcc_periph_clock_enable(GPIO_RCC(DFU_FORCE_PIN)); // enable clock for GPIO domain - gpio_set_mode(GPIO_PORT(DFU_FORCE_PIN), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_PIN(DFU_FORCE_PIN)); // set GPIO to input - // pull on the opposite of the expected value + rcc_periph_clock_enable(GPIO_RCC(DFU_FORCE_PIN)); // enable clock for button #if (DFU_FORCE_VALUE == 1) - gpio_clear(GPIO_PORT(DFU_FORCE_PIN), GPIO_PIN(DFU_FORCE_PIN)); // pull down to be able to detect when tied to high + gpio_mode_setup(GPIO_PORT(DFU_FORCE_PIN), GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN(DFU_FORCE_PIN)); // set GPIO to input if (gpio_get(GPIO_PORT(DFU_FORCE_PIN), GPIO_PIN(DFU_FORCE_PIN))) { // check if output is set to the value to force DFU mode #else - gpio_set(GPIO_PORT(DFU_FORCE_PIN), GPIO_PIN(DFU_FORCE_PIN)); // pull up to be able to detect when tied to low + gpio_mode_setup(GPIO_PORT(DFU_FORCE_PIN), GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN(DFU_FORCE_PIN)); // set GPIO to input if (0 == gpio_get(GPIO_PORT(DFU_FORCE_PIN), GPIO_PIN(DFU_FORCE_PIN))) { // check if output is set to the value to force DFU mode #endif // DFU_FORCE_VALUE dfu_force = true; // DFU mode forced } #endif // defined(DFU_FORCE_PIN) - rcc_periph_clock_disable(RCC_AFIO); // disable alternate function domain to put it back to default rcc_periph_reset_pulse(GPIO_RST(DFU_FORCE_PIN)); // reset pin GPIO domain rcc_periph_clock_disable(GPIO_RCC(DFU_FORCE_PIN)); // disable pin GPIO domain } @@ -71,24 +58,20 @@ void main(void) /* the application starts with the vector table * the first entry in the vector table is the initial stack pointer (SP) address * the stack will be placed in RAM - * on STM32F1xx SRAM begins at 0x2000 0000, and on STM32F103xx there is up to 96 KB of RAM (0x18000). - * since the stack grown "downwards" it should start at the end of the RAM: max 0x2001 8000 + * on STM32F4 SRAM begins at 0x2000 0000, and on STM32F4xx there is up to 384 KiB of RAM (0x60000). + * since the stack grown "downwards" it should start at the end of the RAM: max 0x2006 0000 * if the SP is not in this range (e.g. flash has been erased) there is no valid application * the second entry in the vector table is the reset address, corresponding to the application start */ volatile uint32_t* application = (uint32_t*)&__application_beginning; // get the value of the application address symbol (use a register instead on the stack since the stack pointer will be changed) - if (!dfu_force && (((*application) & 0xFFFE0000) == 0x20000000)) { // application at address seems valid + if (!dfu_force && (((*application) & 0xFFF80000) == 0x20000000)) { // application at address seems valid SCB_VTOR = (volatile uint32_t)(application); // set vector table to application vector table (store at the beginning of the application) __asm__ volatile ("MSR msp,%0" : :"r"(*application)); // set stack pointer to address provided in the beginning of the application (loaded into a register first) (*(void(**)(void))((uint32_t)application + 4))(); // start application (by jumping to the reset function which address is stored as second entry of the vector table) } - rcc_clock_setup_in_hse_8mhz_out_72mhz(); // start main clock board_setup(); // setup board to control LED led_on(); // indicate bootloader started -#if defined(BUSVOODOO) - led_toggle(); // switch from blue to red LED -#endif usb_dfu_setup(); // setup USB DFU for firmware upload usb_dfu_start(); // run DFU mode }