Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP8266 UART RX timeout feature issues #379

Open
casesolved-co-uk opened this issue Jan 24, 2024 · 9 comments
Open

ESP8266 UART RX timeout feature issues #379

casesolved-co-uk opened this issue Jan 24, 2024 · 9 comments

Comments

@casesolved-co-uk
Copy link

casesolved-co-uk commented Jan 24, 2024

I'm having issues with ESP8266 UART RX timeout feature. I found the post below mentioning it only works on ESP32 with 1 byte in the RX FIFO.

Is this the same with ESP8266?

I only get the issue with frames of certain lengths, the rest of the time it is working. This would explain it!

Another think: In some cases the TOUT function in the driver requires the call to uart_set_always_rx_timeout because the TOUT feature needs to leave at least one byte in the FIFO to work correctly.

Originally posted by @alisitsyn in espressif/esp-idf#8369 (comment)

@alisitsyn
Copy link

@casesolved-co-uk ,

The TOUT feature of UART is also available on ESP8266 and should work the same way as on ESP32 if I remember correctly. Some targets have some different aspects related to this feature. One aspect is how the unity of TOUT feature is defined.

Could you provide more information about your issue.

  1. The log which clarifies the issue.
  2. The configuration sequence and test code.

Thanks.

@casesolved-co-uk
Copy link
Author

casesolved-co-uk commented Jan 24, 2024

Here's what you requested.

  1. Log excerpt below
TX len 431
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 431 Start 0x55
TX len 430
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 430 Start 0x55
TX len 429
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 429 Start 0x55
TX len 428
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 428 Start 0x55
TX len 427
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 427 Start 0x55
TX len 426
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 426 Start 0x55
TX len 425
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 425 Start 0x55
TX len 424
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 424 Start 0x55
TX len 423
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 423 Start 0x55
TX len 422
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 422 Start 0x55
TX len 421
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 421 Start 0x55
TX len 420
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 420 Start 0x55
TX len 419
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 419 Start 0x55
TX len 418
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 418 Start 0x55
TX len 417
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 417 Start 0x55
TX len 416
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 416 Start 0x55
TX len 415
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 415 Start 0x55
TX len 414
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 414 Start 0x55
TX len 413
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 413 Start 0x55
TX len 412
0: RX Brk 4
1: TX End
0: RX End TO
RX Len 412 Start 0x55
TX len 411
0: RX Brk 4
1: TX End

The RX sequence doesn't end because no RX timeout interrupt is received.

  1. Configuration is ESP8266 with UARTs in loopback. I go out and in via MAX485's but you should be able to tie pin 3 (UART 0 RX) to pin 2 (UART 1 TX). The test code is in the examples directory, DMXUART_loopback2.ino which must be compiled with the main driver code.

I'm compiling in Arduino 1.8.19, just open the serial monitor to see the log output.
I suspect the issue is the RX timeout interrupt doesn't fire if the RX FIFO is completely empty.

master branch, tag 4.0.1:
DMXUART

@casesolved-co-uk
Copy link
Author

PS you might want to put a resistor between pins 2 & 3 rather than a direct short.

@alisitsyn
Copy link

Thank you for the update.

PS you might want to put a resistor between pins 2 & 3 rather than a direct short.

Ok). Unfortunately, don't have the opportunity to reproduce your results now.

I suspect the issue is the RX timeout interrupt doesn't fire if the RX FIFO is completely empty.

Yes, this is correct and I can confirm this. You need to keep at least one byte in the FIFO to be able to trigger TOUT interrupt. This is how the feature works on ESP32. The uart_set_always_rx_timeout() sets the flag to keep one byte in the buffer in the ESP32 UART driver.

@casesolved-co-uk
Copy link
Author

Yes, this is correct and I can confirm this. You need to keep at least one byte in the FIFO to be able to trigger TOUT interrupt. This is how the feature works on ESP32. The uart_set_always_rx_timeout() sets the flag to keep one byte in the buffer in the ESP32 UART driver.

This appears to be a hardware bug rather than a feature.
There are some other symptoms, the first one is quite serious:

  1. if you enable the RX timeout interrupt with data in the RX FIFO, you get an exception. This may be caused by the inability to clear the RX timeout interrupt bit, even with USIC(0) = (1 << UITO);
