cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Cube_FW_L0_V1.1.2 - HSI/4 (clock&UART) problem - solution

jan
Associate II
Posted on September 24, 2015 at 14:35

Hi,

there are some problems with code generated by STM32CubeMX when using HSI/4 as a system clock. STM32CubeMX generates (stm32l0xx_hal_conf.h): #define HSI_VALUE ((uint32_t)4000000) which is wrong IMO.It should be 16MHz. By generating wrong value it forces Systick to be four times faster i.e. runnning every 250us. ''SystemCoreClock'' has also wrong value of 1MHz instead of 4MHz. Changing HSI_VALUE to 16MHz fixes the clock problem, but introduces problem with UART when running UART from HSI clock. It creates wrong baudrate. it calculates value from HSI not HSI/4. Possible fix:

diff -uprN 
/Project/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c
--- 
/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c 2015-07-14 17:02:397781359 +0100
+++ /Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c 2015-09-23 20:47:415687046 +0100
@@ -1723,8 +1723,15 @@ 
void
UART_SetConfig(UART_HandleTypeDef *
case
UART_CLOCKSOURCE_PCLK1: 
huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate));
break
;
- 
case
UART_CLOCKSOURCE_HSI: 
- huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HSI_VALUE, huart->Init.BaudRate)); 
+ 
case
UART_CLOCKSOURCE_HSI:
+ 
if
((RCC->CR & RCC_CR_HSIDIVF) != 0)
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_LPUART((HSI_VALUE >> 2), huart->Init.BaudRate));
+ }
+ 
else
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HSI_VALUE, huart->Init.BaudRate));
+ }
break
; 
case
UART_CLOCKSOURCE_SYSCLK: 
huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
@@ -1748,7 +1755,14 @@ 
void
UART_SetConfig(UART_HandleTypeDef *
usartdiv = (uint32_t)(__DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate));
break
;
case
UART_CLOCKSOURCE_HSI:
- usartdiv = (uint32_t)(__DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate)); 
+ 
if
((RCC->CR & RCC_CR_HSIDIVF) != 0)
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING8((HSI_VALUE >> 2), huart->Init.BaudRate));
+ }
+ 
else
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate));
+ }
break
;
case
UART_CLOCKSOURCE_SYSCLK:
huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
@@ -1775,7 +1789,14 @@ 
void
UART_SetConfig(UART_HandleTypeDef *
huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate));
break
;
case
UART_CLOCKSOURCE_HSI: 
- huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate)); 
+ 
if
((RCC->CR & RCC_CR_HSIDIVF) != 0)
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING16((HSI_VALUE >> 2), huart->Init.BaudRate));
+ }
+ 
else
+ {
+ huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate));
+ }
break
; 
case
UART_CLOCKSOURCE_SYSCLK: 
huart->Instance->BRR = (uint32_t)(__DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate));
diff -uprN 
/Project/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_usart.c
--- 
/Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_usart.c 2015-07-14 17:02:397781359 +0100
+++ /Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_usart.c 2015-09-23 20:57:00.170503984 +0100
@@ -1653,7 +1653,14 @@ 
static
void
USART_SetConfig(USART_Handle
husart->Instance->BRR = (uint16_t)(HAL_RCC_GetPCLK2Freq() / husart->Init.BaudRate);
break
;
case
USART_CLOCKSOURCE_HSI: 
- husart->Instance->BRR = (uint16_t)(HSI_VALUE / husart->Init.BaudRate); 
+ 
if
((RCC->CR & RCC_CR_HSIDIVF) != 0)
+ {
+ husart->Instance->BRR = (uint16_t)((HSI_VALUE >> 2) / husart->Init.BaudRate);
+ }
+ 
else
+ {
+ husart->Instance->BRR = (uint16_t)(HSI_VALUE / husart->Init.BaudRate);
+ }
break
; 
case
USART_CLOCKSOURCE_SYSCLK: 
husart->Instance->BRR = (uint16_t)(HAL_RCC_GetSysClockFreq() / husart->Init.BaudRate);

Cheers, Jan #stm32-stm32l0
6 REPLIES 6
Amel NASRI
ST Employee
Posted on September 30, 2015 at 16:33

Hi horcicka.jan,

The issue regarding the wrong HSI_VALUE in stm32l0xx_hal_conf.h is reported internally.

However, I don't agree with you that the calculated baudrate for USART is wrong.

In fact, all depends on the selected clock source for USART. Here, if clock source is HSI, baudrate will be calculated based on 16MHz.

If you would like to calculate baudrate based on the 4MHz, you have to set SYSCLK as UART clock source. 

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

jan
Associate II
Posted on October 05, 2015 at 14:58

Hi Mayla,

sorry for late response. For my project I need to run USART1 from HSI or HSI/4. The reason for that is to be able to wake up from stop mode. I have chosen HSI/4 to lower the power consumption. Please see screenshot/code below for my System/USART clock configuration. Case 1) STM32CubeMX generated code setsHSI_VALUE to 4MHz: SystemCoreClock is wrong (set to 1MHz) USART works fine (baudrate calculated fromHSI_VALUE - 4MHz) Case 2) Manually set HSI_VALUE to 16MHz: SystemCoreClock is right (4MHz) USART doesn't work (baudrate calculated fromHSI_VALUE - 16MHz, but should be calculated from 4MHz value) Current baudrate setting doesn't differentiate between HSI and HSI/4. It simply usesHSI_VALUE to calculate the baudrate. Kind regards, Jan

void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV4;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_RTC;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_HSI;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}

0690X00000602vMQAQ.jpg
Amel NASRI
ST Employee
Posted on October 08, 2015 at 13:07

Hi horcicka.jan,

What I want to say is that you have to set UART clock source to SYSCLK (select SYSCLK in ''USART1 Source Mux'' instead of ''HSI 16'').

This way, when you manually fix the CubeMX generated value for HSI, the USART baudrate will be correct.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

stm32cube-t
Senior III
Posted on October 09, 2015 at 14:20

Dear Jan,

Thank you for reporting this issue. Our next release STM32CubeMX 4.11 coming out within next few weeks fixes it (

HSI_VALUE value will be kept to 16MHz)

jan
Associate II
Posted on October 13, 2015 at 12:29

Thank you :)

Brieuc
Associate III

Hello everyone,

This topic is 8 year old but I just discovered that the issue is back ! The HSI_VALUE is forced to 4MHz in the compiler command line options, instead of 16MHz (defined correctly in the template code file, but cut out by a #ifndef...). Even when deleting the option manually, it comes back at the next compilation. The workaround is to edit the .mxproject file at the root of the project, and deleting the CDefines= HSI value.