espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.73k stars 7.43k forks source link

Truncated UART packets when BREAK_ERROR occours #10578

Open hitecSmartHome opened 2 weeks ago

hitecSmartHome commented 2 weeks ago

Board

esp32 wrover

Device Description

psram, eth, flash etc..

Hardware Configuration

psram, eth, flash etc..

Version

latest master (checkout manually)

IDE Name

PlatformIO

Operating System

Windows 10

Flash frequency

80

PSRAM enabled

yes

Upload speed

115200

Description

I often get truncated packets on uart when accessing either the flash with LittleFS wrapper or when making an http call from client to esp32. The way I test this is that I get an interrupt from Serial1.onReceive() with 0x00 data in it when I save something to flash or when making an http request. http server uses the IDF server implementation as well as the arduino Serial wrapper.

I expect the onReceive function to call my cb only when the set timeout is triggered. It is UART_SYMBOL_TIMEOUT 1 in this case. The problem is triggered every time when I write to flash. I can access menuconfig so I made sure that the UART functions and variables are in IRAM and interrupts too.

Sketch

void Modbus::init() {
    Serial1.setRxBufferSize(MAX_RX_BUFFER_SIZE);
    Serial1.setTxBufferSize(MAX_MBUS_DATA_LENGTH);
    Serial1.begin(MBUS_BAUD, SERIAL_8N1, MBUS_RX, MBUS_TX);
    Serial1.setPins(-1, -1, -1, MBUS_RTS);
    Serial1.setMode(UART_MODE_RS485_HALF_DUPLEX);
    Serial1.setRxTimeout(MBUS_RX_TIMEOUT);

    Serial1.onReceive(
        std::bind(&Modbus::handlePacket, this),
        PACKET_TRIGGER_ONLY_ON_TIMEOUT
    );
    Serial1.onReceiveError(
        std::bind(&Modbus::handleReceiveError, this, std::placeholders::_1)
    );
}

Debug Message

Debug messages coming from my API

E (39603) Modbus: CRC error in response packet: 0x00
E (39603) Modbus: Invalid packet. Can't process it.
Raw Packet: 00
E (39608) HardwareHandler: Packet error code: 1

Other Steps to Reproduce

Give repeated modbus packets to your esp, wait for them and access the flash meanwhile.

I have checked existing issues, online documentation and the Troubleshooting Guide

hitecSmartHome commented 1 week ago

So the esp pulls the pin low after so much time that the response data is already coming. It can be because the slaves response time is really low.

TD-er commented 1 week ago

Yep that remark you made before made me realize this could be what's causing this...

hitecSmartHome commented 1 week ago

The slave response packet is already assembled by the time it receives a request and it sends as soon as it can so... I have to make the rts pin quicker. Maybe if I do not call Serial1.setPins(-1, -1, -1, MBUS_RTS); and I controll the pin it will be better. But I don't know when the data actually sent, I just put the data into the serial buffer. :/

TD-er commented 1 week ago

That is why I suggested to pull the /RE down and enable 'collision detection', so you essentially always listen.

hitecSmartHome commented 1 week ago

I wonder what @SuGlider thinks about this

TD-er commented 1 week ago

Just to summarize my hypothesis, so he doesn't have to read 50+ messages ;)

Remember, this is just an idea I got, no idea if it is the real cause. When the error occurs under some kind of load, then the "hardware" handling of the RTS pin is essentially done in software. If it is actually done in "hardware", then the load of the ESP should have nothing to do with this.

hitecSmartHome commented 1 week ago

On some request ( with long response data ) the last byte is truncated and I got two crc errors

// CRC ERROR
E (11153) Modbus: CRC error in response packet: 0x03
CRC error raw packet: : 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe
E (11159) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe
E (11176) HardwareHandler: Packet error code: 1

// ERROR PARSING
E (11182) Expander: M8 new rele info read error. Last modbus error: 1

// CRC ERROR in the next packet
E (11195) Modbus: CRC error in response packet: 0x89
CRC error raw packet: : 89
E (11197) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 89
E (11205) HardwareHandler: Packet error code: 1
E (11210) HardwareHandler: (Packet error handler) Expander not found 0x89

