Skip to content

Problem with receiving data from Serial to update ESP32 OTA #6727

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

Closed
1 task done
primus192 opened this issue May 11, 2022 · 48 comments · Fixed by #7525
Closed
1 task done

Problem with receiving data from Serial to update ESP32 OTA #6727

primus192 opened this issue May 11, 2022 · 48 comments · Fixed by #7525
Assignees
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: Needs investigation We need to do some research before taking next steps on this issue

Comments

@primus192
Copy link

Board

ESP32 Dev Module, custom board

Device Description

ESP32 Dev Module, custom board

Hardware Configuration

Quectel 2G modem attached to pin 26 and 27 of the esp32

Version

latest master (checkout manually)

IDE Name

PlatformIO

Operating System

Windows 11

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

115200

Description

Using earlier versions of arduino framework (pre 2.0 update) i was able to receive all bytes from my GSM 2G modem and push it through the Serial1 connected to pins 26 and 27 to Esp32 to update it OTA with using Serial1.setRXBufferSize(1024) before initializing communication. Baud rate is 115200.

Now with newest Arduino 2.0.3 or 2.0.4 or master branch progress of flashing just stops at 85%, modem sent all the data but esp32 missed some during receiving and after some time prints error number 6 which means timeout. Setting different RX buffer sizes before Serial1.begin() did not help. Maybe setting rx buffer size is broken? Or other things changed which i do not think about? Thanks in advance.

Sketch

Related parts, it is hard for me to paste whole code:
What works in previous frameworks:
fragment of main part:
//////////////////////////////////
        Serial1.setRxBufferSize(1024);
        Serial1.flush();
        btStop();
        if(espUpdate.updateGsm(modem.ftpDownload((String)argv[6].c_str()))) {
            modem.mqttPublish(topic, "Update success");
        } else {
            modem.mqttPublish(topic, "Update fail, try again later");
        }
/////////////////////////////////////
espUpdate part:
////////////////////////////////////

bool ESPUpdate::updateGsm(long filesize) {
    _contentLength = filesize;
    if(filesize < 1) {
        Serial.println("No file or wrong size.");
        return 0;
    }
    log_i("Firmware size: %s bytes", String(_contentLength));
    Update.onProgress([](unsigned int progress, unsigned int total) {
        Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
        });

    while(!Serial1.available()) {
    };

    if (Update.begin(_contentLength)) {
        size_t written = Update.writeStream(Serial1);
        if (written == _contentLength) {
            log_i("Written: %s successfully.", String(written));
        }
        else {
            log_i("Written: %s/%s.", String(written), String(_contentLength));
        }
        if (Update.end()) {
            log_i("Update done.");
            if (Update.isFinished()) {
                Serial.println("Update firmware success.");
                return 1;
                //ESP.restart();
            }
            else {
                _contentLength = 0;
                log_i("Update not finished? Something went wrong!");
                return 0;
            }
        }
        else {
            _contentLength = 0;
            log_e("Error Occurred. Error #: %d", Update.getError());
            return 0;
        }
    }
    else {
        log_e("Something is wrong. OTA Update failed.");
        return 0;
    }
    Serial.println("Update firmware fail. Try again later.");
        return 0;
}



////////////////////////////

What i tried in newer arduino framework which did not help:

 Serial1.end();
        Serial1.setRxBufferSize(1024);
        Serial1.begin(115200,SERIAL_8N1,26,27);
        Serial1.flush();
        btStop();
        if(espUpdate.updateGsm(modem.ftpDownload((String)argv[6].c_str()))) {
            modem.mqttPublish(topic, "Update success");
        } else {
            modem.mqttPublish(topic, "Update fail, try again later");
        }
        device.restart(true);

Debug Message

2.0.3 and up:
Flashing firmware_1.2.1.bin
[ 52534][I][ESPUpdate.cpp:64] updateGsm(): Firmware size: 1500912 bytes
[ 52841][D][Updater.cpp:133] begin(): OTA Partition: app1
[562038][I][ESPUpdate.cpp:78] updateGsm(): Written: 1282730/1500912.
[562038][E][ESPUpdate.cpp:95] updateGsm(): Error Occurred. Error #: 6

before 2.0.0 update:

Flashing firmware_1.2.1.bin
[I][ESPUpdate.cpp:64] updateGsm(): Firmware size: 1500912 bytes
[D][Updater.cpp:132] begin(): OTA Partition: app1
[I][ESPUpdate.cpp:75] updateGsm(): Written: 1500912 successfully.
[I][ESPUpdate.cpp:81] updateGsm(): Update done.
Update firmware success.

Other Steps to Reproduce

No response

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

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@primus192 primus192 added the Status: Awaiting triage Issue is waiting for triage label May 11, 2022
@primus192
Copy link
Author

I must add, the key point for getting it to work on 1.0.6 release was setting the rx buffer to 1024. Without that the buffer will overflow and the bytes are missing. However setting the buffer in arduino > 2.0.0 do not help

