ESP32 OTA更新在启动时不断崩溃

ESP32 OTA update keeps crashing on start

本文关键字:崩溃 启动 OTA 更新 ESP32      更新时间:2023-10-16

我正在尝试OTA更新ESP32,让它向Azure blob存储上的文件发出get请求。

由于某种未知的原因,它不允许我使用WifiClient.connect((函数,因为它总是返回0。所以现在我正在使用HTTPClient库向Azure上的blob存储发出get请求。我得到了它来提出请求,现在我正试图将它流式传输到:

Update.writeStream();

但每当我到达那个部分时,它就会崩溃,并给出以下信息:

Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x00000000  PS      : 0x00060630  A0      : 0x800d1a18  A1      : 0x3ffb1f30  
A2      : 0x00000000  A3      : 0x3ffb1f64  A4      : 0x3ffc11b8  A5      : 0x00000000  
A6      : 0x3ffbd484  A7      : 0x00000000  A8      : 0x800d3304  A9      : 0x3ffb1f10  
A10     : 0x3ffb1f64  A11     : 0x3f40124c  A12     : 0x00000001  A13     : 0x3ffbd44c  
A14     : 0x00000000  A15     : 0x3ffc1678  SAR     : 0x0000000a  EXCCAUSE: 0x00000014  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  
Backtrace: 0x00000000:0x3ffb1f30 0x400d1a15:0x3ffb1f50 0x400d63bb:0x3ffb1fb0 0x40088b9d:0x3ffb1fd0

这是代码:

http.begin("https://AZUREACCOUNT.blob.core.windows.net/CONTAINER/firmware.bin");
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
WiFiClient * stream = http.getStreamPtr();
unsigned long timeout = millis();
while (stream->available() == 0) {
if (millis() - timeout > 5000) {
Serial.println("Client Timeout !");
stream->stop();
return;
}
}
int contentLength = http.getSize();
if (Update.begin(contentLength)) {
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
// No activity would appear on the Serial monitor
// So be patient. This may take 2 - 5mins to complete
size_t written = Update.writeStream((WiFiClient &)stream);
if (written == contentLength) {
Serial.println("Written : " + String(written) + " successfully");
} else {
Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?" );
// retry??
// execOTA();
}
if (Update.end()) {
Serial.println("OTA done!");
if (Update.isFinished()) {
Serial.println("Update successfully completed. Rebooting.");
ESP.restart();
} else {
Serial.println("Update not finished? Something went wrong!");
}
} else {
Serial.println("Error Occurred. Error #: " + String(Update.getError()));
}
}
else {
Serial.println("Not enough space");
}

我如何使此代码工作,以便设备从Azure blob存储中获取文件并更新自身?

您必须找出它崩溃的原因。如果没有工具,回溯对您没有帮助。

堆栈
请在Arduino IDE中安装此工具:
https://github.com/me-no-dev/EspExceptionDecoder

把你的错误放在里面,得到调用堆栈,看看它在哪里崩溃。可能它与Update无关,只与httpclient有关。

SSL
您正在调用https页面,您使用secureClient吗?您使用SSL证书吗?如果没有它,您将无法通过安全连接进行通信。

最后:VERBOSE
在启用详细模式的情况下编译。当某些事情不起作用时,得到每一条信息真的很重要。对于https来说,每一条信息都非常重要,以找出它为什么不能像预期的那样工作。

此回复可能不会直接解决您的问题(因为我使用的是ESP8266HTTPUpdateServerSecure,而不是像您一样使用API请求(,但可能对遇到类似问题的其他人有用

最有可能的是,这是由OOM(内存不足(异常引起的,即某个库试图为变量分配内存,但失败了。TLS文件上传通常占用大量内存。根据@Andriano的建议,您应该使用EspExceptionDecoder(或其姊妹工具https://github.com/littleyoda/EspStackTraceDecoder)。

我设法通过在我的设备上实现"安全模式"来解决这个问题:

// true  = allow for OTA updates in normal mode
// false = allow OTA update ONLY in safeBoot 
#define OTA_AVAILABLE_IN_NORMAL_MODE false
bool safeBoot = false;
void setup() 
{
//...
delay(INITIAL_BOOT_DELAY_ms);
safeBoot = (digitalRead(PIN_BUTTON) == BUTTON_PRESSED_STATE);
initializeWiFi(); 
if (safeBoot || OTA_AVAILABLE_IN_NORMAL_MODE) {
// initializeOTA & TLSWebServer443
}
if(!safeBoot) { 
// initialize all other stuff, including HTTPWebServer80
}
}

启用后,只初始化负责OTA更新的结构
(在我的情况下,这些是ESP8266WebServerSecureESP8266HTTPUpdateServerSecure。我通过TLS页面更新固件,所有其他东西都通过未加密的HTTP工作-它更快,适合我的威胁模型(。

通过这种方式,您将增加可用堆空间(在我的情况下是十倍(,从而增加OTA无错误上传文件的机会。