AnsweredAssumed Answered

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

Question asked by horcicka.jan on Sep 24, 2015
Latest reply on Oct 13, 2015 by horcicka.jan
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:31.397781359 +0100
+++ /Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c  2015-09-23 20:47:19.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:31.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

Outcomes