Skip to main content
GDeto
Associate II
November 5, 2019
Question

Problem with STM32L4 USART and RS485. MCU misreads bytes in the line

  • November 5, 2019
  • 10 replies
  • 11156 views

Problem is solved when I put termination resistors in the stard and end of the bus but when I do not do I have a strange behavior of the MCU that I cannot explain/understand.

Below you see the screenshot of Yellow: RS485 bus, Blue: The RX Line on the MCU.

0690X00000Arg3wQAB.png

This is a 115200 Baudrate, Even Parity, 1 Stop Bit, 8 bit communication.

All the bytes are translated correctly every time (10mil messages exchanged) BUT the very last one sometimes it is not interpreted correctly.

You see that the oscilloscope finds this message as 0x04 or 0b00100000.

The MCU finds it 0x82 or 0b01000001. I looks like shifted by one bit to the left, including its parity bit.

I consider that this is caused by the glitch at the end of the message.... but if you see this is after the stop bit! So I do not really understand this behavior...

I am not using DMA, this is a byte by byte reading, and a quick interrupt handler.

It is true that the overrun flag is triggered but I cannot really tell why..

This is when the last byte is not received properly

0690X00000Arg5FQAR.png

This is when the last byte is received properly.

0690X00000Arg6WQAR.png

So my main question is...

Since this is coming from the datasheet of the MCU:

0690X00000Arg6qQAB.png

Why something in the Next Start bit which is clearly not valid is overwriting my message creating an overrun error?

Kind Regards,

Georgios Detorakis

This topic has been closed for replies.

10 replies

Tesla DeLorean
Guru
November 5, 2019

Overrun tends to imply a data byte not extracted quickly enough. Would avoid doing message processing in interrupt/callback.

Review pin state as sampled by processor, look at GPIO IDR, check not seen as oscillating. Set pin with internal pull-up.​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Ozone
Principal
November 5, 2019

> It is true that the overrun flag is triggered but I cannot really tell why..

As noted, it looks like you spend too much time in the handler.

Perhaps triggering some elaborate cecks/calculations on receiving a message-end character.

GDeto
GDetoAuthor
Associate II
November 5, 2019

The Byte is collected in the --> void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

It is added to a buffer and there is another loop in the background that process this buffer with different priority of course.

The Serial Interrupts have higher Priority.

The Reason that I do not believe has to do with the handler time spent is because when I put the termination resistor I never see this problem again.... and the issue then seems to be related with the glitch. I cannot understand how the glitch can cause an overrun..

It is already using a pull up resistor.

I am using the 64MHz Clock Configuration.

Since it is using oversampling of 16 I cannot see how to check that the value is oscillating on the GPIO IDR.

I am not really sure I understood the last sentence above from Ozone:

"Perhaps triggering some elaborate cecks/calculations on receiving a message-end character"

Thanks

Ozone
Principal
November 5, 2019

> The Reason that I do not believe has to do with the handler time spent is because when I put the termination resistor I never see this problem again.... and the issue then seems to be related with the glitch. I cannot understand how the glitch can cause an overrun..

Only if the glitch causes the noise to be interpreted as valid frame by the UART peripheral.

Is the cable properly twisted or shielded ?

How long is it ?

A rectangular signal at 112500 bps requires frequency components at least up to 10MHz, thus more then appr. 20cm are already a "long cable".

> I am not really sure I understood the last sentence above from Ozone:

> "Perhaps triggering some elaborate cecks/calculations on receiving a message-end character"

Other, seemingly inexperienced users present code were things like "printf ('received characters')" appear in the interrupt context (usually an interrupt callback), breaking the code.

Your post does not look like you falling into this easy trap. Just saying.

GDeto
GDetoAuthor
Associate II
November 5, 2019

Hi Ozone,

In this thread I am not trying to solve the glitch from the Bus.

I am trying to understand why the USART is not working in the same way as I would expect a USART to work...