Fist I got a packet 03 03 20 00 05 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 03 00 00 00 02 00 00 00 03 00 00 00 02 00 00 fe with missing last byte. This resulted in a CRC error. Than I got an other packet which is the last packet last byte 89 this also resulted in a CRC error.

I don't know what truncates the packets. ESP won't send another packet until the last one is processed so it can't switch the rs485 chip to transmit mode.

But these packets are the best

E (301443) Modbus: CRC error in response packet: 0x00
CRC error raw packet: : 00
E (301444) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 00
E (301449) HardwareHandler: Packet error code: 1
SuGlider commented 1 week ago

Does handleReceiveError() get any BREAK error? I know that when UART IDF Driver gets BREAK, it breaks the way how the driver works and it could create 2 separated calls for onReceive().

Other than that, I can't imagine a good reason for this package splitting issue.

SuGlider commented 1 week ago

E (7572) uart: tout_thresh = 12 > maximum value = 1

yeap... just check it in the IDF code. ESP32 has a limit which is 15/symbol_length ==> 15/10 = 1. Other ESP32 (S2/S3/C3 etc) have not such limitation.

For SERIAL_8N1 maximum RX Timeout is always 1 symbol.

SuGlider commented 1 week ago

But these packets are the best

E (301443) Modbus: CRC error in response packet: 0x00
CRC error raw packet: : 00
E (301444) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 00
E (301449) HardwareHandler: Packet error code: 1

This error sounds like receiving an UART BREAK.

You can test break receiving using the uart loopback as in the https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Serial/OnReceiveError_BREAK_Demo/OnReceiveError_BREAK_Demo.ino example.

UART BREAK causes different behaviour when using onReceive() and onReceiveError()

SuGlider commented 1 week ago

@hitecSmartHome - Could you try running your project with BREAK disabled:

#include "driver/uart.h"
#include "hal/uart_hal.h"

void Modbus::init() {
    Serial1.setRxBufferSize(MAX_RX_BUFFER_SIZE);
    Serial1.setTxBufferSize(MAX_MBUS_DATA_LENGTH);
    Serial1.begin(MBUS_BAUD, SERIAL_8N1, MBUS_RX, MBUS_TX);
    Serial1.setPins(-1, -1, -1, MBUS_RTS);
    Serial1.setMode(UART_MODE_RS485_HALF_DUPLEX);
    Serial1.setRxTimeout(MBUS_RX_TIMEOUT);

    uart_disable_intr_mask((uart_port_t) 1, UART_INTR_BRK_DET);  // disable Serial1 BREAK INT 

    Serial1.onReceive(
        std::bind(&Modbus::handlePacket, this),
        PACKET_TRIGGER_ONLY_ON_TIMEOUT
    );
    Serial1.onReceiveError(
        std::bind(&Modbus::handleReceiveError, this, std::placeholders::_1)
    );
}
SuGlider commented 1 week ago

running the BREAK receive example I can see that receiving BREAK will add 0x00 to the received payload...

SuGlider commented 1 week ago

It is possible to write uart using break for testing (using IDF functions): int uart_write_bytes_with_break(uart_port_tuart_num, const void *src, size_t size, int brk_len)

// Write data to UART, end with a break signal with 100 uart bits baud rate length
uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100);
hitecSmartHome commented 1 week ago

Oh god i hope it is as simple as that.

Tomorrow I can test it. I dont know if i got break because i specifically do not print or log errors related to break because i got a lot of that in prev versions and it was annoying. Ofc there is a break because it has to be.

Will check it for sure thank you very much.

SuGlider commented 1 week ago

It may not be "so simple as that". Looking into that, I just guess that the issue may be related to a BREAK detection and UART adding 0x00 to the FIFO. BREAK also forces onReceive() to be called.

It will require a lot of data analysis and checking the logs.

SuGlider commented 1 week ago

@hitecSmartHome -

Also sometimes there is a 0x00 at the first byte of the data which we do not see with an oscilloscope. That 0x00 sometimes there even with this 1ms delay after an onRecive callback.

