cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F44: UART Noise/Frame error with externel CPU clock

Corono
Associate III

Hi

I have a self designed board (STM32F44 MCU) with an UART communication. It works well as long as I configure it to use the internal clock. As soon as I switch to the external clock (oscillator), the UART communication gives a noise and frame error after each received byte. The software is the same except the clock config:

 

static void initExternalClock(void) {

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 12;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    printLogError(ERR_HalClockError, "Configuration of system clock failed");
    errorHandler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    printLogError(ERR_HalClockError, "Configuration of system clock failed");
    errorHandler();
  }
}
static void initInternalClock(void) {

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    printLogError(ERR_HalClockError, "Configuration of system clock failed");
    errorHandler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    printLogError(ERR_HalClockError, "Configuration of system clock failed");
    errorHandler();
  }
}

 

The configuration is done in a way that the core frequency is always 80MHz and does not depend on the selected clock source. I also measured the oscillator (forwarded to a GPIO ouput), it has 24MHz.

The UART configuration itself:

 

HAL_StatusTypeDef initUSART2xUART(void) {

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 4800;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_EVEN;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;

  if (HAL_UART_Init(&huart2) != HAL_OK) {
    printLogError(ERR_HalUartError,
                  "RS485 initialization of UART3 failed, error code %u",
                  huart2.ErrorCode);
    errorHandler();
  }

  initRs485DEnRePin();
  rs485SetDEnRE(ReceiverEnable);

  //Prepare for the first message
  if (HAL_UART_Receive_IT(&huart2, (uint8_t*) (&uart2Data), 1) != HAL_OK) {
    printLogError(ERR_HalUartError,
                  "Initialization of interrupt receiving of UART2 failed, error code %u",
                  huart2.ErrorCode);
    errorHandler();
  }

  //All errors are captured with error handler
  return HAL_OK;
}

 

I measured the hardware signal at the MCU input, it looks perfectly fine.

The setup: The MCU is the master, sends a message and an external device answers. The external device uses the same UART settings. The strange thing: There is an easy workaround. If I set the baud rate on the MCU to 4850 (but not on the external device), it works. For me, this seems to be some kind of sampling problem. I already tried UART_OVERSAMPLING_8, makes no difference.

Does anyone has an idea why this happens, why only with the external clock and what the solution is?

I found in the errara sheet this entry:

Corono_0-1696607734866.png

Is this somehow related?

Thank you.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Corono
Associate III

Finally found the problem. In the HAL config file, there is an entry:

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE              24000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

This value was set to 25MHz (default value). With 24MHz, it works.

 

View solution in original post

5 REPLIES 5

Show clock via MCO PA8 pin, on a scope or calibrated frequency counter.

What frequency? HSE_VALUE matches? XO or crystal? For XO use HSE_BYPASS mode

Perhaps count internal frequency via 32-bit count TIM2 or TIM5, with input-capture of a GPS/GNSS 1PPS signal

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

Seems like a subtle mismatch of clock speeds. If you have the tools to precisely determine the clock rate in each scenario, might be useful. It's possible the HSE is glitching as well, especially since this is a custom board. You might be missing it unless you're monitoring continuously. You can clock a timer with HSE and compare the speed of that vs internal HSI to determine the small differences between them.

> huart2.Init.WordLength = UART_WORDLENGTH_8B;

If you're sending 8 bit characters plus a parity bit, you should set the word length to 9 bits. Probably not the issue, just FYI as sending 7-bit characters is less common.

If you feel a post has answered your question, please click "Accept as Solution".
Corono
Associate III

Thank you for your answers.

 


@Tesla DeLorean wrote:

‎2023-10-06 09:17 AM - edited ‎2023-10-06 09:18 AM

Show clock via MCO PA8 pin, on a scope or calibrated frequency counter.

What frequency? HSE_VALUE matches? XO or crystal? For XO use HSE_BYPASS mode

Perhaps count internal frequency via 32-bit count TIM2 or TIM5, with input-capture of a GPS/GNSS 1PPS signal


That's what I did, I forwarded  the clock to the pin PA8. The clock looks good, it has 24MHz, as far as I can see with an oscilloscope, there are no glitches or missing pulses. It's a bit hard to trigger.

 


@TDK wrote:

Seems like a subtle mismatch of clock speeds. If you have the tools to precisely determine the clock rate in each scenario, might be useful. It's possible the HSE is glitching as well, especially since this is a custom board. You might be missing it unless you're monitoring continuously. You can clock a timer with HSE and compare the speed of that vs internal HSI to determine the small differences between them.

> huart2.Init.WordLength = UART_WORDLENGTH_8B;

If you're sending 8 bit characters plus a parity bit, you should set the word length to 9 bits. Probably not the issue, just FYI as sending 7-bit characters is less common.


Sorry, that was a copy/paste error, my function looks a bit different and I just made it more readable. It is configured as UART_WORDLENGTH_9B.

I can try to compare with the HSI.

 

I found two additional interesting points:

- Even the UART reports this noise/frame errors, the message is sampled correctly, the byte has the right value.

- The CAN bus on the same module works without any problem, even at higher temperatures.. It has a rate of 1Mbit/s and is therefore more critical regarding timeout.

Corono
Associate III

Finally found the problem. In the HAL config file, there is an entry:

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE              24000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

This value was set to 25MHz (default value). With 24MHz, it works.

 

TDK
Guru

> Even the UART reports this noise/frame errors, the message is sampled correctly, the byte has the right value.

UART oversamples each bit. If only one of those samples is off, a noise error is generated even though the bit will be correct. The reference manual goes into detail about this.

If you feel a post has answered your question, please click "Accept as Solution".