stm32/modmachine: Allow changing AHB and APB bus frequencies on STM32WB.

For now SYSCLK cannot be changed and must remain at 64MHz.
This commit is contained in:
Damien George 2020-06-01 21:24:48 +10:00
parent 9ae50d22c9
commit 68d053c66e
2 changed files with 37 additions and 2 deletions

View File

@ -307,7 +307,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
} else { } else {
// set // set
#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4)
mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet")); mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet"));
#else #else
mp_int_t sysclk = mp_obj_get_int(args[0]); mp_int_t sysclk = mp_obj_get_int(args[0]);
@ -317,8 +317,13 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
ahb /= 2; ahb /= 2;
} }
#endif #endif
#if defined(STM32WB)
mp_int_t apb1 = ahb;
mp_int_t apb2 = ahb;
#else
mp_int_t apb1 = ahb / 4; mp_int_t apb1 = ahb / 4;
mp_int_t apb2 = ahb / 2; mp_int_t apb2 = ahb / 2;
#endif
if (n_args > 1) { if (n_args > 1) {
ahb = mp_obj_get_int(args[1]); ahb = mp_obj_get_int(args[1]);
if (n_args > 2) { if (n_args > 2) {

View File

@ -201,7 +201,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk
#endif #endif
#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { STATIC uint32_t calc_ahb_div(uint32_t wanted_div) {
#if defined(STM32H7) #if defined(STM32H7)
@ -293,6 +293,8 @@ STATIC uint32_t calc_apb2_div(uint32_t wanted_div) {
#endif #endif
} }
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) { int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) {
// Return straightaway if the clocks are already at the desired frequency // Return straightaway if the clocks are already at the desired frequency
if (sysclk == HAL_RCC_GetSysClockFreq() if (sysclk == HAL_RCC_GetSysClockFreq()
@ -455,8 +457,36 @@ set_clk:
return 0; return 0;
} }
#elif defined(STM32WB)
int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) {
// For now it's not supported to change SYSCLK (only bus dividers).
if (sysclk != HAL_RCC_GetSysClockFreq()) {
return -MP_EINVAL;
}
// Return straightaway if the clocks are already at the desired frequency.
if (ahb == HAL_RCC_GetHCLKFreq()
&& apb1 == HAL_RCC_GetPCLK1Freq()
&& apb2 == HAL_RCC_GetPCLK2Freq()) {
return 0;
}
// Calculate and configure the bus clock dividers.
uint32_t cfgr = RCC->CFGR;
cfgr &= ~(7 << RCC_CFGR_PPRE2_Pos | 7 << RCC_CFGR_PPRE1_Pos | 0xf << RCC_CFGR_HPRE_Pos);
cfgr |= calc_ahb_div(sysclk / ahb);
cfgr |= calc_apb1_div(ahb / apb1);
cfgr |= calc_apb2_div(ahb / apb2) << (RCC_CFGR_PPRE2_Pos - RCC_CFGR_PPRE1_Pos);
RCC->CFGR = cfgr;
return 0;
}
#endif #endif
#endif // !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
void powerctrl_enter_stop_mode(void) { void powerctrl_enter_stop_mode(void) {
// Disable IRQs so that the IRQ that wakes the device from stop mode is not // Disable IRQs so that the IRQ that wakes the device from stop mode is not
// executed until after the clocks are reconfigured // executed until after the clocks are reconfigured