00 0e 03 01 00 00 1c 45 should be 0e 03 01 00 00 1c 45 ( address, func code, reg num, data first, data second, crc, crc ) registers are 16 bit and sending two 8 bit data. But that 0x00 is mistery still.

This is consistent with a BREAK received in the beginning of the packet transmission. As side effect, it adds a 0x00 into FIFO when a BREAK is detected. This is the HW that adds it.

Unfortunatelly, disabling BREAK INT doesn't fix this extra 0x00.

SuGlider commented 1 week ago

Fixing it would require some sort of combination of detecting the BREAK and ignoring any "extra 0x00"... Using the BREAK receive example: 1- when BREAK is received at the end of the packet: (a) BREAK Error is detected and onReceiveError callback can see all the data + extra 0x00 at the end (b) onReceive callback gets an extra 0x00 is added at the end 2- when BREAK is received at the beginning of the packet: (a) BREAK Error is detected and onReceiveError callback no data (b) onReceive callback gets an extra 0x00 is added at the beginning of the packet.

The output below considers a FIFO Full as 120 bytes.

================================
Test Case #1 BREAK at END
================================

Testing onReceive for receiving 26 bytes at 115200 baud, using RX FIFO Full = 120.
onReceive is called on both FIFO Full and RX Timeout events.
BREAK event will be sent at the END of the 26 bytes
[   678][V][HardwareSerial.cpp:276] _uartEventTask(): UART1 RX break.