The Code was stripped down to the following to find it again when it happens:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

 {

 if(huart->Instance == USART1)

  {

uint8_t _ReceivedValue = IDCPrxbyte; // Get the Actual Received Value

if(_ReceivedValue == 0x04) // Received End of Transmission Message

// Enable a GPIO

else if(_ReceivedValue == 0x82) // Received End of Transmission Message

// Enable another GPIO

HAL_UART_Receive_IT(phidcp,&IDCPrxbyte,1);

  }

 }

I would not expect that this would consume any time..... But it still happens!

My Question how can it be any valid frame if the graph below is showing the following0690X00000ArhCkQAJ.png

The Glitch Duration is as shown below:

0690X00000ArhCuQAJ.png

This is 264ns.... the duration of each oversampling 16 is already double 562ns and it needs to find a few to identify this is an actual start bit...

Am I seeing something wrong here?

Additionally if I connect an FTDI 3.3V to USB I do not see any additional messages reported by the PC Serial Port and the message is interpreted correctly (I understand that the MCU does not have a Buffer / FIFO but at least it confirms that the proper message is sent in the BUS and my PC Serial Port does not see the "additional messages" the MCU sees in the bus)

waclawek.jan
Super User
November 5, 2019

What's your primary clock source, HSE or MSI?

JW

GDeto
GDetoAuthor
Associate II
November 5, 2019

I am using the HSI.

I am new to the ST family so I hope I am not doing something wrong with the timing.

I post the complete System Clock Configuration

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI; //64MHz

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 = 1;

RCC_OscInitStruct.PLL.PLLN = 8;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

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_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) //if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

{

}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_LPUART1|RCC_PERIPHCLK_I2C1;

PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;

PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;

PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;

// PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_MSI;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // Configure the Systick interrupt time //

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); // Configure the Systick //

//  /* Enable MSI Auto calibration */

// HAL_RCCEx_EnableMSIPLLMode();

HAL_NVIC_SetPriority(SysTick_IRQn, 3, 0); // SysTick_IRQn interrupt configuration //

}

GDeto
GDetoAuthor
Associate II
November 5, 2019

Some Additional Information.

I added two debug Points for the Interrupts ( Green & Pink Signals )

Yellow: The RS485 Bus

Green: void USART1_IRQHandler_TX_RX(void)

Pink: void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

Blue: Rx

Scenario with the glich[Problem on Last Measurement]

0690X00000AriJrQAJ.png

Scenario without the glich[Correct Information]

0690X00000AriK1QAJ.png

What you can see over here is that the interrupt when I have a glich is happening much later than when there is no glich.

I want to believe that there is a configuration I have is wrong but for the moment I do not know where shall I look into.

The Start Bit, the Data the Parity and the Stop Bit are all there and there is a glich ... so why the original message is shifted? Looks like the timing is not very well respected or I do not understand something in the manual.

Tesla DeLorean
Guru
November 5, 2019

What else could be causing a service delay in the IRQ Handler firing? Interrupt for ORE or NE rather than RXNE? If the USART has a FIFO make sure to loop to ensure it is empty.

Does look to have a large negative spike on the top trace view.

I've seen line noise generate spurious characters, not sure I've seen overruns.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
GDeto
GDetoAuthor
Associate II
November 5, 2019

Honestly it is the SysTick every 1ms and clearing the Watchdog there.. Nothing else that I am aware of..

Additionally the USART are the only with the 0 Priority so I would expect that it fires fast.

It looks as it fires fast though unless there is this glitch at the end

waclawek.jan
Super User
November 5, 2019

HSI is not precise enough. When receiving a longer string of characters transmitted back-to-back by a precisely timed transmitted, using USART with clock slow enough that the error within one frame accumulates to more than half a bit time (and perhaps even slightly less, depending on how exactly the startbit detection is implemented), starts gradually shifting out the startbit detection into the next frame's startibit, and the error accumulates across the subsequent frames, up to the point when the startbit is detected actually inside the first data bit. At that moment the next frame is received shifted one bit.

Solution is simple and definitive: use HSE, get a crystal.

