diff --git a/stm-firmware/include/stm-periph/option-bytes.h b/stm-firmware/include/stm-periph/option-bytes.h new file mode 100644 index 0000000..f375dda --- /dev/null +++ b/stm-firmware/include/stm-periph/option-bytes.h @@ -0,0 +1,45 @@ +/* Reflow Oven Controller + * + * Copyright (C) 2020 Mario Hüttel + * + * This file is part of the Reflow Oven Controller Project. + * + * The reflow oven controller is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * GDSII-Converter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the reflow oven controller project. + * If not, see . + */ + +#ifndef _OPTION_BYTES_H_ +#define _OPTION_BYTES_H_ + +#include + +struct option_bytes { + /* Word 1 */ + uint32_t read_protection;// : 8; + uint32_t nrst_standby;// : 1; + uint32_t nrst_stop;// : 1; + uint32_t wdg_sw;// : 1; + uint32_t brown_out_level;// : 2; + /* Word 2 */ + uint32_t nwrpi;// : 12; +}; + +/** + * @brief Read out the option bytes to structs + * @param opts + */ +void stm_option_bytes_read(struct option_bytes *opts); + +int stm_option_bytes_program(const struct option_bytes *opts); + +#endif /* _OPTION_BYTES_H_ */ 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/shell.c b/stm-firmware/shell.c index 402e00f..6d42dd3 100644 --- a/stm-firmware/shell.c +++ b/stm-firmware/shell.c @@ -45,6 +45,8 @@ #include #include #include +#include + #include #ifndef GIT_VER @@ -883,6 +885,25 @@ shellmatta_retCode_t shell_cmd_filter_alpha(const shellmatta_handle_t handle, co return SHELLMATTA_OK; } +shellmatta_retCode_t shell_cmd_print_opt_bytes(const shellmatta_handle_t handle, + const char *args, uint32_t len) +{ + (void)args; + (void)len; + struct option_bytes opts; + + stm_option_bytes_read(&opts); + + shellmatta_printf(handle, "Brown-out Level: 0x%x\r\n", opts.brown_out_level); + shellmatta_printf(handle, "nRST Standby: 0x%x\r\n", opts.nrst_standby); + shellmatta_printf(handle, "nRST Stop: 0x%x\r\n", opts.nrst_stop); + shellmatta_printf(handle, "Write Protection: 0x%x\r\n", opts.nwrpi); + shellmatta_printf(handle, "Read Protection: 0x%x\r\n", opts.read_protection); + shellmatta_printf(handle, "SW Watchdog: 0x%x\r\n", opts.wdg_sw); + + return SHELLMATTA_OK; +} + //typedef struct shellmatta_cmd //{ // char *cmd; /**< command name */ @@ -1076,6 +1097,14 @@ static shellmatta_cmd_t cmd[24] = { .helpText = "Sets the filter constant", .usageText = "filter-alpha ", .cmdFct = shell_cmd_filter_alpha, + .next = &cmd[23], + }, + { + .cmd = "print-option-bytes", + .cmdAlias = "opt-bytes", + .helpText = "Print the currently set option bytes of the STM32", + .usageText = "", + .cmdFct = shell_cmd_print_opt_bytes, .next = NULL, } }; diff --git a/stm-firmware/stm-periph/option-bytes.c b/stm-firmware/stm-periph/option-bytes.c new file mode 100644 index 0000000..3425726 --- /dev/null +++ b/stm-firmware/stm-periph/option-bytes.c @@ -0,0 +1,90 @@ +/* Reflow Oven Controller + * + * Copyright (C) 2021 Mario Hüttel + * + * This file is part of the Reflow Oven Controller Project. + * + * The reflow oven controller is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The Reflow Oven Control Firmware is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the reflow oven controller project. + * If not, see . + */ + +#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; + + if (!opts) + return; + + opt_reg = FLASH->OPTCR; + opts->brown_out_level = (opt_reg & FLASH_OPTCR_BOR_LEV) >> 2; + opts->nrst_standby = (opt_reg & FLASH_OPTCR_nRST_STDBY) >> 7; + opts->nrst_stop = (opt_reg & FLASH_OPTCR_nRST_STOP) >> 6; + opts->nwrpi = (opt_reg & FLASH_OPTCR_nWRP) >> 16; + opts->read_protection = (opt_reg & FLASH_OPTCR_RDP) >> 8; + opts->wdg_sw = (opt_reg & FLASH_OPTCR_WDG_SW) >> 5; +} + +int stm_option_bytes_program(const struct option_bytes *opts) +{ + 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; +}