Exception (9):
epc1=0x402014be epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffef823 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffe40 end: 3fffffd0 offset: 0150
3fffff90:  3fffdad0 00000000 3ffeea20 402010db  
3fffffa0:  ffffffff 00000000 3ffeea20 3ffeea4c  
3fffffb0:  00000000 00000000 3ffeea20 40202048  
3fffffc0:  feefeffe feefeffe 3fffdab0 40100f7d  
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3424, room 16 
tail 0
chksum 0x2e
load 0x3fff20b8, len 40, room 8 
tail 0
chksum 0x2b
csum 0x2b
v00042b60
  1. You must clear the RX timeout interrupt, after emptying RX FIFO, either before or after enabling the interrupt because an RX timeout interrupt is set immediately

So:

  • Empty RX FIFO, Clear UITO, Enable UITO, or
  • Empty RX FIFO, Enable UITO, Clear UITO

@alisitsyn
Copy link

alisitsyn commented Jan 25, 2024

This appears to be a hardware bug rather than a feature.
There are some other symptoms, the first one is quite serious:
if you enable the RX timeout interrupt with data in the RX FIFO, you get an exception. This may be caused by the inability to clear the RX timeout interrupt bit, even with USIC(0) = (1 << UITO);

You must clear the RX timeout interrupt, after emptying RX FIFO, either before or after enabling the interrupt because an RX timeout interrupt is set immediately

So:

Empty RX FIFO, Clear UITO, Enable UITO, or
Empty RX FIFO, Enable UITO, Clear UITO

I understand your issue, but I will try to reproduce this later.

I would expect the below sequences to receive the DMX frame should work (simplified). The bit names from official ESP32 TRM are used.

  1. Initialize UART and enable the interrupts: UART_RXFIFO_FULL_INT, UART_BRK_DET_INT (only receiver is active).
  2. Set the UART_RXFIFO_FULL_THRHD = N (for example, 100 bytes). Set the UART_RX_TOUT_THRHD = NB ( number of bits on current baud rate to trigger timeout).
  3. Set the UART_ERR_WR_MASK bit, this prevents to store incorrectly received data into UART FIFO when receive the break bytes.

Interrupt handler of UART receiver:

  1. if UART_BRK_DET_INT interrupt is triggered:
  • clear the break detection interrupt flag;
  • Read all remaining bytes from the FIFO. if DMX RX start flag is set, save the remaining data into DMX buffer, else reset the buffer pointer.
  • Set DMX RX start flag;
  • Enable UART_RXFIFO_TOUT_INT interrupt;
  1. UART_RXFIFO_FULL_INT:
  • check if DMX RX start flag is set;
  • get number of bytes in the FIFO buffer = N;
  • Read (N-1) bytes from FIFO into current position of DMX buffer;
  • increase the buffer pointer, keep one byte in the FIFO to get following UART_RXFIFO_TOUT_INT;
  • Clear the UART_RXFIFO_FULL_INT flag;
  1. UART_RXFIFO_TOUT_INT:
  • check if DMX RX start flag is set;
  • clear the timeout interrupt flag;
  • get the remaining bytes from FIFO buffer and store into DMX buffer;
  • Set the corresponding DMX frame received condition, clear DMX RX start flag;
  • Disable UART_RXFIFO_TOUT_INT interrupt.

@casesolved-co-uk
Copy link
Author

Thanks for the detailed response. I have been able to finish my DMX driver by leaving a byte in the RX FIFO and only emptying when necessary thanks to your confirmation. It works very similarly to your explanation.

I just wanted you and others to be aware of the other TOUT issues.

@alisitsyn
Copy link

Thank you for update. Initially this aspect of TOUT feature was found by test during update of the UART driver. From my side I can get some details about TOUT feature from digital team and then clarify this in the documentation. Once the bug is reproducible and confirmed then we can talk about possible solution or fix.
Good luck with your project!

@casesolved-co-uk
Copy link
Author

I've had experience of faulty UART implementations in the past so is not a surprise to me.

However it would be great if the UART could be fixed in ESP32 since at some point my project will be ported and it would be great if I didn't have to work around hardware issues.

I will understand if ESP8266 is too near its end of life to be fixed. And since my ISR now works reliably it doesn't matter now anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants