Page 1 of 2

UART answer in 2ms

Posted: Wed Sep 11, 2019 1:46 am
by Wander
Hi,
I'm trying to get UART to respond within 2ms after receiving something.
But the fastest I could get was 8ms, responding immediately after any data received without processing.
Apparently the answer is scheduled rather than sent immediately.
Measuring the time between receiving something from UART and replying, I got 1.6ms, but when I monitor the pins with an oscilloscope, I see that the response only starts to be sent 8 or 9ms after the end of the received message.
These times happen with baudrate = 9600.
If I use baudrate = 19200 the response time drops in half as well.
Working in C, directly with FreeRTOS I get a 2ms response at 9600 baud, so I know it's not a hardware limitation.
Does anyone have any idea how to reduce this time?

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 5:36 am
by jimmo
Are you using UART.irq to detect the incoming data?

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 7:54 am
by Roberthh
Since the delay depends on the baud rate, it looks like a timeout behavior in the receive. Looking at the documentation of the UART irq handler, that might not help much, because that is definitely waits for a timeout, however only of one character. But maybe there's a fault there, taking bits for bytes.

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 5:54 pm
by Wander
jimmo wrote:
Wed Sep 11, 2019 5:36 am
Are you using UART.irq to detect the incoming data?
No, I'm doing this way:

Code: Select all

uart1 = UART(1,
             baudrate = 9600,
             bits = 8,
             parity = 0,    # 0 = even / 1 = odd
             stop = 1,
             tx = 4,
             rx = 5,
             txbuf = 1024,
             rxbuf = 1024)

wr1 = uart1.write
rd1 = uart1.read

def send(msg):
    snd_msgs = ('RESET',
                b'\x82\x96\x06\x01\x32\x56\x01\x00\x61',
                b'\x82\x96\x06\x01\x58\x6B\xFB\xFF\x30',
                b'\x82\x96\x06\x01\x00\x00\x00\x00\x07',
                b'\x82\x96\x06\x01\xA8\x94\x04\x00\x3F',
                b'\x82\x96\x03\x01\xB2\xB0\x00\x00\x00',
                b'\x82\x96\x03\x01\xC0\xC2\x00\x00\x00')

    ok_to_send = (msg > 0) & (msg <= 6)
    if(ok_to_send):
        wr1(snd_msgs[msg])

def teste():
    buff = None

    while(buff != b'x'):
        buff = rd1(32)
        if(buff is None):
            continue
        else:
            send(1)

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 6:03 pm
by Wander
[quote=Roberthh post_id=39326 time=1568188453 user_id=601]
Since the delay depends on the baud rate, it looks like a timeout behavior in the receive. Looking at the documentation of the UART irq handler, that might not help much, because that is definitely waits for a timeout, however only of one character. But maybe there's a fault there, taking bits for bytes.
[/quote]

Yes, taking bits for bytes.... it's possible. :o

I followed this tutorial (https://www.microdev.it/wp/en/2018/08/0 ... for-esp32/) and compiled everything from scratch again, so I could modify some files for testing.

I changed the timeouts on machine_uart.c and compile again, but the result was the same.

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 6:17 pm
by Roberthh
Did you try to use uart.any() to check, whether there is data to be read? That could be faster than read, which might have a timeout.

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 6:31 pm
by Wander
No, I'll try to use the different options for read and write to see if the timing changes.

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 6:56 pm
by Roberthh
I made a test set-up and tried to use uart.any() and it dos not change the picture.

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 7:15 pm
by Wander
Ok...
I can't test right now, but tonight I'll test all the possibilities.
Thank you for test read.any()

Re: UART answer in 2ms

Posted: Wed Sep 11, 2019 7:33 pm
by Roberthh
I have a solution:
in file machine_uart.c, add the following line after line 207:

Code: Select all

    uart_set_rx_timeout(self->uart_num, self->timeout_char);
This section should then look like:

Code: Select all

    // set timeout_char
    // make sure it is at least as long as a whole character (13 bits to be safe)
    self->timeout_char = args[ARG_timeout_char].u_int;
    uint32_t min_timeout_char = 13000 / baudrate + 1;
    if (self->timeout_char < min_timeout_char) {
        self->timeout_char = min_timeout_char;
    }
    uart_set_rx_timeout(self->uart_num, self->timeout_char);
There is a parameter for the UART constructor, which is timeout_char=xxx. The smallest accepted value is 2. Then you get a delay of ~1ms at 9600 baud. It seems that this parameter was not set for the UART.
rxtx_1ms.jpg
rxtx_1ms.jpg (64.31 KiB) Viewed 57 times