-- onReceiveError [ERR#1:UART_BREAK_ERROR] 
-- onReceiveError:: There are 27 bytes available.
onReceive Callback:: There are 27 bytes available: {0x41='A' 0x42='B' 0x43='C' 0x44='D' 0x45='E' 0x46='F' 0x47='G' 0x48='H' 0x49='I' 0x4a='J' 0x4b='K' 0x4c='L' 0x4d='M' 0x4e='N' 0x4f='O' 0x50='P' 0x51='Q' 0x52='R' 0x53='S' 0x54='T' 0x55='U' 0x56='V' 0x57='W' 0x58='X' 0x59='Y' 0x5a='Z' 0x0=''}

Sent String: ABCDEFGHIJKLMNOPQRSTUVWXYZ

It has sent 26 bytes from Serial1 TX to Serial1 RX
onReceive() has read a total of 27 bytes

================================
Test Case #1 BREAK at BEGINNING
================================

Testing onReceive for receiving 26 bytes at 115200 baud, using RX FIFO Full = 120.
onReceive is called on both FIFO Full and RX Timeout events.
BREAK event will be sent at the BEGINNING of the 26 bytes
[   756][V][HardwareSerial.cpp:276] _uartEventTask(): UART1 RX break.

-- onReceiveError [ERR#1:UART_BREAK_ERROR] 
-- onReceiveError:: There are 0 bytes available.

Sent String: ABCDEFGHIJKLMNOPQRSTUVWXYZ
onReceive Callback:: There are 27 bytes available: {0x0='' 0x41='A' 0x42='B' 0x43='C' 0x44='D' 0x45='E' 0x46='F' 0x47='G' 0x48='H' 0x49='I' 0x4a='J' 0x4b='K' 0x4c='L' 0x4d='M' 0x4e='N' 0x4f='O' 0x50='P' 0x51='Q' 0x52='R' 0x53='S' 0x54='T' 0x55='U' 0x56='V' 0x57='W' 0x58='X' 0x59='Y' 0x5a='Z'}

It has sent 26 bytes from Serial1 TX to Serial1 RX
onReceive() has read a total of 27 bytes
========================
Finished!
hitecSmartHome commented 1 week ago

That is.... funny. So I need to listen to a break error and expect a 0x00 somewhere in the packet...

Break is not an error in this case. It should be there after every message since there is a packet timeout.

But why don't i get this extra byte every single time? And why is the uart acting and placing random bytes into the buffer in my behalf? Even on cases where it is an error, ( like streams ) it should not alter the buffer...

hitecSmartHome commented 1 week ago

So In my testing

void Modbus::handleReceiveError(hardwareSerial_error_t error) {
    if (error == UART_NO_ERROR) { return; }
    ESP_LOGE(MBUS_DEBUG_TAG, "Packet error code: %d", error);
    ESP_LOGE(MBUS_DEBUG_TAG, "Packet error description: %s", uartErrorStrings[error]);
    if( error == UART_BREAK_ERROR ){ return; }
    translateUartError(error);
    callErrorCb(lastPacketError);
}

I get a BREAK_ERROR after every message.

E (376014) Modbus: Packet error code: 1
E (376018) Modbus: Packet error description: UART_BREAK_ERROR
E (376025) Modbus: Packet error code: 1
E (376029) Modbus: Packet error description: UART_BREAK_ERROR
E (376036) Modbus: Packet error code: 1
E (376040) Modbus: Packet error description: UART_BREAK_ERROR
E (376046) Modbus: Packet error code: 1
E (376051) Modbus: Packet error description: UART_BREAK_ERROR
E (376057) Modbus: Packet error code: 1
E (376061) Modbus: Packet error description: UART_BREAK_ERROR
E (376068) Modbus: Packet error code: 1
E (376072) Modbus: Packet error description: UART_BREAK_ERROR

This is consistent and comes after every packet and there are no 0x00 byte in my actual packets. It does not split in half or anything.

hitecSmartHome commented 1 week ago

Previously I had this error handler like this

void Modbus::handleReceiveError(hardwareSerial_error_t error) {
    if (error == UART_NO_ERROR || error == UART_BREAK_ERROR) { return; }
    ESP_LOGE(MBUS_DEBUG_TAG, "Packet error code: %d", error);
    ESP_LOGE(MBUS_DEBUG_TAG, "Packet error description: %s", uartErrorStrings[error]);
    translateUartError(error);
    callErrorCb(lastPacketError);
}

So I ignored the BREAK_ERROR since there is a break after every message as it should be.

hitecSmartHome commented 1 week ago

What is the purpose of the onReceive callback if the framework forces me to do my own packet framing because it is unreliable and useless? UART_BREAK should not be an error in the case of UART_MODE_RS485_HALF_DUPLEX because it will fire no matter what and it should not alter my receive buffer. Now I have to implement a workaround into my packet handler to check for single 0 bytes and check the first and last byte of my packet and continue to ignore BREAK

hitecSmartHome commented 1 week ago

From this

void Modbus::handlePacket() {
    int available = Serial1.available();
    uint8_t rawPacket[available] = {0};
    int readBytes = Serial1.readBytes(rawPacket, available);
    if (!isPacketValid(rawPacket, readBytes)) {
        ESP_LOGE(MBUS_DEBUG_TAG, "Invalid packet. Can't process it.");
        utils.printRawPacket("MODBUS INVALID PACKET", rawPacket, readBytes);
        callErrorCb(rawPacket[0]);
        return;
    }
    parseScanPacket(rawPacket, readBytes);
    if (packetCallback && !isScanning) {
        packetCallback(rawPacket, readBytes);
    }
}

I can workaround the 0x00 issue like this

void Modbus::handlePacket() {
    int available = Serial1.available();
    if (available <= 0) { return; }

    uint8_t rawPacket[available] = {0};
    int readBytes = Serial1.readBytes(rawPacket, available);

    // Check and remove 0x00 at the start
    int startIdx = 0;
    if (rawPacket[0] == 0x00) {
        ESP_LOGW(MBUS_DEBUG_TAG, "Detected 0x00 at start - removing.");
        startIdx = 1; // Skip the first byte
    }

    // Check and remove 0x00 at the end
    int endIdx = readBytes;
    if (rawPacket[readBytes - 1] == 0x00) {
        ESP_LOGW(MBUS_DEBUG_TAG, "Detected 0x00 at end - removing.");
        endIdx = readBytes - 1; // Ignore the last byte
    }

    // Calculate the new length after trimming
    int trimmedLength = endIdx - startIdx;
    if (trimmedLength <= 0) {
        ESP_LOGW(MBUS_DEBUG_TAG, "Packet length is zero after trimming - ignoring packet.");
        return;
    }

    // Create a trimmed packet array if necessary
    uint8_t trimmedPacket[trimmedLength];
    memcpy(trimmedPacket, rawPacket + startIdx, trimmedLength);

    if (!isPacketValid(trimmedPacket, trimmedLength)) {
        ESP_LOGE(MBUS_DEBUG_TAG, "Invalid packet. Can't process it.");
        utils.printRawPacket("MODBUS INVALID PACKET", trimmedPacket, trimmedLength);
        callErrorCb(trimmedPacket[0]);
        return;
    }
    parseScanPacket(trimmedPacket, trimmedLength);
    if (packetCallback && !isScanning) {
        packetCallback(trimmedPacket, trimmedLength);
    }
}

This way I can detect single 0x00 or at the start or end but I still got truncated packets like this

E (11162) Modbus: CRC error in response packet: 0x03
CRC error raw packet: : 0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe
E (11175) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe
E (11198) HardwareHandler: Packet error code: 1

E (11216) Modbus: CRC error in response packet: 0x89
CRC error raw packet: : 0x89
E (11219) Modbus: Invalid packet. Can't process it.
MODBUS INVALID PACKET: 0x89
E (11227) HardwareHandler: Packet error code: 1

The driver cuts the last byte of the frame and makes an other frame with it with an other callback...

hitecSmartHome commented 1 week ago

This frame does not even overflow the buffer. This is 37 bytes and cuts the last byte.

0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe 0x89

hitecSmartHome commented 1 week ago

I must switch to interrupts handling and process the incoming bytes myself...

SuGlider commented 1 week ago

As you say, onReceive() may not fit the application needs. It works based on how IDF and the HW works, as described in https://github.com/espressif/arduino-esp32/issues/10578#issuecomment-2460210311

It may be usefull withSerial1.setRxFIFOFull(1); in order to use an async callback for each single incomming byte. Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO.

Don't bother if BREAK is called error. This is just a denomination.

hitecSmartHome commented 1 week ago

Thank you for your response and your help.

As you say, onReceive() may not fit the application needs.

What application would need a truncated/clipped frame provider callback?

Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO.

Why?

SuGlider commented 1 week ago

Anyway, regarding the initial topic of this issue, there is no relationship between HTTP / Flash Accessing Tasks and the truncated UART packets.

SuGlider commented 1 week ago

What application would need a truncated/clipped frame provider callback?

onReceive() is just a way to emulate an UART ISR (async callback). It can be configured to be used in different ways using Timeout or FIFO Full events.

Other possible application: an UART console.

Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO. Why?

This is a question for the Espressif Digital Design team... I have no answer.

SuGlider commented 1 week ago

@hitecSmartHome - thinking about the BREAK = received 0x00:

What if used Parity is ODD instead of EVEN? 0x00 ==> Start Bit + DATA + Parity Bit + STOPBIT. BREAK is when ParityBit doesn't match the necessary STOPBIT which shall be HIGH when the Line is hold LOW.

But if Parity is ODD, Parity Bit should be 1 instead of 0. Therefore you may get a BREAK associated to a PARITY error instead of BREAK error... This may work in the sense of not adding 0x00 to FIFO.

Just guessing...

SuGlider commented 1 week ago

@hitecSmartHome - thinking about the BREAK = received 0x00:

What if used Parity is ODD instead of EVEN? 0x00 ==> Start Bit + DATA + Parity Bit + STOPBIT. BREAK is when ParityBit doesn't match the necessary STOPBIT which shall be HIGH when the Line is hold LOW.

But if Parity is ODD, Parity Bit should be 1 instead of 0. Therefore you may get a BREAK associated to a PARITY error instead of BREAK error... This may work in the sense of not adding 0x00 to FIFO.

Just guessing...

It doesn't help... I've just tested it using the OnReceiveError_BREAK_Demo.ino example code, but it still adds 0x00 to FIFO. I have tried EVEN/ODD, 7 bits ... no solution.

Another possible way would be using some SoftwareSerial Library to deal with UART. It is CPU intensive, but it may give the application a better control over bytes and timing.

Just a suggestion.

SuGlider commented 1 week ago

As you say, onReceive() may not fit the application needs. It works based on how IDF and the HW works, as described in #10578 (comment)

It may be usefull withSerial1.setRxFIFOFull(1); in order to use an async callback for each single incomming byte. Regarding the BREAK signal, this is how ESP32 HW works. If the BREAK is too long, it will add 0x00 to the UART RX FIFO.

Don't bother if BREAK is called error. This is just a denomination.

Well... as final testing: Serial1.setRxFIFOFull(1); will execute the callback on every single byte, but if the callback takes too long, it could be called when FIFO has more bytes waiting for processing. It means that a single byte will force a callback, but it doens't mean that there is just one byte waiting in FIFO, therefore, Serial1.available() may return higher than 1.

hitecSmartHome commented 1 week ago

Anyway, regarding the initial topic of this issue, there is no relationship between HTTP / Flash Accessing Tasks and the truncated UART packets.

Yes, that is true.

hitecSmartHome commented 1 week ago

Technically the single 0x00 byte "packet" callback happens because of the uart driver puts it when BREAK happens. But the last byte clipping is an other issue it seems. I can workaround the 0x00 byte as I shown but I don't know about the last byte clip. Needs more testing

hitecSmartHome commented 1 week ago

just to see if I understand correctly:

hitecSmartHome commented 1 week ago

Well, interestingly the application wrote a file automatically meanwhile and I got this on the serial

I (10830070) DataBase: Writing json: /saves/users.json
W (10830075) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830092) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830103) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830111) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830125) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830130) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830132) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830138) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830146) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830152) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830171) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830173) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830179) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830199) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830201) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830209) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830217) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830222) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830228) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830236) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830242) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830247) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830253) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830260) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830267) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830280) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830294) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830299) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830301) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830307) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830315) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830329) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830341) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830347) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830349) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830353) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830360) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830369) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830374) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830387) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830389) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830395) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830402) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830409) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830417) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830424) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830436) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830441) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830445) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830452) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830467) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830473) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830477) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830481) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830487) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830494) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830504) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830508) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830516) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830525) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830575) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830586) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830602) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830605) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830611) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830614) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830621) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830628) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830635) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830653) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830656) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830661) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830665) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830674) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830693) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830695) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830706) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830712) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830716) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830733) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830741) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830743) Modbus: Detected single byte frame: 0x00. Ignoring it...
W (10830749) Modbus: Detected single byte frame: 0x00. Ignoring it...
I (10830774) UserHandler: Saved 1 users to file: /saves/users.json
hitecSmartHome commented 1 week ago

As you can see, it started writing I (10830070) DataBase: Writing json: /saves/users.json -> bunch of UART BREAK BYTES coming in -> stopped writing to flash I (10830774) UserHandler: Saved 1 users to file: /saves/users.json -> no further errors

hitecSmartHome commented 1 week ago

god help us

SuGlider commented 1 week ago

This frame does not even overflow the buffer. This is 37 bytes and cuts the last byte.

0x03 0x03 0x20 0x00 0x05 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0xfe 0x89

I have tested sending this sequence using the OnReceiveError_BREAK_Demo.ino example code. I see no cut when FIFO Full is 120 bytes.

It adds the 0x00 because of the BREAK (at the end or beginning of the package), but that's all.

Could it be a problem with the Line? Bad impedance or parasitic capacitance?

SuGlider commented 1 week ago

just to see if I understand correctly:

  • UART_BREAK happens if the flow of data stops for x time
  • If UART_BREAK happens, the driver puts a 0x00 byte into the buffer, indicating a break
  • This break signaling byte will show up at the first byte of the next packet if the data flow started right after a break but the timeout does not fired
  • If the data flow does not start right away, I get an onReceive callback with only the 0x00 break byte since the timeout is fired.

Yes, correct!

SuGlider commented 1 week ago

This has been an excellent issue report. I'll add that as a reference discussion later on.

hitecSmartHome commented 1 week ago

Could it be a problem with the Line? Bad impedance or parasitic capacitance?

Yes, it can be line problem or the slave itself. Iam testing it meanwhile and so far it occoures on the same slave over and over again. Requires further testing.

hitecSmartHome commented 1 week ago

But it seems flash write also triggers uart break. Hehe

hitecSmartHome commented 1 week ago

Will test this as well