@VojtechBartoska VojtechBartoska added Area: Peripherals API Relates to peripheral's APIs. Type: Question Only question labels May 11, 2022
@SuGlider SuGlider self-assigned this May 11, 2022
@SuGlider
Copy link
Collaborator

Similar to #6644

@SuGlider
Copy link
Collaborator

Related parts, it is hard for me to paste whole code:
What works in previous frameworks:
fragment of main part:
//////////////////////////////////
        Serial1.setRxBufferSize(1024);
        Serial1.flush();
        btStop();
        if(espUpdate.updateGsm(modem.ftpDownload((String)argv[6].c_str()))) {
            modem.mqttPublish(topic, "Update success");
        } else {
            modem.mqttPublish(topic, "Update fail, try again later");
        }
/////////////////////////////////////

You are sure that Serial1.setRxBufferSize() is being executed before Serial1.begin(), right?

@SuGlider
Copy link
Collaborator

What about setting a bigger RXBuffer, such as 4096? Would it make any difference?

@SuGlider
Copy link
Collaborator

Please try this and let me know:

  Serial1.setRxBufferSize(4096);
  Serial1.setTimeout(0);
  Serial1.begin(115200,SERIAL_8N1,26,27);
  ...

@primus192
Copy link
Author

Related parts, it is hard for me to paste whole code:
What works in previous frameworks:
fragment of main part:
//////////////////////////////////
        Serial1.setRxBufferSize(1024);
        Serial1.flush();
        btStop();
        if(espUpdate.updateGsm(modem.ftpDownload((String)argv[6].c_str()))) {
            modem.mqttPublish(topic, "Update success");
        } else {
            modem.mqttPublish(topic, "Update fail, try again later");
        }
/////////////////////////////////////

You are sure that Serial1.setRxBufferSize() is being executed before Serial1.begin(), right?

Yes, while moving to new framework i moved setRxBufferSize(1024) before begin of the serial1 because it was throwing me error that i cant set buffer when serial is already running (not a problem in 1.0.6 tho). Unfortunately setting buffer size to 4096 and even 10000 didnt fix the problem and the progress is not increasing , still about 1282730/1500912 bytes

@SuGlider
Copy link
Collaborator

SuGlider commented May 11, 2022

I don't have a modem to test it, but maybe I can try to emulate it with a Python script.
In order to do it, I would like to make it simulate the amount of data received along the time, including, maybe, some data bursts.

Can you provide me with some sort of output that has something like this:
[time_in_milliseconds], [number_of_bytes_received_from_Quectel 2G modem]

