stability improvements in C6 flashing

This commit is contained in:
Nic Limper
2025-03-27 21:10:10 +01:00
parent 0fb0c6f74d
commit e102f8e4e9
13 changed files with 137 additions and 111 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -12,8 +12,8 @@ extern struct espSetChannelPower curChannel;
#define AP_STATE_NORADIO 7
struct APInfoS {
bool isOnline = false;
uint8_t state = AP_STATE_OFFLINE;
volatile bool isOnline = false;
volatile uint8_t state = AP_STATE_OFFLINE;
uint8_t type;
uint16_t version = 0;
uint8_t channel;
@@ -29,6 +29,17 @@ struct APInfoS {
extern struct APInfoS apInfo;
enum ApSerialState {
SERIAL_STATE_NONE,
SERIAL_STATE_INITIALIZED,
SERIAL_STATE_STARTING,
SERIAL_STATE_RUNNING,
SERIAL_STATE_STOP,
SERIAL_STATE_STOPPED
};
extern volatile ApSerialState gSerialTaskState;
void APTask(void* parameter);
bool sendCancelPending(struct pendingData* pending);
@@ -38,5 +49,5 @@ void APEnterEarlyReset();
bool sendChannelPower(struct espSetChannelPower* scp);
void rxSerialTask2(void* parameter);
void APTagReset();
bool bringAPOnline();
bool bringAPOnline(uint8_t newState = AP_STATE_ONLINE);
void setAPstate(bool isOnline, uint8_t state);

View File

@@ -63,7 +63,7 @@ struct Config {
uint8_t language;
uint8_t maxsleep;
uint8_t stopsleep;
uint8_t runStatus;
volatile uint8_t runStatus;
uint8_t preview;
uint8_t nightlyreboot;
uint8_t lock;

View File

@@ -224,8 +224,8 @@ bool FlashC6_H2(const char *RepoUrl) {
File readfile = contentFS->open(JsonFilename, "r");
if(!readfile) {
Serial.println("load " + JsonFilename + ": Failed to open file");
break;
wsSerial("load " + JsonFilename + ": Failed to open file");
return true;
}
DeserializationError jsonError = deserializeJson(jsonDoc, readfile);

View File

@@ -306,22 +306,25 @@ void handleRollback(AsyncWebServerRequest* request) {
#ifdef C6_OTA_FLASHING
void C6firmwareUpdateTask(void* parameter) {
String *Url = reinterpret_cast<String *>(parameter);
LOG("C6firmwareUpdateTask: url '%s'\n",Url->c_str());
char* urlPtr = reinterpret_cast<char*>(parameter);
LOG("C6firmwareUpdateTask: url '%s'\n", urlPtr);
wsSerial("Stopping AP service");
setAPstate(false, AP_STATE_FLASHING);
gSerialTaskState = SERIAL_STATE_STOP;
config.runStatus = RUNSTATUS_STOP;
setAPstate(false, AP_STATE_FLASHING);
#ifndef FLASHER_DEBUG_SHARED
extern bool rxSerialStopTask2;
rxSerialStopTask2 = true;
#endif
vTaskDelay(500 / portTICK_PERIOD_MS);
Serial1.end();
setAPstate(false, AP_STATE_FLASHING);
wsSerial(SHORT_CHIP_NAME " flash starting");
bool result = FlashC6_H2(Url->c_str());
bool result = FlashC6_H2(urlPtr);
wsSerial(SHORT_CHIP_NAME " flash end");
@@ -340,15 +343,15 @@ void C6firmwareUpdateTask(void* parameter) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
apInfo.version = 0;
wsSerial("resetting AP");
APTagReset();
vTaskDelay(1000 / portTICK_PERIOD_MS);
wsSerial("bringing AP online");
if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN;
// if (bringAPOnline(AP_STATE_REQUIRED_POWER_CYCLE)) config.runStatus = RUNSTATUS_STOP;
if (bringAPOnline(AP_STATE_ONLINE)) {
config.runStatus = RUNSTATUS_RUN;
setAPstate(true, AP_STATE_ONLINE);
}
// Wait for version info to arrive
vTaskDelay(50 / portTICK_PERIOD_MS);
// Wait for version info to arrive
vTaskDelay(500 / portTICK_PERIOD_MS);
if(apInfo.version == 0) {
result = false;
}
@@ -358,16 +361,19 @@ void C6firmwareUpdateTask(void* parameter) {
wsSerial("Finished!");
char buffer[50];
snprintf(buffer,sizeof(buffer),
"ESP32-" SHORT_CHIP_NAME " version is now %04x",apInfo.version);
"ESP32-" SHORT_CHIP_NAME " version is now %04x", apInfo.version);
wsSerial(String(buffer));
}
else if(apInfo.version == 0) {
wsSerial("AP failed failed to come online. :-(");
wsSerial("AP failed to come online. :-(");
}
else {
wsSerial("Flashing failed. :-(");
}
delete Url;
// wsSerial("Reboot system now");
// wsSerial("[reboot]");
free(urlPtr);
vTaskDelay(30000 / portTICK_PERIOD_MS);
vTaskDelete(NULL);
}
#endif
@@ -376,9 +382,10 @@ void C6firmwareUpdateTask(void* parameter) {
void handleUpdateC6(AsyncWebServerRequest* request) {
#if defined C6_OTA_FLASHING
if (request->hasParam("url",true)) {
String *Url = new String(request->getParam("url",true)->value());
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, Url, 10, NULL);
request->send(200, "Ok");
const char* urlStr = request->getParam("url", true)->value().c_str();
char* urlCopy = strdup(urlStr);
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, urlCopy, 10, NULL);
request->send(200, "Ok");
}
else {
LOG("Sending bad request");

View File

@@ -15,7 +15,7 @@
#include "web.h"
#include "zbs_interface.h"
#define LOG(format, ... ) printf(format,## __VA_ARGS__)
#define LOG(format, ...) printf(format, ##__VA_ARGS__)
QueueHandle_t rxCmdQueue;
SemaphoreHandle_t txActive;
@@ -47,15 +47,6 @@ struct espSetChannelPower curChannel = {0, 11, 10};
volatile uint32_t lastAPActivity = 0;
struct APInfoS apInfo;
enum ApSerialState {
SERIAL_STATE_NONE,
SERIAL_STATE_INITIALIZED,
SERIAL_STATE_STARTING,
SERIAL_STATE_RUNNING,
SERIAL_STATE_STOP,
SERIAL_STATE_STOPPED
};
volatile ApSerialState gSerialTaskState;
struct rxCmd {
@@ -166,27 +157,28 @@ void setAPstate(bool isOnline, uint8_t state) {
CRGB::Red,
CRGB::YellowGreen};
rgbIdleColor = colorMap[state];
#ifdef BLE_ONLY
rgbIdleColor = CRGB::Green;
#endif
#ifdef BLE_ONLY
rgbIdleColor = CRGB::Green;
#endif
rgbIdlePeriod = (isOnline ? 767 : 255);
if (isOnline) rgbIdle();
#endif
#ifdef FLASHER_DEBUG_SHARED
// Flasher shares port with AP comms
if(state == AP_STATE_FLASHING) {
LOG("Shared COM port, gSerialTaskState %d\n",gSerialTaskState);
// Flasher shares port with AP comms
if (state == AP_STATE_FLASHING) {
LOG("Shared COM port, gSerialTaskState %d\n", gSerialTaskState);
gSerialTaskState = SERIAL_STATE_STOP;
for(int i = 0; i < 100; i++) {
for (int i = 0; i < 100; i++) {
vTaskDelay(1 / portTICK_RATE_MS);
if(gSerialTaskState == SERIAL_STATE_STOPPED) {
if (gSerialTaskState == SERIAL_STATE_STOPPED) {
gSerialTaskState = SERIAL_STATE_NONE;
break;
}
}
LOG("gSerialTaskState %d\n",gSerialTaskState);
LOG("gSerialTaskState %d\n", gSerialTaskState);
}
#endif
wsSendSysteminfo();
}
// Reset the tag
@@ -415,46 +407,49 @@ void rxCmdProcessor(void* parameter) {
txActive = xSemaphoreCreateBinary();
xSemaphoreGive(txActive);
while (1) {
struct rxCmd* rxcmd = nullptr;
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
if (q == pdTRUE) {
switch (rxcmd->type) {
case RX_CMD_RQB:
processBlockRequest((struct espBlockRequest*)rxcmd->data);
if (apInfo.isOnline) {
struct rxCmd* rxcmd = nullptr;
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
if (q == pdTRUE) {
switch (rxcmd->type) {
case RX_CMD_RQB:
processBlockRequest((struct espBlockRequest*)rxcmd->data);
#ifdef HAS_RGB_LED
// shortBlink(CRGB::Blue);
// shortBlink(CRGB::Blue);
#endif
quickBlink(3);
break;
case RX_CMD_ADR:
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
quickBlink(3);
break;
case RX_CMD_ADR:
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
#ifdef HAS_RGB_LED
// shortBlink(CRGB::Aqua);
// shortBlink(CRGB::Aqua);
#endif
quickBlink(1);
break;
case RX_CMD_XFC:
processXferComplete((struct espXferComplete*)rxcmd->data, true);
quickBlink(1);
break;
case RX_CMD_XFC:
processXferComplete((struct espXferComplete*)rxcmd->data, true);
#ifdef HAS_RGB_LED
// shortBlink(CRGB::Purple);
// shortBlink(CRGB::Purple);
#endif
break;
case RX_CMD_XTO:
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
break;
case RX_CMD_RSET:
Serial.println("AP did reset, resending pending\r\n");
refreshAllPending();
sendChannelPower(&curChannel);
break;
case RX_CMD_TRD:
// received tag return data
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
break;
break;
case RX_CMD_XTO:
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
break;
case RX_CMD_RSET:
Serial.println("AP did reset, resending pending\r\n");
refreshAllPending();
sendChannelPower(&curChannel);
break;
case RX_CMD_TRD:
// received tag return data
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
break;
}
if (rxcmd->data) free(rxcmd->data);
if (rxcmd) free(rxcmd);
}
if (rxcmd->data) free(rxcmd->data);
if (rxcmd) free(rxcmd);
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
void rxSerialTask(void* parameter) {
@@ -539,8 +534,8 @@ void rxSerialTask(void* parameter) {
packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1);
memset(cmdbuffer, 0x00, 4);
lastAPActivity = millis();
if (apInfo.isOnline == false)
setAPstate(true, AP_STATE_ONLINE);
// don't set APstate heree, as it interferes with the flashing process
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
}
if (strncmp(cmdbuffer, "ADR>", 4) == 0) {
RXState = ZBS_RX_WAIT_DATA_REQ;
@@ -549,8 +544,8 @@ void rxSerialTask(void* parameter) {
packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1);
memset(cmdbuffer, 0x00, 4);
lastAPActivity = millis();
if (apInfo.isOnline == false)
setAPstate(true, AP_STATE_ONLINE);
// don't set APstate heree, as it interferes with the flashing process
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
}
if (strncmp(cmdbuffer, "XFC>", 4) == 0) {
RXState = ZBS_RX_WAIT_XFERCOMPLETE;
@@ -573,8 +568,6 @@ void rxSerialTask(void* parameter) {
packetp = (uint8_t*)calloc(sizeof(struct espTagReturnData) + 8, 1);
memset(cmdbuffer, 0x00, 4);
lastAPActivity = millis();
if (apInfo.isOnline == false)
setAPstate(true, AP_STATE_ONLINE);
}
break;
case ZBS_RX_BLOCK_REQUEST:
@@ -747,11 +740,11 @@ void rxSerialTask2(void* parameter) {
} else {
Serial.println("Failed!");
}
logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN)?("ok"):("failed"));
logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN) ? ("ok") : ("failed"));
}
rxStrCount = 0;
memset(rxStr, 0, sizeof(rxStr));
} else if(rxStrCount < sizeof(rxStr) - 2) {
} else if (rxStrCount < sizeof(rxStr) - 2) {
rxStrCount++;
} else {
rxStrCount = 0;
@@ -764,7 +757,7 @@ void rxSerialTask2(void* parameter) {
if (currentTime - startTime >= 1000) {
if (charCount > 6000) {
rxSerialStopTask2 = true;
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second");
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second)");
}
startTime = currentTime;
charCount = 0;
@@ -822,35 +815,35 @@ void segmentedShowIp() {
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
bool bringAPOnline() {
bool bringAPOnline(uint8_t newState) {
#ifdef BLE_ONLY
apInfo.state = AP_STATE_NORADIO;
#endif
if (apInfo.state == AP_STATE_NORADIO) return true;
if (apInfo.state == AP_STATE_FLASHING) return false;
if(gSerialTaskState != SERIAL_STATE_INITIALIZED) {
if (gSerialTaskState != SERIAL_STATE_INITIALIZED) {
#ifdef HAS_ELECROW_ADV_2_8
// Set GPIO45 low to connect the wireless interface to the multiplexed pins
pinMode(45, OUTPUT);
digitalWrite(45, LOW);
// Set GPIO45 low to connect the wireless interface to the multiplexed pins
pinMode(45, OUTPUT);
digitalWrite(45, LOW);
#endif
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
#elif defined(HAS_EXT_FLASHER)
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
#elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
#endif
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
#elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
#endif
gSerialTaskState = SERIAL_STATE_INITIALIZED;
#endif
gSerialTaskState = SERIAL_STATE_INITIALIZED;
}
if(gSerialTaskState != SERIAL_STATE_RUNNING) {
gSerialTaskState = SERIAL_STATE_STARTING;
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
vTaskDelay(500 / portTICK_PERIOD_MS);
if (gSerialTaskState != SERIAL_STATE_RUNNING) {
gSerialTaskState = SERIAL_STATE_STARTING;
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
setAPstate(false, AP_STATE_OFFLINE);
// try without rebooting
@@ -888,18 +881,18 @@ bool bringAPOnline() {
}
vTaskDelay(200 / portTICK_PERIOD_MS);
setAPstate(true, AP_STATE_ONLINE);
setAPstate(newState == AP_STATE_ONLINE ? true : false, newState);
return true;
}
}
bool checkRadio() {
#ifdef BLE_ONLY
#ifdef BLE_ONLY
return false;
#endif
#ifndef C6_OTA_FLASHING
#endif
#ifndef C6_OTA_FLASHING
return true;
#endif
#endif
// make a short between FLASHER_AP_TXD and FLASHER_AP_RXD to indicate that no radio is present
// e.g. for flasher only, or just to use the S3 to generate images for smaller AP's
pinMode(FLASHER_AP_TXD, OUTPUT);
@@ -923,7 +916,6 @@ void APTask(void* parameter) {
return;
}
xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 6000, NULL, 15, NULL);
#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED)
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL);

View File

@@ -182,6 +182,7 @@
<div class="nextcheckin"></div>
<div class="nextupdate"></div>
<div class="corner">
<div class="waitingicon" title="New content is scheduled to be generated (as soon as possible, or shortly before the next expected checkin time)">&#9203;</div>
<div class="pendingicon" title="A new message is waiting for the tag to pick up">&circlearrowright;</div>
<div class="warningicon" title="This tag has not been seen for a long time">&#9888;
</div>

View File

@@ -651,6 +651,16 @@ select {
text-align: center;
}
.waitingicon {
display: none;
font-size: 1.2em;
background-color: lightgreen;
color: black;
height: 20px;
width: 20px;
vertical-align: top;
text-align: center;
}
ul.messages {
padding: 5px;
}

View File

@@ -21,7 +21,7 @@ const apstate = [
{ state: "online", color: "green", icon: "check_circle" },
{ state: "flashing", color: "orange", icon: "flash_on" },
{ state: "wait for reset", color: "blue", icon: "hourglass" },
{ state: "AP requires power cycle", color: "purple", icon: "refresh" },
{ state: "AP requires reboot", color: "purple", icon: "refresh" },
{ state: "failed", color: "red", icon: "error" },
{ state: "coming online...", color: "orange", icon: "hourglass" },
{ state: "AP without radio", color: "green", icon: "wifi_off" }
@@ -371,6 +371,11 @@ function processTags(tagArray) {
} else {
$('#tag' + tagmac + ' .nextupdate').innerHTML = "";
}
if (element.nextupdate < (Date.now() / 1000) - servertimediff) {
$('#tag' + tagmac + ' .waitingicon').style.display = 'inline-block';
} else {
$('#tag' + tagmac + ' .waitingicon').style.display = 'none';
}
if (element.nextcheckin > 1672531200) {
div.dataset.nextcheckin = element.nextcheckin;

View File

@@ -185,13 +185,13 @@ export async function initUpdate() {
if(firmwareVer != 'unknown') {
let Ver = Number('0x' + firmwareVer);
if(Ver > gCurrentRfVer) {
tablerow += 'Newer';
tablerow += 'newer';
}
else if (Ver < gCurrentRfVer) {
tablerow += 'Older';
tablerow += 'older';
}
else if(!Number.isNaN(Ver)){
tablerow += 'Same';
tablerow += 'current version';
}
}
tablerow += '</td>';
@@ -211,7 +211,7 @@ export async function initUpdate() {
tableHeader2.innerHTML = '<th>Firmware</th><th><center>Update</center></th>';
table2.appendChild(tableHeader2);
const tableRow = document.createElement('tr');
tablerow = '<td>Last uploaded version</td>';
tablerow = '<td title="manual upload, make sure all four files are present">Binaries from <a href="/edit" target="littlefs">file system</a></td>';
tablerow += `<td><button type="button" onclick="otamodule.updateC6H2('')">${gModuleType}</button></td>`;
tableRow.innerHTML = tablerow;
table2.appendChild(tableRow);
@@ -222,7 +222,7 @@ export async function initUpdate() {
"/master/binaries/ESP32-" + gShortName +
"/firmware_" + gShortName + ".json";
tablerow = `<td><a href="https://github.com/${repo}" target="_new">Latest version from repo</a></td>`;
tablerow = `<td><a href="https://github.com/${repo}/tree/master/binaries/ESP32-${gShortName}/" target="_new">Latest version from repo</a></td>`;
tablerow += `<td><button type="button" onclick="otamodule.updateC6H2('${Url}')">${gModuleType}</button></td>`;
tableRow.innerHTML = tablerow;
table2.appendChild(tableRow);