Or, if you are willing to undergo the torture, fine-tune the RC oscillators from whatever precision timing source you may have (e.g. LSE), or autobaud the USART.

JW

GDeto
GDetoAuthor
Associate II
November 5, 2019

Hello Jan,

thank you for the response. I also consider that it is preferred to use an external oscillator.

However if you take a look on the two pictures I attached before it is clear that there is no drifting on the clock.

It is a rather BIG change on the last character, at least this is how I interpret it.

You see the consistency of the Green Signal that it toggles every time there is a new stop bit, for all except on the last character when the glitch is present.

If there was a drift I would expect that the whole Green Signal would have been slightly shifted but it only happens for the last character. I zoomed in, they always fall exactly on the same spot...

Regards.

waclawek.jan
Super User
November 5, 2019

Okay, so what does it take to make an experiment?

Transmit from your UART - or another UART set to the same baudrate from the same clock source - and measure how long it takes.

And/or decrease the set baudrate by cca 5%, i.e. set it to 109440 Baud.

JW

GDeto
GDetoAuthor
Associate II
November 6, 2019

I put the Termination Resistor so the line is free of glitches.

So changing to 5% it really did not work

0690X00000ArkBVQAZ.png

It was detecting start bits everywhere...

Changing to 1-2% it had a very stable communication

Regarding the Timings on the MCU.

0690X00000ArkBpQAJ.png

This return message from the MCU was measured 4.99ms

This was a 52 bytes transfered each having 11bits ( Start Bit, 8 bits Info, 1 bit Parity, 1 bit Stop ) + assertion-deassertion time.

Theoretical value was calculated to 4.985us. This gives a 0.1% difference from what it should be.... I cannot believe that this is a problem of the RC.

My question is related to the Interrupt Latency. How is it possible that this glitch can cause a trouble with the the interrupt routine? I cannot see how any other part of the firmware can cause this delay to occur, there is literally nothing running in the background other than the SisTyck with priority 3 that clears the Watchdog.

And how can it sees it as an overrun if there are no more bytes in the line? It misinterpreted the glich to the startbit which does not comply with the graph in the datasheet.

kkoutso
Associate
December 16, 2020

Hi @GDeto​ ,

did you find any solution?

I am experiencing sth similar. 40ms after a break condition @9600.8N1 on the uart line the next byte (0x54) is captured as 0xF5. I can probe on the RX pin of the STM32 with usb2uart cable and see that the byte reaching that point is indeed 0x54.

Thanks.

Visitor II
September 21, 2023

We have exactly the same problem here after we swapped the controller from F103 to L431 on a board. After investigating the problem more closely, we are very sure that it is a problem with the UART/USART peripheral. A short pulse during the stop bit often results in the last byte not being recognized correctly. As a solution for the problem, we change the UART configuration to 0.5 stop bits during reception and to the desired setting during transmission.

We have set up a project that reproduces exactly this error on a NUCLEO L476 board:

https://github.com/DerDan/Stm32L4_UART_Glitch.git

Garnett.Robert
Senior III
September 21, 2023

Hi,

 

Have you tried DMA.

I use DMA whenever I process data streams from UARTS and haven't had any issues, although I haven't done any RS485.

I use the modbus timeout feature to signal end of frame for reception.

Regards

Rob.

Visitor II
September 21, 2023

Hi,

We use DMA in our production code, which is where we first observed the behavior.
We do not use DMA in the project to find the error. In this troubleshooting project, exactly one UART frame is generated using a pattern generator. This one byte is always received. However, sometimes incorrect if the UART frame is disturbed with a glitch within the stop bit. This glitch is created using the pattern generator.

We looked at the generated pattern with the oscilloscope:
However, you can only see the signal around the stop bit.

  • yellow: a signal which is high over the entire UART byte.
  • green: the generated UART byte with the glitch
  • red: high if the glitch at this position resulted in an error (from the previous runs)
  • blue: a statistcal represtation via DAC (from the previous runs)

scope_0.png

 

Based on the investigations we have carried out, we are absolutely certain that there is a bug in the USART/UART Peripheral