example (time_ms, #bytes):
100, 2345
205, 120
220, 8450
221, 45
327, 9887

Thanks!

@primus192
Copy link
Author

I don't have a modem to test it, but maybe I can try to emulate it with a Python script. In order to do it, I would like to make it simulate the amount of data received along the time, including, maybe, some data bursts.

Can you provide me with some sort of output that has something like this: [time_in_milliseconds], [number_of_bytes_received_from_Quectel 2G modem]

example (time_ms, #bytes): 100, 2345 205, 120 220, 8450 221, 45 327, 9887

Thanks!

I will Try to prepare something tomorrow

@SuGlider
Copy link
Collaborator

Just to verify... you say that with Arduino Core 2.0.0, you get the same issue, right.
Meaning that the problem was introduced when moved from version 1.0.6 to the 2.0.0?

@primus192
Copy link
Author

primus192 commented May 11, 2022

It is working for me in arduino 1.0.6 with setting rx buffer to 1024. Without setting buffer it is not. In arduino 2.0.0 and later it is not working regardless of setting serial buffer size or not. So the problem for me was introduced in 2.0.0 as i cant get it to work even with setting buffer size

@primus192
Copy link
Author

Did not have time today to measure the timings and bytes. I did check Reading data from the stream directly and check how many bytes did i read. 1500912 which is exactly my binary file size. So the esp32 can handle data from the modem but when i pass Stream directly to the writeStream() function, it looks like esp32 cannot keep up with Reading and writing data to flash at the same time.

@mudgalp
Copy link

mudgalp commented May 13, 2022

Did not have time today to measure the timings and bytes. I did check Reading data from the stream directly and check how many bytes did i read. 1500912 which is exactly my binary file size. So the esp32 can handle data from the modem but when i pass Stream directly to the writeStream() function, it looks like esp32 cannot keep up with Reading and writing data to flash at the same time.

i also think so in the same kind of problem i'm facing in my issue #6644

@primus192
Copy link
Author

Did not have time today to measure the timings and bytes. I did check Reading data from the stream directly and check how many bytes did i read. 1500912 which is exactly my binary file size. So the esp32 can handle data from the modem but when i pass Stream directly to the writeStream() function, it looks like esp32 cannot keep up with Reading and writing data to flash at the same time.

i also think so in the same kind of problem i'm facing in my issue #6644

Yes. Did you Try my solution in arduino 1.0.6?

@mudgalp
Copy link

mudgalp commented May 15, 2022

Did not have time today to measure the timings and bytes. I did check Reading data from the stream directly and check how many bytes did i read. 1500912 which is exactly my binary file size. So the esp32 can handle data from the modem but when i pass Stream directly to the writeStream() function, it looks like esp32 cannot keep up with Reading and writing data to flash at the same time.

i also think so in the same kind of problem i'm facing in my issue #6644

Yes. Did you Try my solution in arduino 1.0.6?

Yes, i tried that. didn't work.

@SuGlider
Copy link
Collaborator

I have seen some people that uses OTA from a LTE/GPRS modem in a different way:
First the application copies the firmaware to the SPIFFS and after finishing, it flashes the firmware from this SPIFFS partition...

Not sure if this way would work for you.

@mudgalp
Copy link

mudgalp commented May 16, 2022

I have seen some people that uses OTA from a LTE/GPRS modem in a different way: First the application copies the firmaware to the SPIFFS and after finishing, it flashes the firmware from this SPIFFS partition...

Not sure if this way would work for you.

i have also seen this and tried already, but again getting some different error in that process.
find the code and debug below.

###Function_Code
`bool DoFirmwareUpdate()
{
Serial.println("<<< ATTENTION !!! DO NOT TURN OFF THE DEVICE... >>>"); Serial.println();
Serial.println("Updating the Device Firmware Now!"); Serial.println();
Serial.println("Please Wait untill the Device Restarts"); Serial.println();
bool value;
String fwurl = "";
fwurl = URL_fw_Bin;
Serial.println(fwurl); Serial.println();

if (WiFi.status() != WL_CONNECTED)
{
Network_Check_GSM();
if (GSM_Network_STS == true)
{
Serial2.write("AT+QIACT?\r\n");
delay(100);
input = Serial2.readString();
if (input.indexOf("OK") >= 0)
{
Serial.println("GPRS CONNECT SUCCESSFULLY");
Serial.println();
input = Serial2.readString();
input.remove(0);
Serial2.print("AT+QHTTPURL=79,30\r\n");
delay(100);
input = Serial2.readString();
if (input.indexOf("CONNECT") >= 0)
{
Serial2.print(fwurl);
delay(100);
input = Serial2.readString();
if (input.indexOf("OK") >= 0)
{
Serial.println("URL CONNECT SUCCESSFULLY");
Serial.println();
input = Serial2.readString();
input.remove(0);
int count = 0;
Serial2.write("AT+QHTTPGET=30\r\n");
input = Serial2.readString();
while (input.indexOf("+QHTTPGET") < 0)
{
Serial.println("WAITING FOR GET COMMAND RESPONSE");
Serial.println();
if (count >= 5)
{
break;
}
count++;
input = Serial2.readString();
}
String GetResponse = input.substring(input.indexOf("+QHTTPGET") + 13, input.indexOf("+QHTTPGET") + 16);
Serial.print("GET RESPONSE IS:");
Serial.println(GetResponse);
Serial.println();
if (GetResponse == "200")
{
Serial.println("GET RESPONSE IS OK");
Serial.println();
input = Serial2.readString();
input.remove(0);
httpResponseLineCount = 0;
Serial2.write("AT+QHTTPREAD=30\r\n");
while (!Serial2.available())
{
}
File file = SPIFFS.open("/update.bin", FILE_APPEND);
while (Serial2.available() > 0)
{
// read line till /n
String line = Serial2.readStringUntil('\n');
// remove space, to check if the line is end of headers
Serial.print("line:");
Serial.println(line);
line.trim();
// if the the line is empty,
// this is end of headers
// break the while and feed the
// remaining client to the
// Update.writeStream();
if (!line.length())
{
Serial.println("This Line Was empty one times");//headers ended
Serial.println("httpResponseLineCount is :" + String(httpResponseLineCount));
if (httpResponseLineCount == 1)
{
Serial.println("This Line Was empty two times");//headers ended
Serial.println("Breaking While() Now");
httpResponseLineCount = 0;
break; // and get the OTA started
}
httpResponseLineCount ++;
//break; // and get the OTA started
}
// Check if the HTTP Response is 200
// else break and Exit Update
if (line.startsWith("HTTP/1.1"))
{
if (line.indexOf("200") < 0)
{
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
break;
}
}
// extract headers here
// Start with content length
if (line.startsWith("Content-Length: "))
{
contentLength = atol((getHeaderValue(line, "Content-Length: ")).c_str());
Serial.println("Got " + String(contentLength) + " bytes from server");
}
// Next, the content type
if (line.startsWith("Content-Type: "))
{
String contentType = getHeaderValue(line, "Content-Type: ");
Serial.println("Got " + contentType + " payload.");
if (contentType == "application/octet-stream")
{
isValidContentType = true;
}
}
}//-------------------------------------
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
// check contentLength and content type
if (contentLength && isValidContentType)
{
while (Serial2.available() > 0)
{
if (!file.print(char(Serial2.read())))
{
Serial.println("Appending file failed");
}
}
file.close();// this line runs before getting all the data from the server
Serial.println("File Closed");
}
else
{
Serial.println("There was no content in the response");
Serial2.flush();
}
}
input = Serial2.readString();
input.remove(0);
Serial2.write("AT+QHTTPSTOP\r\n");
delay(100);
input = Serial2.readString();
input.remove(0);
}
else
{
Serial.println("HTTP RESPONSE ERROR");
Serial.println();
input.remove(0);
value = false;
}
}
else
{
Serial.println("URL CONNECT FAILED");
Serial.println();
value = false;
}
}
else
{
Serial.println("GPRS CONNECT FAILED");
Serial.println();
value = false;
}
input = Serial2.readString();
input.remove(0);
Serial2.write("AT+QIDEACT=1\r\n");
delay(100);
input = Serial2.readString();
input.remove(0);
updateFromFS();
}
else if (GSM_Network_STS == false)
{
value = false;
}
}
if (WiFi.status() == WL_CONNECTED)
{
WiFiClient client;
httpUpdate.setLedPin(LED);
t_httpUpdate_return ret = httpUpdate.update(client, URL_fw_Bin);
switch (ret)
{
case HTTP_UPDATE_FAILED:
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("HTTP_UPDATE_NO_UPDATES");
break;
case HTTP_UPDATE_OK:
Serial.println("HTTP_UPDATE_OK");
break;
}
}
return value;
}
`

### Debug_Output

[5-11 11:40:01.3][ 17068][D][WiFiGeneric.cpp:852] _eventCallback(): Arduino Event: 0 - WIFI_READY
[5-11 11:40:01.4][ 17169][V][WiFiGeneric.cpp:283] _arduino_event_cb(): STA Started
[5-11 11:40:01.4][ 17170][D][WiFiGeneric.cpp:852] _eventCallback(): Arduino Event: 2 - STA_START
[5-11 11:40:02.9][ 18669][E][WiFiMulti.cpp:55] addAP(): [WIFI][APlistAdd] no ssid or ssid too long
[5-11 11:40:02.9][ 18669][I][WiFiMulti.cpp:84] addAP(): [WIFI][APlistAdd] add SSID: silicis
[5-11 11:40:02.9][ 18671][I][WiFiMulti.cpp:84] addAP(): [WIFI][APlistAdd] add SSID: PM12
[5-11 11:40:02.9][ 18678][I][WiFiMulti.cpp:84] addAP(): [WIFI][APlistAdd] add SSID: PM13
[5-11 11:40:02.9]CONNECTING TO WIFI...
[5-11 11:40:02.9]
[5-11 11:40:04.8][ 20520][V][WiFiGeneric.cpp:317] _arduino_event_cb(): SCAN Done: ID: 128, Status: 0, Results: 0
[5-11 11:40:04.8][ 20521][D][WiFiGeneric.cpp:852] _eventCallback(): Arduino Event: 1 - SCAN_DONE
[5-11 11:40:04.8][ 20525][I][WiFiMulti.cpp:114] run(): [WIFI] scan done
[5-11 11:40:04.8][ 20530][E][WiFiMulti.cpp:117] run(): [WIFI] no networks found
[5-11 11:40:04.8][ 20535][E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[5-11 11:40:05.8]UNABLE TO CONNECT ANY WIFI
[5-11 11:40:05.8]
[5-11 11:40:05.8]CHECKING GSM MODULE IN 10Sec.
[5-11 11:40:05.8]
[5-11 11:40:23.5]MODULE OK
[5-11 11:40:23.5]
[5-11 11:40:23.5]SETTING OTHER PARAMETERS TO GSM
[5-11 11:40:23.5]
[5-11 11:40:25.7]IMEI : 861190059737848
[5-11 11:40:25.7]
[5-11 11:40:27.3]CHECKING FOR SIM CARD
[5-11 11:40:27.3]
[5-11 11:40:28.4]SIM CARD FOUND OK
[5-11 11:40:28.4]
[5-11 11:40:29.5]GSM INITIALIZATION COMPLETE
[5-11 11:40:29.5]
[5-11 11:40:30.6]GSM IS REGISTERED ON NETWORK
[5-11 11:40:30.6]
[5-11 11:40:31.8]NETWORK TIME SYNC SUCCESSFUL
[5-11 11:40:31.8]
[5-11 11:40:32.9]SETTING SMS COMMANDS
[5-11 11:40:32.9]
[5-11 11:40:33.5]SETTING HTTP COMMANDS
[5-11 11:40:33.5]
[5-11 11:40:36.8]<--APN SET FOR JIO-->
[5-11 11:40:36.8]
[5-11 11:40:39.4]STARTING GPRS/PDP CONTEXT CONNECTION
[5-11 11:40:41.4]CONTEXT PROFILE IS OK
[5-11 11:40:41.4]
[5-11 11:40:42.4]GPRS/PDP CONTEXT PROFILE IS ACTIVATED
[5-11 11:40:42.4]
[5-11 11:40:43.4]
[5-11 11:40:43.4]+QIACT: 1,1,1,"26.61.218.118"
[5-11 11:40:43.4]
[5-11 11:40:43.4]OK
[5-11 11:40:43.4]
[5-11 11:40:43.4]Device Firmware Version is : 1.0
[5-11 11:40:43.4]
[5-11 11:40:43.4]Checking Firmware update...
[5-11 11:40:43.4]
[5-11 11:40:43.4]http://data.silicisroadindustries.com/silicis_fota/buslog4g_fota_lpa/fw_version.txt
[5-11 11:40:43.4]
[5-11 11:40:44.4]GSM REGISTERED ON NETWORK
[5-11 11:40:44.4]
[5-11 11:40:45.5]Signal Strength : 31
[5-11 11:40:45.5]
[5-11 11:40:46.6]GPRS CONNECT SUCCESSFULLY
[5-11 11:40:46.6]
[5-11 11:40:49.7]URL CONNECT SUCCESSFULLY
[5-11 11:40:49.7]
[5-11 11:40:51.7]WAITING FOR GET COMMAND RESPONSE
[5-11 11:40:51.7]
[5-11 11:40:52.8]GET RESPONSE IS:200
[5-11 11:40:52.8]
[5-11 11:40:52.8]GET RESPONSE IS OK
[5-11 11:40:52.8]
[5-11 11:40:53.8]line is:
[5-11 11:40:53.8]This Line Was empty
[5-11 11:40:53.8]httpResponseLineCount is :1
[5-11 11:40:53.8]line is:CONNECT
[5-11 11:40:53.8]line is:HTTP/1.1 200 OK
[5-11 11:40:53.8]line is:Server: nginx/1.18.0 (Ubuntu)
[5-11 11:40:53.8]line is:Date: Wed, 11 May 2022 06:10:51 GMT
[5-11 11:40:53.8]line is:Content-Type: text/plain
[5-11 11:40:53.8]Got text/plain payload.
[5-11 11:40:53.8]line is:Content-Length: 5
[5-11 11:40:53.8]Got 5 bytes from server
[5-11 11:40:54.0]line is:Last-Modified: Tue, 19 Apr 2022 03:56:14 GMT
[5-11 11:40:54.0]line is:Connection: keep-alive
[5-11 11:40:54.0]line is:ETag: "625e32de-5"
[5-11 11:40:54.0]line is:Accept-Ranges: bytes
[5-11 11:40:54.0]line is:
[5-11 11:40:54.0]This Line Was empty
[5-11 11:40:54.0]httpResponseLineCount is :2
[5-11 11:40:54.0]This Line Was empty Two Times
[5-11 11:40:54.0]Breaking While() Now
[5-11 11:40:54.0]contentLength : 5, isValidContentType : 1
[5-11 11:40:54.0]Found Firmware Version is:1.1
[5-11 11:40:54.0]This is a New Firmware Version1.1
[5-11 11:40:55.9]Starting FOTA to update New Firmware
[5-11 11:40:55.9]
[5-11 11:40:55.9]<<< ATTENTION !!! DO NOT TURN OFF THE DEVICE... >>>
[5-11 11:40:55.9]
[5-11 11:40:55.9]Updating the Device Firmware Now!
[5-11 11:40:55.9]
[5-11 11:40:55.9]Please Wait untill the Device Restarts
[5-11 11:40:55.9]
[5-11 11:40:55.9]http://data.silicisroadindustries.com/silicis_fota/buslog4g_fota_lpa/update.bin
[5-11 11:40:56.0]
[5-11 11:40:57.0]GSM REGISTERED ON NETWORK
[5-11 11:40:57.0]
[5-11 11:40:58.0]Signal Strength : 31
[5-11 11:40:58.0]
[5-11 11:40:59.1]GPRS CONNECT SUCCESSFULLY
[5-11 11:40:59.1]
[5-11 11:41:02.3]URL CONNECT SUCCESSFULLY
[5-11 11:41:02.3]
[5-11 11:41:04.5]GET RESPONSE IS:200
[5-11 11:41:04.5]
[5-11 11:41:04.5]GET RESPONSE IS OK
[5-11 11:41:04.5]
[5-11 11:41:05.7]line:
[5-11 11:41:05.7]This Line Was empty one times
[5-11 11:41:05.7]httpResponseLineCount is :0
[5-11 11:41:05.7]line:CONNECT
[5-11 11:41:05.7]line:HTTP/1.1 200 OK
[5-11 11:41:05.7]line:Server: nginx/1.18.0 (Ubuntu)
[5-11 11:41:05.7]line:Date: Wed, 11 May 2022 06:11:03 GMT
[5-11 11:41:05.7]line:Content-Type: application/octet-stream
[5-11 11:41:05.7]Got application/octet-stream payload.
[5-11 11:41:05.7]line:Content-Length: 213296
[5-11 11:41:05.7]Got 213296 bytes from server
[5-11 11:41:05.7]line:Last-Modified: Tue, 10 May 2022 14:13:33 GMT
[5-11 11:41:05.7]line:Connection: keep-alive
[5-11 11:41:05.7]line:ETag: "627a730d-34130"
[5-11 11:41:05.7]line:Accept-Ranges: bytes
[5-11 11:41:05.7]line:
[5-11 11:41:05.7]This Line Was empty one times
[5-11 11:41:05.9]httpResponseLineCount is :1
[5-11 11:41:05.9]This Line Was empty two times
[5-11 11:41:05.9]Breaking While() Now
[5-11 11:41:05.9]contentLength : 213296, isValidContentType : 1
[5-11 11:41:06.0]File Closed
[5-11 11:41:28.3]updateSize :5242
[5-11 11:41:28.3]Starting update
[5-11 11:41:28.3][104010][D][Updater.cpp:133] begin(): OTA Partition: app1
[5-11 11:41:28.4]Writes : 5242 successfully
[5-11 11:41:28.4]E (104141) esp_image: invalid segment length 0x656e0029
[5-11 11:41:28.4]Error occured #: 9
[5-11 11:41:30.4]<----------BOOT PROCESS COMPLETE---------->
[5-11 11:41:30.4]

here the while loop breaks before getting all the data from server don't know why..
check if you can understand this problem.

@VojtechBartoska VojtechBartoska removed the Status: Awaiting triage Issue is waiting for triage label May 17, 2022
@SuGlider
Copy link
Collaborator

@primus192
Copy link
Author

Unfortunately my binary size exceeds 1.5MB so i wont load it to spiffs. I just wonder why it works on 1.0.6 and not on > 2.0.0. I will stick to 1.0.6 for now

@mudgalp
Copy link

mudgalp commented May 20, 2022

Unfortunately my binary size exceeds 1.5MB so i wont load it to spiffs. I just wonder why it works on 1.0.6 and not on > 2.0.0. I will stick to 1.0.6 for now

i will also face this problem in future because i'm testing the OTA with only the OTA functions not with all the working functions on the device. after adding the complete code it will be about 1.7MB in size.

@SuGlider
Copy link
Collaborator

SuGlider commented Jun 6, 2022

There is a possible work around that may fix this issue.

Pease try this code/example when starting Serial1 (used to receive data from the Modem with OTA firmware):

#include "driver/uart.h"
void setup(){
        Serial1.setRxBufferSize(1024);
        Serial1.begin(115200,SERIAL_8N1,26,27);
        Serial1.setRxTimeout(1);
        uart_set_always_rx_timeout(1, true); // 1 is for Serial1, in this case
        Serial1.flush();
}

Please let me know if this solves the issue.

@VojtechBartoska
Copy link
Contributor

any updates @primus192?

@primus192
Copy link
Author

primus192 commented Aug 23, 2022 via email

@Pragalf
Copy link

Pragalf commented Sep 15, 2022

I must add, the key point for getting it to work on 1.0.6 release was setting the rx buffer to 1024. Without that the buffer will overflow and the bytes are missing. However setting the buffer in arduino > 2.0.0 do not help

Hi,
I am also having the same issue. Ota update working in ESP version 1.0.6 but not in ESP 2.0.3. Data is received in the modem but didn't receive in ESP. Tried to print the data and it was much less than my defined packet size. Rx buffer is set to match the packet size, but I think it isn't working.

@SuGlider
Copy link
Collaborator

We have done a few updates to UART in the new Arduino Core 2.0.5 version.
There are new functions that may help your OTA applications:

  • void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
    onReceive() will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or
    UART_INTR_RXFIFO_TOUT). This means that it is possible to set up a callback that will be executed as soon as data is
    received.
    UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by
    default in IDF). This default value of 120 can be changed using setRxFIFOFull() with a value from 1 to 127.
    UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception
    (defined as 2 symbols by default). This can also be changed with setRxTimeout()

    onlyOnTimeout parameter will define how onReceive will behave:
    true -- The callback will only be called when RX Timeout happens.
    Whole stream of bytes will be ready for being read on the callback function at once.
    This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received
    in the streaming
    Default: false -- The callback will be called when FIFO reaches RXFIFO_FULL bytes and also on RX Timeout.
    The stream of incommig bytes will be "split" into blocks of minimum RXFIFO_FULL bytes on each callback.
    This option avoids any sort of Rx Overflow, but leaves the UART packet reassembling work
    to the Application.

  • void onReceiveError(OnReceiveErrorCb function);
    onReceiveError() will be called on error events (see hardwareSerial_error_t) and it will also call the onReceive() callback in
    case some was defined. By this, it is possible to read data using onReceive() callback when a BREAK is sent to UART, for
    instance.

  • void setRxTimeout(uint8_t symbols_timeout);
    setRxTimeout() sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
    param symbols_timeout defines a timeout threshold in uart symbol periods.
    Setting 0 (zero) symbol timeout disables the callback call by timeout.
    Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
    For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
    For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms

  • void setRxFIFOFull(uint8_t fifoBytes);
    setRxFIFOFull() will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
    This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data,
    Serial internal RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
    This parameter can be set to a low value, such as 1 in order to receive byte by byte, but it will also consume more
    CPU time as the ISR will be activates often.

@primus192
Copy link
Author

Unfortunately it does not work. Updating still hangs at 97% while on arduino 1.0.6 it works like a charm.

@SuGlider
Copy link
Collaborator

SuGlider commented Dec 4, 2022

@primus192 @mudgalp

Please try using lastest master branch from Arduino ESP32 Github to build you application.
There is a new PR that may fix the issue: #7525
It will be necessary to apply this PR over the master brach while it is not merged.

This PR fixes Stream::readBytes() to make it faster using IDF in the new Core 2.0.x

I think that it may solve the timeout issue.

Please use this setup:

void setup(){
        Serial.setRxBufferSize(2048);
        Serial.begin(115200,SERIAL_8N1,26,27);  // RxPin = 26 & TxPin = 27
        Serial.setRxTimeout(1);
        Serial.setRxFIFOFull(120);
        Serial.flush();
}

@primus192
Copy link
Author

primus192 commented Dec 4, 2022 via email

@primus192
Copy link
Author

primus192 commented Dec 7, 2022 via email

@primus192
Copy link
Author

Not completed by any means ;)

