summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes B. Klinke <jbk@chromium.org>2023-01-23 15:47:38 -0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-01-25 20:38:21 +0000
commit18f8cc0d6976fe6a367fb872b848f2d311e6a4ac (patch)
treee22b3df8825c6e8ad1165eaeaa61d9c383abf713
parent4a475bcaf766d46feb9e7ef8c585d6f6336a485b (diff)
downloadchrome-ec-18f8cc0d6976fe6a367fb872b848f2d311e6a4ac.tar.gz
chip/stm32: Modification to DFU for STM32L5
The STM32L5 series behaves the same as STM32L4 to a large degree, so this CL adds code to enable RTC clock on L5 using the same register bits as on L4. The "backup registers" however, sit in a new "Tamper" component on L5, and not in the RTC component as on L4. This CL adds register declarations for the TAMP component. Lastly, jumping to the ROM bootloader with C function pointer call, as was done in jump_to_dfu(), does not work on the STM32L5 ROM bootloader (at least not on my Nucleo-X552EZ board.) The flaw seems to be that an ARM vector table contains a reset vector, and separately contains an initial value for the stack register. The previous code made no attempt at setting the stack point as the bootloader expected, and depending on how the EC code (and the STM ROM bootloader) is compiled, this may or may not work. This CL adds assembly code to set the stack pointer to the value given in the ROM header, before performing the jump. BUG=b:192262089 TEST=Upgrade firmware on STM32L5 based Nucleo board using dfu-util Change-Id: I2a871f0eaf9ea9f4c27c75ccb472cd4ff9616524 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4190164 Reviewed-by: Brian Nemec <bnemec@google.com> Tested-by: Jes Klinke <jbk@chromium.org> Commit-Queue: Jes Klinke <jbk@chromium.org>
-rw-r--r--chip/stm32/dfu_bootmanager_main.c43
-rw-r--r--chip/stm32/registers-stm32l5.h24
-rw-r--r--chip/stm32/system.c4
3 files changed, 53 insertions, 18 deletions
diff --git a/chip/stm32/dfu_bootmanager_main.c b/chip/stm32/dfu_bootmanager_main.c
index 452a7a6443..bad07c23b7 100644
--- a/chip/stm32/dfu_bootmanager_main.c
+++ b/chip/stm32/dfu_bootmanager_main.c
@@ -93,7 +93,7 @@ static void dfu_bootmanager_init(void)
{
/* enable clock on Power module */
#ifndef CHIP_FAMILY_STM32H7
-#ifdef CHIP_FAMILY_STM32L4
+#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5)
STM32_RCC_APB1ENR1 |= STM32_RCC_PWREN;
#else
STM32_RCC_APB1ENR |= STM32_RCC_PWREN;
@@ -105,7 +105,7 @@ static void dfu_bootmanager_init(void)
#elif defined(CHIP_FAMILY_STM32H7)
/* enable backup registers */
STM32_RCC_AHB4ENR |= BIT(28);
-#elif defined(CHIP_FAMILY_STM32L4)
+#elif defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5)
/* enable RTC APB clock */
STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_RTCAPBEN;
#else
@@ -118,25 +118,40 @@ static void dfu_bootmanager_init(void)
STM32_PWR_CR |= BIT(8);
}
-static void jump_to_rw(void)
+/*
+ * Load stack pointer and reset vector from an ARM vector table, and jump.
+ */
+static void jump_to_arm_reset_vector(uint32_t addr)
{
- void (*addr)(void);
-
- addr = (void (*)(void))(*((uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE +
- CONFIG_RW_MEM_OFF + 4)));
+ /*
+ * The first 32-bit entry ARM vector table is the initial value of the
+ * stack pointer, the second entry is the reset vector.
+ */
+ asm("mov r1, %0\n"
+ /* Load stack pointer */
+ "ldr r0, [r1, 0]\n"
+ "msr msp, r0\n"
+ /* Load reset vector */
+ "ldr r0, [r1, 4]\n"
+ /* Jump without saving return address (would modify msp) */
+ "bx r0\n"
+ : /* no outputs */
+ : "r"(addr)
+ :);
+}
- addr();
+static void jump_to_rw(void)
+{
+ jump_to_arm_reset_vector(CONFIG_PROGRAM_MEMORY_BASE +
+ CONFIG_RW_MEM_OFF);
}
static void jump_to_dfu(void)
{
- void (*addr)(void);
-
- addr = (void (*)(void))(*((uint32_t *)(STM32_DFU_BASE + 4)));
-
/* Clear the scratchpad. */
dfu_bootmanager_backup_write(DFU_BOOTMANAGER_VALUE_CLEAR);
- addr();
+
+ jump_to_arm_reset_vector(STM32_DFU_BASE);
}
/*
@@ -159,7 +174,7 @@ int main(void)
* shortly after the jump. If the application is corrupt and fails before
* this, the only action that can be done is jumping into DFU mode.
*/
-void exception_panic(void)
+void __keep exception_panic(void)
{
dfu_bootmanager_enter_dfu();
}
diff --git a/chip/stm32/registers-stm32l5.h b/chip/stm32/registers-stm32l5.h
index 45f333951b..9a5fe75c95 100644
--- a/chip/stm32/registers-stm32l5.h
+++ b/chip/stm32/registers-stm32l5.h
@@ -132,6 +132,7 @@
#define STM32_RTC_BASE (APB1PERIPH_BASE + 0x2800UL)
#define STM32_WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL)
#define STM32_IWDG_BASE (APB1PERIPH_BASE + 0x3000UL)
+#define STM32_TAMP_BASE (APB1PERIPH_BASE + 0x3400UL)
#define STM32_SPI2_BASE (APB1PERIPH_BASE + 0x3800UL)
#define STM32_SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL)
#define STM32_USART2_BASE (APB1PERIPH_BASE + 0x4400UL)
@@ -2008,13 +2009,32 @@
#define STM32_RTC_TSDR REG32(STM32_RTC_BASE + 0x34)
#define STM32_RTC_TAFCR REG32(STM32_RTC_BASE + 0x40)
#define STM32_RTC_ALRMASSR REG32(STM32_RTC_BASE + 0x44)
-#define STM32_RTC_BACKUP(n) REG32(STM32_RTC_BASE + 0x50 + 4 * (n))
#define STM32_RTC_CLEAR_FLAG(x) \
(STM32_RTC_ISR = (~((x) | STM32_RTC_ISR_INIT) | \
(STM32_RTC_ISR & STM32_RTC_ISR_INIT)))
-#define STM32_BKP_DATA(n) STM32_RTC_BACKUP(n)
+/* --- Tamper and backup registers --- */
+#define STM32_TAMP_CR1 REG32(STM32_TAMP_BASE)
+#define STM32_TAMP_CR2 REG32(STM32_TAMP_BASE + 0x04)
+#define STM32_TAMP_CR3 REG32(STM32_TAMP_BASE + 0x08)
+#define STM32_TAMP_FLTCR REG32(STM32_TAMP_BASE + 0x0C)
+#define STM32_TAMP_ATCR1 REG32(STM32_TAMP_BASE + 0x10)
+#define STM32_TAMP_ATSEEDR REG32(STM32_TAMP_BASE + 0x14)
+#define STM32_TAMP_ATOR REG32(STM32_TAMP_BASE + 0x18)
+#define STM32_TAMP_ATOCR2 REG32(STM32_TAMP_BASE + 0x1C)
+#define STM32_TAMP_ATSMCR REG32(STM32_TAMP_BASE + 0x20)
+#define STM32_TAMP_PRIVCR REG32(STM32_TAMP_BASE + 0x24)
+#define STM32_TAMP_IER REG32(STM32_TAMP_BASE + 0x2C)
+#define STM32_TAMP_SR REG32(STM32_TAMP_BASE + 0x30)
+#define STM32_TAMP_MISR REG32(STM32_TAMP_BASE + 0x34)
+#define STM32_TAMP_SMISR REG32(STM32_TAMP_BASE + 0x38)
+#define STM32_TAMP_SCR REG32(STM32_TAMP_BASE + 0x3C)
+#define STM32_TAMP_COUNTR REG32(STM32_TAMP_BASE + 0x40)
+#define STM32_TAMP_CFGR REG32(STM32_TAMP_BASE + 0x50)
+#define STM32_TAMP_BACKUP(n) REG32(STM32_TAMP_BASE + 0x100 + 4 * (n))
+
+#define STM32_BKP_DATA(n) STM32_TAMP_BACKUP(n)
#define STM32_BKP_BYTES 128
#define RTC_TR_PM_POS 22U
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 53ba7c3f52..6d7c4b624a 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -271,7 +271,7 @@ void system_pre_init(void)
/* enable clock on Power module */
#ifndef CHIP_FAMILY_STM32H7
-#ifdef CHIP_FAMILY_STM32L4
+#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5)
STM32_RCC_APB1ENR1 |= STM32_RCC_PWREN;
#else
STM32_RCC_APB1ENR |= STM32_RCC_PWREN;
@@ -283,7 +283,7 @@ void system_pre_init(void)
#elif defined(CHIP_FAMILY_STM32H7)
/* enable backup registers */
STM32_RCC_AHB4ENR |= BIT(28);
-#elif defined(CHIP_FAMILY_STM32L4)
+#elif defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5)
/* enable RTC APB clock */
STM32_RCC_APB1ENR1 |= STM32_RCC_APB1ENR1_RTCAPBEN;
#else