summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-01-31 16:47:03 +1100
committerDamien George <damien@micropython.org>2022-01-31 18:26:55 +1100
commitc8c229b96c892ceb8ca1cf72e4a87096617ede64 (patch)
tree3a8e8c234ff8ec9e4ae1c402051620c36f85d8c6
parentc99ed8d6fa9d4429bf78bcd965ce60ee747e67c3 (diff)
stm32/mboot: Use PLL3 for USB clock source on H7 MCUs.
PLL3-Q is more reliable than PLL1-Q for the USB clock source when entering mboot from various reset states (eg power on vs MCU reset). (It was found that if the main application used PLL3-Q then sometimes the USB clock source would stay stuck on PLL3-Q and not switch to PLL1-Q after a reset.) Other related changes: - SystemCoreClockUpdate() should be called on H7 because the calculation can be involved in some cases. - __set_PRIMASK(0) should be called because on H7 the built-in ST DFU bootloader exits with IRQs disabled. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/stm32/mboot/main.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c
index 3c3e4a864..ae409168b 100644
--- a/ports/stm32/mboot/main.c
+++ b/ports/stm32/mboot/main.c
@@ -265,27 +265,48 @@ void SystemClock_Config(void) {
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) {
}
- // Configure PLL1 factors and source
- RCC->PLLCKSELR =
- MICROPY_HW_CLK_PLLM << RCC_PLLCKSELR_DIVM1_Pos
- | 2 << RCC_PLLCKSELR_PLLSRC_Pos; // HSE selected as PLL source
+ // Disable PLL3
+ __HAL_RCC_PLL3_DISABLE();
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY) != RESET) {
+ }
+
+ // Select HSE as PLLx source
+ RCC->PLLCKSELR = 2 << RCC_PLLCKSELR_PLLSRC_Pos;
+ RCC->PLLCFGR = 0;
+
+ // Configure PLL1 for use by SYSCLK
+ RCC->PLLCKSELR |= MICROPY_HW_CLK_PLLM << RCC_PLLCKSELR_DIVM1_Pos;
+ RCC->PLLCFGR |= RCC_PLLCFGR_DIVP1EN;
+ RCC->PLL1FRACR = 0;
RCC->PLL1DIVR =
(MICROPY_HW_CLK_PLLN - 1) << RCC_PLL1DIVR_N1_Pos
| (MICROPY_HW_CLK_PLLP - 1) << RCC_PLL1DIVR_P1_Pos // only even P allowed
| (MICROPY_HW_CLK_PLLQ - 1) << RCC_PLL1DIVR_Q1_Pos
| (MICROPY_HW_CLK_PLLR - 1) << RCC_PLL1DIVR_R1_Pos;
- // Enable PLL1 outputs for SYSCLK and USB
- RCC->PLLCFGR = RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN;
+ // Configure PLL3 for use by USB at Q=48MHz
+ RCC->PLLCKSELR |= MICROPY_HW_CLK_PLL3M << RCC_PLLCKSELR_DIVM3_Pos;
+ RCC->PLLCFGR |= RCC_PLLCFGR_DIVQ3EN;
+ RCC->PLL3FRACR = 0;
+ RCC->PLL3DIVR =
+ (MICROPY_HW_CLK_PLL3N - 1) << RCC_PLL3DIVR_N3_Pos
+ | (MICROPY_HW_CLK_PLL3P - 1) << RCC_PLL3DIVR_P3_Pos // only even P allowed
+ | (MICROPY_HW_CLK_PLL3Q - 1) << RCC_PLL3DIVR_Q3_Pos
+ | (MICROPY_HW_CLK_PLL3R - 1) << RCC_PLL3DIVR_R3_Pos;
- // Select PLL1-Q for USB clock source
- RCC->D2CCIP2R |= 1 << RCC_D2CCIP2R_USBSEL_Pos;
+ // Select PLL3-Q for USB clock source
+ MODIFY_REG(RCC->D2CCIP2R, RCC_D2CCIP2R_USBSEL, RCC_D2CCIP2R_USBSEL_1);
// Enable PLL1
__HAL_RCC_PLL_ENABLE();
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) {
}
+ // Enable PLL3
+ __HAL_RCC_PLL3_ENABLE();
+ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY) == RESET) {
+ }
+
// Increase latency before changing SYSCLK
if (MICROPY_HW_FLASH_LATENCY > (FLASH->ACR & FLASH_ACR_LATENCY)) {
__HAL_FLASH_SET_LATENCY(MICROPY_HW_FLASH_LATENCY);
@@ -320,7 +341,7 @@ void SystemClock_Config(void) {
;
// Update clock value and reconfigure systick now that the frequency changed
- SystemCoreClock = CORE_PLL_FREQ;
+ SystemCoreClockUpdate();
systick_init();
}
@@ -1486,6 +1507,9 @@ enter_bootloader:
// set the system clock to be HSE
SystemClock_Config();
+ // Ensure IRQs are enabled (needed coming out of ST bootloader on H7)
+ __set_PRIMASK(0);
+
#if USE_USB_POLLING
// irqs with a priority value greater or equal to "pri" will be disabled
// "pri" should be between 1 and 15 inclusive