@me-no-dev me-no-dev reopened this Dec 13, 2022
@VojtechBartoska VojtechBartoska added Status: Needs investigation We need to do some research before taking next steps on this issue and removed Type: Question Only question labels Dec 13, 2022
@Dave-Osborne
Copy link

Dave-Osborne commented Jun 26, 2023

I've just updated from 1.0.6 to 2.0.9 and am facing the same issue. Is there an ETA on resolving this or a workaround?

UPDATE: After setting a cb for HardwareSerial::onReceiveError I'm now seeing additional logging

[W] UART1 FIFO Overflow. Consider adding Hardware Flow Control to your Application.

Adding hardware flow control isn't really an option as our product has been working fine up until this software upgrade.

@SuGlider
Copy link
Collaborator

I've just updated from 1.0.6 to 2.0.9 and am facing the same issue. Is there an ETA on resolving this or a workaround?

UPDATE: After setting a cb for HardwareSerial::onReceiveError I'm now seeing additional logging

[W] UART1 FIFO Overflow. Consider adding Hardware Flow Control to your Application.

Adding hardware flow control isn't really an option as our product has been working fine up until this software upgrade.

@Dave-Osborne - FIFO Overflow means that the internal ESP32 UART1 FIFO got full before the data could be read by the Arduino Sketch.
One way to overcome it would be to add a bigger RX Buffer by executing Serial1.setRxBufferSize(4096);, for instance, prior to executing Serial1.begin(baudrate);. What is the baud rate used in the project?

