Races when disabling RX on UART on IMX.6 in half duplex

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Races when disabling RX on UART on IMX.6 in half duplex

553 Views
piotrfigiel
Contributor I

Hello,

 I'm looking to find a correct way to disable RX in the UART during TX-ing, which wouldn't be prone to any races with outside world. Below issue I describe concerns related with this scenario but I think it may be also affecting imx_shutdown when stop_rx is called currently in the imx.c code.

 I'm mostly concerned about the fact that the URXD register must not be accessed (as documented in IMX.6 RM) when RX is disabled (RXEN=0). Given stop_rx is called with interrupts disabled with spinlock held by UART core, it currently disables RX interrupts and disables RX receiver. The issue is that in the following sequence:

1. Acquire spinlock, disable local interrupts,
2. Disable RX receiver (RXEN=0 in UCR2),
3. Disable RX interrupt (RRDYEN -> 0 in UCR1),
4. Release spinlock, reenable interrupts.

The RX fifo may become not empty after point #1 but before #2 or #3. This will raise interrupt which will be handled after re-enabling interrupts (after #4). ISR in this case will check the status bit of the interrupt and fetch RX FIFO contents, which I understand is forbidden by the documentation and may rise error on the bus.

The solution for the above problem seems to be to change the procedure so that it's:

1. Acquire spinlock, disable local interrupts,
2. Disable RX interrupt,
3. Fetch RX fifo contents,
4. Disable RX receiver,
5. Check if RX fifo is not-empty by use of USR2, if it's not-empty it means the characters were not added between steps #3 and #4. If RX FIFO is not empty re-enable RX receiver and go to 3. Otherwise continue.
6. Release spinlock, reenable interrupts.

I wonder is this the only way to do that, as it doesn't seem clean. Other option would be to check in the ISR whether the RX is enabled before getting FIFO contents, but what would be correct behavior if it is not empty? (Interrupt would be handled but FIFO contents wouldn't be cleaned, when those should be fetched?).

Could you please comment?

Best regards, Piotr.

Labels (1)
0 Kudos
1 Reply

406 Views
art
NXP Employee
NXP Employee

> 1. Acquire spinlock, disable local interrupts,
> 2. Disable RX interrupt,
> 3. Fetch RX fifo contents,
> 4. Disable RX receiver,
> 5. Check if RX fifo is not-empty by use of USR2, if it's not-empty it means the characters were not added between steps #3 and #4. If RX FIFO is not empty re-enable RX receiver and go to 3. Otherwise continue.
> 6. Release spinlock, reenable interrupts.

This sequence you describe seems to be the only one that allows to reliably shut down the UART RX section while TX is still running.


Have a great day,
Artur

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos