I am working with STM32L152VD. After waking up from sleep and switching to 8Mhz. everything work properly (SPI,I2C,..) except UART. I configure it using following function:
void uart1_configuration(void) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); /* Configure USART2 pins: Rx and Tx ----------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1,ENABLE); /* Enable RXNE interrupt */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* Enable USART1 global interrupt */ NVIC_EnableIRQ(USART1_IRQn); }
It Seems UART is disabled.
I don't work with your processor but you write "and switching to 8Mhz."
How will the processor know the clock frequency used by the UART, so it knows how to compute the register values needing to fulfill this line?
USART_InitStructure.USART_BaudRate = 9600;
The UART is asynchronous, so baudrate errors means failure. SPI is synchronous so a change of master clock frequency will not be noticed unless you either overclock some device or the baudrate becomes too low to manage your required transfer needs. And a SPI slave doesn't need same internal clocking - just fast enough clocking so the internal state machine can keep up with the master SPI clock.
There is a function below used in function 'USART_Init' RCC_GetClocksFreq(&RCC_ClocksStatus); which is below:
/** * @brief Returns the frequencies of the System, AHB and APB busses clocks. * @note The frequency returned by this function is not the real frequency * in the chip. It is calculated based on the predefined constant and * the source selected by RCC_SYSCLKConfig(): * * @note If SYSCLK source is MSI, function returns values based on MSI * Value as defined by the MSI range, refer to RCC_MSIRangeConfig() * * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*) * * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**) * * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**) * or HSI_VALUE(*) multiplied/divided by the PLL factors. * * (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value * 16 MHz) but the real value may vary depending on the variations * in voltage and temperature, refer to RCC_AdjustHSICalibrationValue(). * * (**) HSE_VALUE is a constant defined in stm32l1xx.h file (default value * 8 MHz), user has to ensure that HSE_VALUE is same as the real * frequency of the crystal used. Otherwise, this function may * return wrong result. * * - The result of this function could be not correct when using fractional * value for HSE crystal. * * @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold * the clocks frequencies. * * @note This function can be used by the user application to compute the * baudrate for the communication peripherals or configure other parameters. * @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function * must be called to update the structure's field. Otherwise, any * configuration based on this function will be incorrect. * * @retval None */ void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) { uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, presc = 0, msirange = 0; /* Get SYSCLK source -------------------------------------------------------*/ tmp = RCC->CFGR & RCC_CFGR_SWS; switch (tmp) { case 0x00: /* MSI used as system clock */ msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13; RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1))); break; case 0x04: /* HSI used as system clock */ RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; break; case 0x08: /* HSE used as system clock */ RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; break; case 0x0C: /* PLL used as system clock */ /* Get PLL clock source and multiplication factor ----------------------*/ pllmul = RCC->CFGR & RCC_CFGR_PLLMUL; plldiv = RCC->CFGR & RCC_CFGR_PLLDIV; pllmul = PLLMulTable[(pllmul >> 18)]; plldiv = (plldiv >> 22) + 1; pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; if (pllsource == 0x00) { /* HSI oscillator clock selected as PLL clock source */ RCC_Clocks->SYSCLK_Frequency = (((HSI_VALUE) * pllmul) / plldiv); } else { /* HSE selected as PLL clock source */ RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE) * pllmul) / plldiv); } break; default: /* MSI used as system clock */ msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13; RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1))); break; } /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/ /* Get HCLK prescaler */ tmp = RCC->CFGR & RCC_CFGR_HPRE; tmp = tmp >> 4; presc = APBAHBPrescTable[tmp]; /* HCLK clock frequency */ RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; /* Get PCLK1 prescaler */ tmp = RCC->CFGR & RCC_CFGR_PPRE1; tmp = tmp >> 8; presc = APBAHBPrescTable[tmp]; /* PCLK1 clock frequency */ RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; /* Get PCLK2 prescaler */ tmp = RCC->CFGR & RCC_CFGR_PPRE2; tmp = tmp >> 11; presc = APBAHBPrescTable[tmp]; /* PCLK2 clock frequency */ RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; }
It seems this function fails to find SYSCLK frequency.
So debug it and return back what goes wrong.
I have used SystemCoreClockSetHSI(); to switch to high frequency. I measured this frequency from timers operation and concluded that it is exactly 8MHz. how ever it is still a question for me why it is not 16Mhz? this may be the issue USART fails to work.
As you said I began to debug and find out that 'RCC_GetClocksFreq' returns 16Mhz. but my real frequency I measured is half of this number. How can I find the reason?