diff options
Diffstat (limited to 'ports/stm32/powerctrlboot.c')
-rw-r--r-- | ports/stm32/powerctrlboot.c | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 31dae527c1..059d2a45da 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -47,9 +47,15 @@ void stm32_system_init(void) { #endif void powerctrl_config_systick(void) { + #if defined(STM32N6) + uint32_t systick_source_freq = HAL_RCC_GetCpuClockFreq(); + #else + uint32_t systick_source_freq = HAL_RCC_GetHCLKFreq(); + #endif + // Configure SYSTICK to run at 1kHz (1ms interval) SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; - SysTick_Config(HAL_RCC_GetHCLKFreq() / 1000); + SysTick_Config(systick_source_freq / 1000); NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); #if !BUILDING_MBOOT && (defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)) @@ -410,6 +416,124 @@ void SystemClock_Config(void) { DBGMCU->CR &= ~(DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY); #endif } + +#elif defined(STM32N6) + +void SystemClock_Config(void) { + // Enable HSI. + LL_RCC_HSI_Enable(); + while (!LL_RCC_HSI_IsReady()) { + } + + // Switch the CPU clock source to HSI. + LL_RCC_SetCpuClkSource(LL_RCC_CPU_CLKSOURCE_HSI); + while (LL_RCC_GetCpuClkSource() != LL_RCC_CPU_CLKSOURCE_STATUS_HSI) { + } + + // Switch the system clock source to HSI. + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { + } + + // Disable all ICx clocks. + RCC->DIVENCR = 0x000fffff; + + // This doesn't work, VOSRDY never becomes active. + #if 0 + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); + while (!LL_PWR_IsActiveFlag_VOSRDY()) { + } + #endif + + // Enable HSE. + LL_RCC_HSE_Enable(); + while (!LL_RCC_HSE_IsReady()) { + } + + // Disable PLL1. + LL_RCC_PLL1_Disable(); + while (LL_RCC_PLL1_IsReady()) { + } + + // Configure PLL1 for use as system clock. + LL_RCC_PLL1_SetSource(LL_RCC_PLLSOURCE_HSE); + LL_RCC_PLL1_DisableBypass(); + LL_RCC_PLL1_DisableFractionalModulationSpreadSpectrum(); + LL_RCC_PLL1_SetM(MICROPY_HW_CLK_PLLM); + LL_RCC_PLL1_SetN(MICROPY_HW_CLK_PLLN); + LL_RCC_PLL1_SetP1(MICROPY_HW_CLK_PLLP1); + LL_RCC_PLL1_SetP2(MICROPY_HW_CLK_PLLP2); + LL_RCC_PLL1_SetFRACN(MICROPY_HW_CLK_PLLFRAC); + LL_RCC_PLL1P_Enable(); + + // Enable PLL1. + LL_RCC_PLL1_Enable(); + while (!LL_RCC_PLL1_IsReady()) { + } + + // Configure IC1, IC2, IC6, IC11. + LL_RCC_IC1_SetSource(LL_RCC_ICCLKSOURCE_PLL1); + LL_RCC_IC1_SetDivider(1); + LL_RCC_IC1_Enable(); + LL_RCC_IC2_SetSource(LL_RCC_ICCLKSOURCE_PLL1); + LL_RCC_IC2_SetDivider(2); + LL_RCC_IC2_Enable(); + LL_RCC_IC6_SetSource(LL_RCC_ICCLKSOURCE_PLL1); + LL_RCC_IC6_SetDivider(1); + LL_RCC_IC6_Enable(); + LL_RCC_IC11_SetSource(LL_RCC_ICCLKSOURCE_PLL1); + LL_RCC_IC11_SetDivider(1); + LL_RCC_IC11_Enable(); + + // Configure IC14 at 100MHz for slower peripherals. + LL_RCC_IC14_SetSource(LL_RCC_ICCLKSOURCE_PLL1); + LL_RCC_IC14_SetDivider(8); + LL_RCC_IC14_Enable(); + + // Enable buses. + LL_BUS_EnableClock(LL_APB5 | LL_APB4 | LL_APB3 | LL_APB2 | LL_APB1 | LL_AHB5 | LL_AHB4 | LL_AHB3 | LL_AHB2 | LL_AHB1); + LL_MISC_EnableClock(LL_PER); + + // Configure bus dividers. + LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_1); + LL_RCC_SetAPB5Prescaler(LL_RCC_APB5_DIV_1); + + // Switch the CPU clock source to IC1 (connected to PLL1). + LL_RCC_SetCpuClkSource(LL_RCC_CPU_CLKSOURCE_IC1); + while (LL_RCC_GetCpuClkSource() != LL_RCC_CPU_CLKSOURCE_STATUS_IC1) { + } + + // Switch the system clock source to IC2/IC6/IC11 (connected to PLL1). + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_IC2_IC6_IC11); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_IC2_IC6_IC11) { + } + + // ADC clock configuration, HCLK/2. + LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_HCLK); + LL_RCC_SetADCPrescaler(2 - 1); + + // USB clock configuration. + #if MICROPY_HW_ENABLE_USB + + // Select HSE/2 as output of direct HSE signal. + LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock(); + + // Select HSE/2 for OTG1 clock source. + LL_RCC_SetClockSource(LL_RCC_OTGPHY1_CLKSOURCE_HSE_DIV_2_OSC); + LL_RCC_SetClockSource(LL_RCC_OTGPHY1CKREF_CLKSOURCE_HSE_DIV_2_OSC); + LL_RCC_SetOTGPHYClockSource(LL_RCC_OTGPHY1_CLKSOURCE_HSE_DIV_2_OSC); + LL_RCC_SetOTGPHYCKREFClockSource(LL_RCC_OTGPHY1CKREF_CLKSOURCE_HSE_DIV_2_OSC); + + #endif + + // Reconfigure clock state and SysTick. + SystemCoreClockUpdate(); + powerctrl_config_systick(); +} + #elif defined(STM32WB) void SystemClock_Config(void) { |