From eb41e5e21089da6ae9d65ae75c030ed554509027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 16 Oct 2021 23:39:23 +0200 Subject: [PATCH] Implement option byte writing and set brown out level --- stm-firmware/main.c | 33 ++++++++++++++++++ stm-firmware/stm-periph/option-bytes.c | 46 ++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/stm-firmware/main.c b/stm-firmware/main.c index 373c0b0..c3b51c9 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -49,6 +49,7 @@ #include #include #include +#include static void setup_nvic_priorities(void) { @@ -211,6 +212,35 @@ static inline void handle_boot_status(void) } } +/** + * @brief Read out the option bytes of the STM32 and program them to the desired values. + * + * - This function currently forces the brown out level to Level 3. + */ +static void check_and_program_opt_bytes(void) +{ + struct option_bytes opts; + int err; + + /** - Read option bytes */ + stm_option_bytes_read(&opts); + + + if (opts.brown_out_level != 0) { + /* Set the brown out level to level 3 => highest brown out limit. */ + opts.brown_out_level = 0; + /** - Program the option bytes if brown out level was not set correctly */ + err = stm_option_bytes_program(&opts); + + /** - If programming failes, enter panic mode */ + if (err) + panic_mode(); + + /** - If programming is successful, reset the system to apply new settings */ + NVIC_SystemReset(); + } +} + /** * @brief Setup the system. * @@ -220,6 +250,9 @@ static inline void setup_system(void) { float tmp; + /** - Read the option bytes and if necessary program them to the desired values */ + check_and_program_opt_bytes(); + /** - Setup the NVIC priorities of the core peripherals using interrupts */ setup_nvic_priorities(); diff --git a/stm-firmware/stm-periph/option-bytes.c b/stm-firmware/stm-periph/option-bytes.c index 9668de5..3425726 100644 --- a/stm-firmware/stm-periph/option-bytes.c +++ b/stm-firmware/stm-periph/option-bytes.c @@ -21,6 +21,16 @@ #include #include +/** + * @brief First key for unlocking hte option byte write access + */ +#define FLASH_OPTION_KEY1 (0x08192A3BUL) + +/** + * @brief Second key for unlocking hte option byte write access + */ +#define FLASH_OPTION_KEY2 (0x4C5D6E7FUL) + void stm_option_bytes_read(struct option_bytes *opts) { uint32_t opt_reg; @@ -39,10 +49,42 @@ void stm_option_bytes_read(struct option_bytes *opts) int stm_option_bytes_program(const struct option_bytes *opts) { - FLASH->OPTKEYR = 0x08192A3BUL; - FLASH->OPTKEYR = 0x4C5D6E7FUL; + uint32_t reg; + FLASH->OPTKEYR = FLASH_OPTION_KEY1; + FLASH->OPTKEYR = FLASH_OPTION_KEY2; + + __DSB(); + + if (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) { + /* Unlocking failed */ + return -1; + } + + reg = FLASH->OPTCR; + reg &= ~FLASH_OPTCR_BOR_LEV; + reg &= ~FLASH_OPTCR_nRST_STDBY; + reg &= ~FLASH_OPTCR_nRST_STOP; + reg &= ~FLASH_OPTCR_nWRP; + reg &= ~FLASH_OPTCR_RDP; + reg &= ~FLASH_OPTCR_WDG_SW; + + reg |= (opts->brown_out_level << 2) & FLASH_OPTCR_BOR_LEV; + reg |= (opts->nrst_standby << 7) & FLASH_OPTCR_nRST_STDBY; + reg |= (opts->nrst_stop << 6) & FLASH_OPTCR_nRST_STOP; + reg |= (opts->nwrpi << 16) & FLASH_OPTCR_nWRP; + reg |= (opts->read_protection << 8) & FLASH_OPTCR_RDP; + reg |= (opts->wdg_sw << 5) & FLASH_OPTCR_WDG_SW; + + while (FLASH->SR & FLASH_SR_BSY); + + FLASH->OPTCR = reg; + FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; + __DSB(); + while (FLASH->SR & FLASH_SR_BSY); FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; + + __DSB(); return 0; }