Issue with UART driver

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
User avatar
lilvinz
Posts: 130
Joined: Sat Dec 21, 2013 2:56 pm
Has thanked: 1 time
Been thanked: 6 times

Issue with UART driver

Post by lilvinz »

Hi,

i have written a complex driver which exposes a BaseChannel interface of a half duplex rs485 line using the uart driver.
In this case the uarts rx and tx lines are tied together so when i want to transmit data, i have to stop rx first and
after i have received the tx2 cb (physically sent) i reenable rx.
When looking at the uart_lld implementation for STM32/UARTv1, i can see that the start and stop of rx and tx is
achieved by enabling and disabling the dma channels.
I think there is a race condition which ill try to explain:

Sending data looks like this (simplified):
1.) onotify - uartStopReceiveI(), then uartStartSendI()
2.) txend1_cb - if there is more data to send uartStartSendI()
3.) txend2_cb - uartStartReceiveI()

Receiving data looks like this (simplified):
1.) rxend_cb - uartStartReceiveI()

What happens when i have a lot of direction changes (i.e. a loopback) is, that i get rx callbacks for data which has just been sent before.
I think this happens when the set_rx_idle_loop dma is being stopped in between the reception of a byte at the uart and the restart
of the reception in 3.) which leads to a rxend_cb for this received byte which should have been dropped instead because of the prior call to uartStopReceive().
The normal case is, that the rx_idle_dma consumes the byte. In high load, this fails occasionally and thus i get an rxend_cb.

I can "fix" this by adding

Code: Select all

uartp->usart->CR1 &= ~USART_CR1_RE;

to uart_lld_stop_receive

and

Code: Select all

uartp->usart->CR1 |= USART_CR1_RE;

to uart_lld_start_receive
but dont really feel good in patching the uart_lld driver.

From a user perspective i am receiving data although i called uartStopReceive() before.
Please advise.

Thank you in advance and with best regards,

Vinz
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Issue with UART driver

Post by Giovanni »

Hi,

I have a problem with the idea that some received bytes should be discarded, each byte received byte should be notified using one of the two callbacks. Which callback is determined by timings. Because this the RX is never stopped, just the DMA channel reprogrammed.

Stopping the idle loop means that a byte being shifted in by the UART will be considered part of the next block of received data.

The only problem would be if you get an rxend_cb() *after* calling uartStopReceiveI(), that should never happen because pending RX DMA IRQs are cleared on RX DMA disable.

Giovanni
User avatar
lilvinz
Posts: 130
Joined: Sat Dec 21, 2013 2:56 pm
Has thanked: 1 time
Been thanked: 6 times

Re: Issue with UART driver

Post by lilvinz »

Giovanni wrote:The only problem would be if you get an rxend_cb() *after* calling uartStopReceiveI(), that should never happen because pending RX DMA IRQs are cleared on RX DMA disable.


Hi Giovanni,

that is what i - think - is happening. I will try to write a testcase which proves this.

Thanks and cheers,

Vinz
User avatar
lilvinz
Posts: 130
Joined: Sat Dec 21, 2013 2:56 pm
Has thanked: 1 time
Been thanked: 6 times

Re: Issue with UART driver

Post by lilvinz »

Hi again.

You can find the testcase here: https://github.com/lilvinz/ChibiOS-RT/c ... 6bc7b797c6

I modified testhal/STM32F4xx/UART to:
- no idle rx callback
- receive buffer size 1
- on button press, stop receive then send message

To reproduce it, load it on a discoveryf4 board and put a jumper on PA2 <-> PA3.
This simulates the half duplex behavior required for a rs485 implementation.
When you run the test and hit the button you will see that rxend gets called which should not happen.
Sidenote: when moving down uartStartReceiveI() inside txend2() some lines, it stops so i assume this to be a race condition.

Thanks again and with best regards,

Vinz
User avatar
lilvinz
Posts: 130
Joined: Sat Dec 21, 2013 2:56 pm
Has thanked: 1 time
Been thanked: 6 times

Re: Issue with UART driver

Post by lilvinz »

After looking at it using the debugger what happens is that
- txend2 gets called and starts uart receive
- rxend gets called for the byte which just triggered txend2 before
So one could argue that the uart driver behaves as advertised.
Do you have an idea or a hint for me then how to implement a half duplex driver while avoiding this issue?

Thanks and cheers,

Vinz
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Issue with UART driver

Post by Giovanni »

Last time I implemented an RS485 but I had to insert a 2-frames time between the TX operation and next RX phase, during the switch spurious bytes were received.

You may transmit few "idle" bytes after the transmission phase and then resynchronize on the next incoming data, it depends on the protocol of course.

Giovanni
Post Reply