From aea139a1004d30ebda94f6da78329baf9224a572 Mon Sep 17 00:00:00 2001 From: Dennis Marttinen Date: Tue, 7 Sep 2021 00:19:53 +0300 Subject: [PATCH 1/2] Fix RTC backup register indexing, add target-specific register and boot command According to ST's RM0008 STM32F103xx reference manual section 6.4.5 table 17 the backup registers are 32 bits wide with only the lower 16 bits being used for storing values. In addition to this, the "first" register slot is entirely reserved and there is no backup register zero, meaning that BKP_DR1 starts from an offset of 0x04. This was mostly correctly reflected in backup.c, but the 2-multiplier for the register enum throws everything off by a lot, which results in the boot command check failing to work correctly when using anything but the first backup register. BKP0 has also been removed since as described by RM0008 indexing starts at one (BKP1 is now fully equivalent to the old BKP0). I've also gone ahead and implemented support for specifying the backup register and boot command to use per-target. If not defined, options equivalent to the old behavior are used to not break existing applications. --- src/stm32f103/backup.c | 8 ++++---- src/stm32f103/backup.h | 7 ++++++- src/stm32f103/target_stm32f103.c | 12 +++++++++--- src/stm32l1/target_stm32l1.c | 13 ++++++++++--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/stm32f103/backup.c b/src/stm32f103/backup.c index 18a4c20..c120ea7 100644 --- a/src/stm32f103/backup.c +++ b/src/stm32f103/backup.c @@ -29,13 +29,13 @@ void backup_write(enum BackupRegister reg, uint32_t value) { rcc_periph_clock_enable(RCC_BKP); pwr_disable_backup_domain_write_protect(); - RTC_BKP_DR((int)reg*2) = value & 0xFFFFUL; - RTC_BKP_DR((int)reg*2+1) = (value & 0xFFFF0000UL) >> 16; + RTC_BKP_DR((int)reg) = value & 0xFFFFUL; + RTC_BKP_DR((int)reg+1) = (value & 0xFFFF0000UL) >> 16; pwr_enable_backup_domain_write_protect(); } uint32_t backup_read(enum BackupRegister reg) { - uint32_t value = ((uint32_t)RTC_BKP_DR((int)reg*2+1) << 16) - | ((uint32_t)RTC_BKP_DR((int)reg*2) << 0); + uint32_t value = (uint32_t)RTC_BKP_DR((int)reg) + | ((uint32_t)RTC_BKP_DR((int)reg+1) << 16); return value; } diff --git a/src/stm32f103/backup.h b/src/stm32f103/backup.h index c2fe2b0..739dced 100644 --- a/src/stm32f103/backup.h +++ b/src/stm32f103/backup.h @@ -20,11 +20,16 @@ #define BACKUP_H_INCLUDED enum BackupRegister { - BKP0 = 0, BKP1, BKP2, BKP3, BKP4, + BKP5, + BKP6, + BKP7, + BKP8, + BKP9, + BKP10, }; extern void backup_write(enum BackupRegister reg, uint32_t value); diff --git a/src/stm32f103/target_stm32f103.c b/src/stm32f103/target_stm32f103.c index 6948482..ba924b5 100644 --- a/src/stm32f103/target_stm32f103.c +++ b/src/stm32f103/target_stm32f103.c @@ -55,7 +55,13 @@ _Static_assert((FLASH_BASE + FLASH_SIZE_OVERRIDE >= APP_BASE_ADDRESS), "Incompatible flash size"); #endif -static const uint32_t CMD_BOOT = 0x544F4F42UL; +#ifndef REG_BOOT +#define REG_BOOT BKP1 +#endif + +#ifndef CMD_BOOT +#define CMD_BOOT 0x544F4F42UL +#endif void target_clock_setup(void) { #ifdef USE_HSI @@ -160,13 +166,13 @@ const usbd_driver* target_usb_init(void) { bool target_get_force_bootloader(void) { bool force = false; /* Check the RTC backup register */ - uint32_t cmd = backup_read(BKP0); + uint32_t cmd = backup_read(REG_BOOT); if (cmd == CMD_BOOT) { force = true; } /* Clear the RTC backup register */ - backup_write(BKP0, 0); + backup_write(REG_BOOT, 0); #if HAVE_BUTTON /* Wait some time in case the button has some debounce capacitor */ diff --git a/src/stm32l1/target_stm32l1.c b/src/stm32l1/target_stm32l1.c index 57b4825..f94bd90 100644 --- a/src/stm32l1/target_stm32l1.c +++ b/src/stm32l1/target_stm32l1.c @@ -27,8 +27,15 @@ #include "config.h" #include "backup.h" +#ifndef REG_BOOT +#define REG_BOOT BKP1 +#endif + +#ifndef CMD_BOOT +#define CMD_BOOT 0x544F4F42UL +#endif + //#define CMD_FAST_BOOT 0xfa57b007 -static const uint32_t CMD_BOOT = 0x544F4F42UL; void target_clock_setup(void) { @@ -82,11 +89,11 @@ const usbd_driver* target_usb_init(void) bool target_get_force_bootloader(void) { bool enter_bl = false; - uint32_t cmd = backup_read(BKP0); + uint32_t cmd = backup_read(REG_BOOT); if (cmd == CMD_BOOT) { enter_bl = true; } - backup_write(BKP0, 0); + backup_write(REG_BOOT, 0); #if HAVE_BUTTON #warning HAVE_BUTTON not implemented for L1 From 30e54d0322672f655d2b62fe25debc6755000d2d Mon Sep 17 00:00:00 2001 From: Dennis Marttinen Date: Fri, 10 Sep 2021 22:47:58 +0300 Subject: [PATCH 2/2] Use only one backup register for CMD_BOOT for stm32f103 based targets This is behavior is more akin to what most STM32F103xx applications wanting to enter the bootloader are accustomed to. Should retain backwards compatibility with existing applications writing to both registers, the higher one just won't be checked by the bootloader anymore. --- src/stm32f103/backup.c | 11 ++++------- src/stm32f103/backup.h | 4 ++-- src/stm32f103/target_stm32f103.c | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/stm32f103/backup.c b/src/stm32f103/backup.c index c120ea7..1137568 100644 --- a/src/stm32f103/backup.c +++ b/src/stm32f103/backup.c @@ -24,18 +24,15 @@ #define RTC_BKP_DR(reg) MMIO16(BACKUP_REGS_BASE + 4 + (4 * (reg))) -void backup_write(enum BackupRegister reg, uint32_t value) { +void backup_write(enum BackupRegister reg, uint16_t value) { rcc_periph_clock_enable(RCC_PWR); rcc_periph_clock_enable(RCC_BKP); pwr_disable_backup_domain_write_protect(); - RTC_BKP_DR((int)reg) = value & 0xFFFFUL; - RTC_BKP_DR((int)reg+1) = (value & 0xFFFF0000UL) >> 16; + RTC_BKP_DR((int)reg) = value; pwr_enable_backup_domain_write_protect(); } -uint32_t backup_read(enum BackupRegister reg) { - uint32_t value = (uint32_t)RTC_BKP_DR((int)reg) - | ((uint32_t)RTC_BKP_DR((int)reg+1) << 16); - return value; +uint16_t backup_read(enum BackupRegister reg) { + return RTC_BKP_DR((int)reg); } diff --git a/src/stm32f103/backup.h b/src/stm32f103/backup.h index 739dced..5e265a9 100644 --- a/src/stm32f103/backup.h +++ b/src/stm32f103/backup.h @@ -32,7 +32,7 @@ enum BackupRegister { BKP10, }; -extern void backup_write(enum BackupRegister reg, uint32_t value); -extern uint32_t backup_read(enum BackupRegister reg); +extern void backup_write(enum BackupRegister reg, uint16_t value); +extern uint16_t backup_read(enum BackupRegister reg); #endif diff --git a/src/stm32f103/target_stm32f103.c b/src/stm32f103/target_stm32f103.c index ba924b5..557f630 100644 --- a/src/stm32f103/target_stm32f103.c +++ b/src/stm32f103/target_stm32f103.c @@ -60,7 +60,7 @@ _Static_assert((FLASH_BASE + FLASH_SIZE_OVERRIDE >= APP_BASE_ADDRESS), #endif #ifndef CMD_BOOT -#define CMD_BOOT 0x544F4F42UL +#define CMD_BOOT 0x4F42UL #endif void target_clock_setup(void) { @@ -166,7 +166,7 @@ const usbd_driver* target_usb_init(void) { bool target_get_force_bootloader(void) { bool force = false; /* Check the RTC backup register */ - uint32_t cmd = backup_read(REG_BOOT); + uint16_t cmd = backup_read(REG_BOOT); if (cmd == CMD_BOOT) { force = true; }