Page 1 of 1

Disable fifo buffers on the ESP32 UART?

Posted: Mon Nov 27, 2017 6:01 am
by OzmoOzmo
I need to send/transmit with very lot latency - for a bus protocol to connect to a legacy device (security system) I want to connect to. The protocol cannot be changed.

I need the ESP32 to wait for a message (about 16 bytes) on the UART, process it and send a small packet of data (4 bytes) in response to ack that message immediately. But the fifo buffering is causing things to get out of sync as TX messages are not sent immediately and RX responses seem only to arrive after 120 characters have filled the buffer.

Currently I see the following:
Polling for data - I only get notified when there are 120 bytes available to read.
When I send - (I can see from my oscilloscope) - it tends to not send the data Immediately - but buffers up several packets and send them together.

I need to find a way of removing the TX and RX buffering that appears to be happening. Any ideas anyone?
Thanks..

Following describes the buffering issue I'm having.

Code: Select all

byte data[]={1};

//I expect - [data][35ms silence][data][35ms silence][data]...
//but what i get is [35ms silence][data][data][data][data]...[35ms silence]
//ie. all the data is bunched together causing sync issues :(

void Test1() {
  HardwareSerial Serial1(1);
  Serial1.begin(2048, SERIAL_8N1, RXD_PIN, TXD_PIN);
  while(true)
  {
      Serial1.write(data,1);
      delay(35);
  }
}

Re: Disable fifo buffers on the ESP32 UART?

Posted: Thu Nov 30, 2017 2:49 am
by tele_player
That's not what I see. Running this code, with loopback wire from TX to RX, there's no evidence of a problem with write buffering.

Code: Select all

/*
 * From HardwareSerial.cpp, UART default pins:
 * 
    if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
        rxPin = 3;
        txPin = 1;
    }
    if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
        rxPin = 9;
        txPin = 10;
    }
    if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
        rxPin = 16;
        txPin = 17;
    }

 */
HardwareSerial hws(1);

void setup() {
  Serial.begin(115200);
  Serial.print("\n\n");
  delay(500);

  hws.begin(19200, SERIAL_8N1);
}


void loop() {

  int num;
  static int ix = 0;  
  
  hws.write('a' + ix);
  Serial.printf("sent: %c\n", 'a'+ix);
  ix = (ix + 1) % 26;

  while(!(num = hws.available())) {
    delay(10);
  }

  while(num--) {
    int c = hws.read();
    Serial.printf("rcvd: %c\n", c );
  }
  Serial.printf("---\n");

  delay(1000);

}

Re: Disable fifo buffers on the ESP32 UART?

Posted: Thu Nov 30, 2017 12:06 pm
by OzmoOzmo
Thank you for trying it -
My timings are a bit more critical.. Its a frame based protocol - and the Master device only waits a few ms before assuming the device is lost - so I need a quick response and they need to be in Request-Response sequence.

Based on your code - here is some code that shows the problem
/*
* FIFO buffering protocol Sync issue:
* UART is not sending quick enough
*
* Hardware UART pins rx = 14; tx = 12
*
* Expect: [byte][5ms pause][byte]...
* Getting: [byte][byte][byte]..[byte][big pause]
*/
HardwareSerial hws(1);

void setup() {
Serial.begin(115200);
Serial.print("\n\n");
delay(500);

hws.begin(9600, SERIAL_8N1, 12, 14);
}

void loop() {
hws.write(0x00);
delay(5); //Number chosen so will fit on my scope screen - but even larger number causes problems
}
And here is what Im seeing actually transmitted on the wire...
You can see 7 full bytes (definitely not bits) sent all together and all the pauses at the end - not 1 byte, pause, 1 byte.

It means the master device is getting responses to previous replies. The Arduino I'm porting from does not exhibit this timing issue. Thanks.

Image

Re: Disable fifo buffers on the ESP32 UART?

Posted: Fri Dec 01, 2017 2:55 am
by tele_player
I think you are seeing a limitation of using delay() for small values, not a FIFO problem.

Re: Disable fifo buffers on the ESP32 UART?

Posted: Wed Dec 13, 2017 4:01 am
by OzmoOzmo
I found the solution to at least one issue - by default the Arduino code is set to only notify you when 120 characters have arrived (or a preset timeout) - removing this latency has helped a lot to made the communications much more responsive.

Within the Arduino code - after the Serial.begin() - I used this.

Code: Select all

  #include "driver/uart.h"
  #include "soc/uart_struct.h"
  HardwareSerial Serial1(1);

  Serial1.begin(nSerialBaudKP_RX, SERIAL_8N1, SERIAL1_RXPIN, SERIAL1_TXPIN);
  //Tweek the fifo settings
  uart_intr_config_t uart_intr;
  uart_intr.intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M
                          | UART_RXFIFO_TOUT_INT_ENA_M
                          | UART_FRM_ERR_INT_ENA_M
                          | UART_RXFIFO_OVF_INT_ENA_M
                          | UART_BRK_DET_INT_ENA_M
                          | UART_PARITY_ERR_INT_ENA_M;
  uart_intr.rxfifo_full_thresh = 1; //UART_FULL_THRESH_DEFAULT,  //120 default!! aghh! need receive 120 chars before we see them
  uart_intr.rx_timeout_thresh = 10; //UART_TOUT_THRESH_DEFAULT,  //10 works well for my short messages I need send/receive
  uart_intr.txfifo_empty_intr_thresh = 10; //UART_EMPTY_THRESH_DEFAULT
  uart_intr_config(uart_num, &uart_intr);