@Dave-Osborne
Copy link

@SuGlider - Hi, the rx buffer size is already set to 4096 before the serial begin (I've also tried setting it larger).

Baud rate is 115200

@SuGlider
Copy link
Collaborator

What is the sketch used for OTA?
Is it connected to a LTE Modem or something like that?

@Dave-Osborne
Copy link

Dave-Osborne commented Jun 27, 2023

It is part of OTA (via LTE-M Modem), I download smaller gzipped sections of the firmware and store on a LittleFS partition and then later stitch them together and perform an OTA update.

Normally I use 300k sections, but have dropped to about 50k whilst looking into this issue.

I've changed the code to only read the number of bytes available during the loop, as you can see below using this method a small number bytes in consistently read which is nowhere near the 4096 buffer limit, it looks like perhaps the Serial1.setRxBufferSize(4096); call isn't actually increasing the FIFO buffer?

FileStream: Estimated completion: 7 %, bytes written: 3589
[ 48095][I][commsGsm.cpp:678] doGet(): Read 120, remaining 47613 of 51202
[ 48095][I][commsGsm.cpp:678] doGet(): Read 109, remaining 47504 of 51202
[ 48127][I][commsGsm.cpp:678] doGet(): Read 120, remaining 47384 of 51202
[ 48137][I][commsGsm.cpp:678] doGet(): Read 120, remaining 47264 of 51202
[ 48147][I][commsGsm.cpp:678] doGet(): Read 120, remaining 47144 of 51202
[ 48206][W][HardwareSerial.cpp:298] _uartEventTask(): UART1 FIFO Overflow. Consider adding Hardware Flow Control to your Application.
[ 48217][W][HardwareSerial.cpp:298] _uartEventTask(): UART1 FIFO Overflow. Consider adding Hardware Flow Control to your Application.
FileStream: Estimated completion: 8 %, bytes written: 4178
[ 48246][I][commsGsm.cpp:678] doGet(): Read 120, remaining 47024 of 51202

UPDATE:
I just change to read 1024 blocks, it looks as if Serial1.readBytes isn't clearing from the FIFO buffer correctly when reading.

FileStream: Estimated completion: 1 %, bytes written: 1024
[ 40398][I][commsGsm.cpp:678] doGet(): Read 1024, remaining 50178 of 51202
FileStream: Estimated completion: 3 %, bytes written: 2048
[ 40479][I][commsGsm.cpp:678] doGet(): Read 1024, remaining 49154 of 51202
FileStream: Estimated completion: 5 %, bytes written: 3072
[ 40563][I][commsGsm.cpp:678] doGet(): Read 1024, remaining 48130 of 51202
[ 40722][W][HardwareSerial.cpp:298] _uartEventTask(): UART1 FIFO Overflow. Consider adding Hardware Flow Control to your Application.
FileStream: Estimated completion: 7 %, bytes written: 4096

@SuGlider
Copy link
Collaborator

Stream::readBytes() may be related to the issue...

Please try using Serial1.read(uint8_t *buffer, size_t size) instead.
Let me know if it changes anything about the issue.

@Dave-Osborne
Copy link

Dave-Osborne commented Jun 27, 2023

Thanks for @SuGlider, I'm still using readBytes() but have just found that if I don't write my buffer to LittleFs there is no issue reading serial data, so perhaps there is an underlying issue reading serial and then writing to flash?

As I'm downloading the firmware in sections I'm going to transfer to PSRam, check the CRC bytes I include and then append to a larger file on LittleFs before performing the update.

@primus192
Copy link
Author

primus192 commented Jun 27, 2023

As far as I remember I checked regular read before and it did not fix my issue either, i am passing serial data from modem directly to the update class. Still sitting On 1.0.6 because of this issue..

Tried the read instead of read bytes a moment ago. No luck

Screenshot_20230627_131849_Messenger

Maybe if we could increase hw fifo size which is limited to 1024b but hardcoded to 128b per rx tx could help but i see there was request to be able to change it but noone implemented it yet

espressif/esp-idf#9682

@Dave-Osborne
Copy link

I can confirm that if I no longer write to flash directly I no longer get FIFO Overflows.

As a quick workaround I'm now writing to a PS RAM filesystem first https://github.com/tobozo/ESP32-PsRamFS

I download in 300k sections and then append each to a LittleFS file, but if you have enough PSRam you could probably update directly from the PS RAM filesystem?

I'll perhaps refactor to use a PSRam stream instead at some point, but this workaround is working for me at the moment.

@primus192
Copy link
Author

primus192 commented Jun 28, 2023

I can confirm that if I no longer write to flash directly I no longer get FIFO Overflows.

As a quick workaround I'm now writing to a PS RAM filesystem first https://github.com/tobozo/ESP32-PsRamFS

I download in 300k sections and then append each to a LittleFS file, but if you have enough PSRam you could probably update directly from the PS RAM filesystem?

I'll perhaps refactor to use a PSRam stream instead at some point, but this workaround is working for me at the moment.

Unfortunately PSRAM is not the option for me
EDIT: Quickly Tried hardware flow control. I can confirm that with hwctrl update completes

@SuGlider
Copy link
Collaborator

@primus192 - Can you please try this:

        Serial1.setRxBufferSize(4096);
        Serial1.begin(115200,SERIAL_8N1,26,27);
        Serial1.setTimeout(0);   // ====> This may affect the process of time out and help with OTA
        Serial1.flush();

@primus192
Copy link
Author

primus192 commented Jun 29, 2023

@primus192 - Can you please try this:

        Serial1.setRxBufferSize(4096);
        Serial1.begin(115200,SERIAL_8N1,26,27);
        Serial1.setTimeout(0);   // ====> This may affect the process of time out and help with OTA
        Serial1.flush();

Tomorrow i will try that but i think i have Tried that before with No success

EDIT: No success :) Still getting fifo overflows

@NeevoTech
Copy link

Hi @primus192 did you resolved this issue?
I am also facing the same issue. If you have resolved it, please give us some pointers.
Thank you in adv.

@TheMasterofBlubb
Copy link

@primus192 Just a small idea:
I guess you were writing to flash when doing the OTA, which would mean that while you write, you can not read from flash. So consequently you can not run code at that time as it would be read from flash.

Did you try to put the functions reading Serial and writing Flash into IRAM? ( using IRAM_ATTR you can tell the toolchain to do that)

Putting the functions into IRAM would make them independent of the flash and allow for execution while flash is written.

@primus192
Copy link
Author

primus192 commented Jun 17, 2024 via email

@Parsaabasi
Copy link

Hello,

This issue seems resolved. Therefore I close it.

In case it occurred again, please reopen it.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: Needs investigation We need to do some research before taking next steps on this issue
Projects
Development

Successfully merging a pull request may close this issue.

10 participants