2015-10-12 02:14 AM
I use the STM32L151RBT6.
I can work well with a clock initialized with the ''Code 1''HSI 32MKz or with a clock initialized with the ''Code 2'' MSI 4MHz.But I do not know how to change the clock in runtime.I would like:loop{configure to 32MHz HSIswitch to 4MHz MSIconfigure to STOP mode with RTC clocked by LSIwakeup and work to 4 MHz MSIswitch to 32MHz HSI}the ''Code 1'' and the ''Code 2'' works well only after the reset, but how do switch correctly ''32 MHz HSI'' to ''4 MHz MSI'' and go back?some advice?
(I will estimate, maybe I'm just less than 4 MHz.)
�Code 1�/* PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0); /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL); �Code 2�__IO uint32_t StartUpCounter = 0, MSIStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ /* Enable MSI */ RCC->CR |= ((uint32_t)RCC_CR_MSION); /* Wait till MSI is ready and if Time out is reached exit */ do { MSIStatus = RCC->CR & RCC_CR_MSIRDY; StartUpCounter++; } while((MSIStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_MSIRDY) != RESET) { MSIStatus = (uint32_t)0x01; } else { MSIStatus = (uint32_t)0x00; } if (MSIStatus == (uint32_t)0x01) { /* Enable 64-bit access */ FLASH->ACR |= FLASH_ACR_ACC64; /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_ACR_PRFTEN; /* Flash 1 wait state */ FLASH->ACR |= FLASH_ACR_LATENCY; /* Enable the PWR APB1 Clock */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* Select the Voltage Range 3 (1.2V) */ PWR->CR = PWR_CR_VOS; /* Wait Until the Voltage Regulator is ready */ while((PWR->CSR & PWR_CSR_VOSF) != RESET); /* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; /* Set MSI clock range */ RCC->ICSCR &= (uint32_t)((uint32_t)~(RCC_ICSCR_MSIRANGE)); RCC->ICSCR |= (uint32_t)RCC_ICSCR_MSIRANGE_6; /* Select MSI as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_MSI; /* Wait till MSI is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x00); } else { /* If MSI fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ } #clock-hsi-msi-lsi2015-10-12 10:39 AM
There is no ''4 MHz LSI'' - in the 'L15x, there is a MSI RC oscillator, which can be used as system clock and can run at 4MHz (and other frequencies); and there is a LSI RC oscillator running at 37kHz which can be used as RTC source.
Both HSI and MSI will stop during STOP mode, so there's little reason to switch between them if the only reason would be to conserve power during STOP mode. Please read carefully the RCC chapter in RM0038, and also the PWR chapter for the Stop mode. JW2015-10-13 01:18 AM
copy and paste is bad :( yes MSI I corrected (“Code2�? is MSI)
My flow is:status 1: Hi-performance - Hi-power -> 32MHz (about 10mA)status 2: Low-performance - Low-power -> 4MHz or Less (about 4mA)status 3: STOP mode in WFI with exit RTC clocked by LSI or pin EXTIThe environment determine ''Status1'' and ''Status2''.The link by Client determine ''Status3''Sincerely I have any consumption problems in STOP mode (about 1mA) , but that's another story ( maybe I open another thread) But now I want to fix this frequency switch.2015-10-13 10:41 AM
Generally, you switch on the new clock source, switch system clock to the new clock source, then shut off the old clock source. If the two timings require different FLASH latency, you can switch to the lower latency AFTER you switched to lower clock (MSI), and switch back to high latency BEFORE you switch to higher clock.
You should think also about how the timing-dependent peripherals will behave (timers, UART,...) JW2015-10-16 02:06 AM
Ok, I still have not solved some problems.
Now I would easier the question.After resuming from STOP, the clock config returns to its reset state (MSI used assystem clock).I want to go back to 32 MHz, using this code:/* PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL | RCC_CFGR_PLLDIV)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI | RCC_CFGR_PLLMUL6 | RCC_CFGR_PLLDIV3); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0); /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL); but it stop on/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0);can you give me some advice.2015-10-16 02:36 AM
As you use HSI as PLL source, make sure it is running before switching on PLL (i.e. switch on HSI and wait until it is running).
JW2015-10-16 04:57 AM
Thank you very much, now works fine, but I have to understand why USART_IT_ORE_RX when I restore USART .
I take this opportunity to ask you.It is good thing stop all peripherals before the STOP MCU and at wakeup reconfigure it ?It seems to consumes less if not stop periperal.My sequence is: Stop_User_Timer(); Stop_Measure_Timer(); SPI_Cmd(LSM303D_SPI, DISABLE); I2C_Cmd(S_EEPROM_I2C, DISABLE); I2C_Cmd(LPS25H_I2C, DISABLE); USART_IO_DeConfig(); ATOMIC_SECTION_BEGIN(); ******************* GPIO_LowPower_Config(); SysTick->CTRL = 0; Stop the sys tick to avoid interrupts SysTick_CounterCmd(SysTick_Counter_Clear); StartRtcWakeupIrq(RTC_WakeUpSecond); //////////////////////////////////////////////////////////////// PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI); //////////////////////////////////////////////////////////////// PWR_ClearFlag(PWR_FLAG_WU); Clear Wake Up flag StopRtcWakeupIrq(); RestoreClock32MHzAfterStop();++++++++++++++++++++++ Clock_Init(); // reconfigure il sysTick Restore_GPIO_Config(); ATOMIC_SECTION_END();********************** USART_IO_Config(); I2C_Cmd(LPS25H_I2C, ENABLE); I2C_Cmd(S_EEPROM_I2C, ENABLE); SPI_Cmd(LSM303D_SPI, ENABLE); Start_Measure_Timer(); Start_User_Timer();