2023-10-06 08:58 AM
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:
Is this somehow related?
Thank you.
Solved! Go to Solution.
2023-10-09 06:22 AM
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.
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
2023-10-06 09:30 AM
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.
2023-10-09 03:04 AM
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.
2023-10-09 06:22 AM
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.
2023-10-09 06:31 AM
> 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.