From 8c7cacddfc4cb9946c1e9c4cd95ad5f0ec79a489 Mon Sep 17 00:00:00 2001 From: Jelmer Date: Mon, 27 Mar 2023 22:56:00 +0200 Subject: [PATCH] added return validation --- ESP32_AP-Flasher/src/serial.cpp | 219 ++++++++++++++++++++++++-------- 1 file changed, 164 insertions(+), 55 deletions(-) diff --git a/ESP32_AP-Flasher/src/serial.cpp b/ESP32_AP-Flasher/src/serial.cpp index e655f959..44b70c8e 100644 --- a/ESP32_AP-Flasher/src/serial.cpp +++ b/ESP32_AP-Flasher/src/serial.cpp @@ -24,13 +24,65 @@ #define ZBS_DMA_PIN FLASHER_AP_MISO -uint8_t restartBlockRequest = 0; +QueueHandle_t rxCmdQueue; +SemaphoreHandle_t txActive; + +#define CMD_REPLY_WAIT 0x00 +#define CMD_REPLY_ACK 0x01 +#define CMD_REPLY_NOK 0x02 +#define CMD_REPLY_NOQ 0x03 +volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT; + +bool txStart() { + if (xPortInIsrContext()) { + if (xSemaphoreTakeFromISR(txActive, NULL) == pdTRUE) return true; + } else { + if (xSemaphoreTake(txActive, portTICK_PERIOD_MS)) return true; + } + return false; +} + +void txEnd() { + if (xPortInIsrContext()) { + xSemaphoreGiveFromISR(txActive, NULL); + } else { + xSemaphoreGive(txActive); + } +} + +bool waitCmdReply() { + uint32_t val = millis(); + while (millis() < val + 100) { + switch (cmdReplyValue) { + case CMD_REPLY_WAIT: + break; + case CMD_REPLY_ACK: + return true; + break; + case CMD_REPLY_NOK: + return false; + break; + case CMD_REPLY_NOQ: + return false; + break; + } + } + return false; +} uint16_t sendBlock(const void* data, const uint16_t len) { - Serial1.print(">D>"); - delay(3); + if (!txStart()) return 0; + for (uint8_t attempt = 0; attempt < 5; attempt++) { + cmdReplyValue = CMD_REPLY_WAIT; + Serial1.print(">D>"); + if (waitCmdReply()) goto blksend; + Serial.printf("block send failed in try %d\n", attempt); + } + Serial.print("Failed sending block...\n"); + txEnd(); + return 0; +blksend: digitalWrite(ZBS_DMA_PIN, HIGH); - delay(1); uint8_t blockbuffer[sizeof(struct blockData)]; struct blockData* bd = (struct blockData*)blockbuffer; bd->size = len; @@ -58,65 +110,127 @@ uint16_t sendBlock(const void* data, const uint16_t len) { Serial1.write(0xAA); delay(10); digitalWrite(ZBS_DMA_PIN, LOW); + txEnd(); return bd->checksum; } void sendDataAvail(struct pendingData* pending) { + if (!txStart()) return; addCRC(pending, sizeof(struct pendingData)); - Serial1.print("SDA>"); - for (uint8_t c = 0; c < sizeof(struct pendingData); c++) { - Serial1.write(((uint8_t*)pending)[c]); + for (uint8_t attempt = 0; attempt < 5; attempt++) { + cmdReplyValue = CMD_REPLY_WAIT; + Serial1.print("SDA>"); + for (uint8_t c = 0; c < sizeof(struct pendingData); c++) { + Serial1.write(((uint8_t*)pending)[c]); + } + Serial1.write(0x00); + Serial1.write(0x00); + if (waitCmdReply()) goto sdasend; + Serial.printf("SDA send failed in try %d\n", attempt); } - Serial1.write(0x00); - Serial1.write(0x00); - Serial1.write(0x00); - Serial1.write(0x00); + Serial.print("SDA failed to send...\n"); + txEnd(); + return; +sdasend: + txEnd(); } void sendCancelPending(struct pendingData* pending) { + if (!txStart()) return; addCRC(pending, sizeof(struct pendingData)); - Serial1.print("CXD>"); - for (uint8_t c = 0; c < sizeof(struct pendingData); c++) { - Serial1.write(((uint8_t*)pending)[c]); + addCRC(pending, sizeof(struct pendingData)); + for (uint8_t attempt = 0; attempt < 5; attempt++) { + cmdReplyValue = CMD_REPLY_WAIT; + Serial1.print("CXD>"); + for (uint8_t c = 0; c < sizeof(struct pendingData); c++) { + Serial1.write(((uint8_t*)pending)[c]); + } + Serial1.write(0x00); + Serial1.write(0x00); + if (waitCmdReply()) goto cxdsend; + Serial.printf("CXD send failed in try %d\n", attempt); } - Serial1.write(0x00); - Serial1.write(0x00); - Serial1.write(0x00); - Serial1.write(0x00); + Serial.print("CXD failed to send...\n"); + txEnd(); + return; +cxdsend: + txEnd(); } -uint8_t RXState = ZBS_RX_WAIT_HEADER; -char cmdbuffer[4] = {0}; -uint8_t* packetp = nullptr; -uint8_t pktlen = 0; -uint8_t pktindex = 0; -char lastchar = 0; -uint8_t charindex = 0; uint64_t waitingForVersion = 0; uint8_t crashcounter = 0; uint16_t version; -void ShortRXWaitLoop() { - if (Serial1.available()) { - lastchar = Serial1.read(); - Serial.write(lastchar); - // shift characters in - for (uint8_t c = 0; c < 3; c++) { - cmdbuffer[c] = cmdbuffer[c + 1]; - } - cmdbuffer[3] = lastchar; - } -} - void Ping() { + if (!txStart()) return; Serial1.print("VER?"); + txEnd(); waitingForVersion = esp_timer_get_time(); } +#define RX_CMD_RQB 0x01 +#define RX_CMD_ADR 0x02 +#define RX_CMD_XFC 0x03 +#define RX_CMD_XTO 0x04 + +struct rxCmd { + uint8_t* data; + uint8_t len; + uint8_t type; +}; + +void rxCmdProcessor(void* parameter) { + rxCmdQueue = xQueueCreate(30, sizeof(struct rxCmd*)); + 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); + break; + case RX_CMD_ADR: + processDataReq((struct espAvailDataReq*)rxcmd->data); + break; + case RX_CMD_XFC: + processXferComplete((struct espXferComplete*)rxcmd->data); + break; + case RX_CMD_XTO: + processXferTimeout((struct espXferComplete*)rxcmd->data); + break; + } + + if (rxcmd->data) free(rxcmd->data); + if (rxcmd) free(rxcmd); + } + } +} + +void addRXQueue(uint8_t* data, uint8_t len, uint8_t type) { + struct rxCmd* rxcmd = new struct rxCmd; + rxcmd->data = data; + rxcmd->len = len; + rxcmd->type = type; + BaseType_t queuestatus = xQueueSend(rxCmdQueue, &rxcmd, 0); + if (queuestatus == pdFALSE) { + if (data) free(data); + free(rxcmd); + } +} + void SerialRXLoop() { - if (Serial1.available()) { + static char cmdbuffer[4] = {0}; + static uint8_t* packetp = nullptr; + static uint8_t pktlen = 0; + static uint8_t pktindex = 0; + static uint8_t RXState = ZBS_RX_WAIT_HEADER; + static char lastchar = 0; + static uint8_t charindex = 0; + + while (Serial1.available()) { lastchar = Serial1.read(); - // Serial.write(lastchar); switch (RXState) { case ZBS_RX_WAIT_HEADER: Serial.write(lastchar); @@ -125,6 +239,11 @@ void SerialRXLoop() { cmdbuffer[c] = cmdbuffer[c + 1]; } cmdbuffer[3] = lastchar; + + if ((strncmp(cmdbuffer, "ACK>", 4) == 0)) cmdReplyValue = CMD_REPLY_ACK; + if ((strncmp(cmdbuffer, "NOK>", 4) == 0)) cmdReplyValue = CMD_REPLY_NOK; + if ((strncmp(cmdbuffer, "NOQ>", 4) == 0)) cmdReplyValue = CMD_REPLY_NOQ; + if ((strncmp(cmdbuffer, "VER>", 4) == 0)) { pktindex = 0; RXState = ZBS_RX_WAIT_VER; @@ -137,7 +256,6 @@ void SerialRXLoop() { pktindex = 0; packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1); memset(cmdbuffer, 0x00, 4); - restartBlockRequest = 0; } if (strncmp(cmdbuffer, "ADR>", 4) == 0) { RXState = ZBS_RX_WAIT_DATA_REQ; @@ -146,10 +264,6 @@ void SerialRXLoop() { packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1); memset(cmdbuffer, 0x00, 4); } - if (strncmp(cmdbuffer, "BST>", 4) == 0) { - Serial.print(">SYNC BURST\n"); - RXState = ZBS_RX_WAIT_HEADER; - } if (strncmp(cmdbuffer, "XFC>", 4) == 0) { RXState = ZBS_RX_WAIT_XFERCOMPLETE; pktindex = 0; @@ -167,8 +281,7 @@ void SerialRXLoop() { packetp[pktindex] = lastchar; pktindex++; if (pktindex == sizeof(struct espBlockRequest)) { - processBlockRequest((struct espBlockRequest*)packetp); - free(packetp); + addRXQueue(packetp, pktindex, RX_CMD_RQB); RXState = ZBS_RX_WAIT_HEADER; } break; @@ -176,9 +289,7 @@ void SerialRXLoop() { packetp[pktindex] = lastchar; pktindex++; if (pktindex == sizeof(struct espXferComplete)) { - struct espXferComplete* xfc = (struct espXferComplete*)packetp; - processXferComplete(xfc); - free(packetp); + addRXQueue(packetp, pktindex, RX_CMD_XFC); RXState = ZBS_RX_WAIT_HEADER; } break; @@ -186,9 +297,7 @@ void SerialRXLoop() { packetp[pktindex] = lastchar; pktindex++; if (pktindex == sizeof(struct espXferComplete)) { - struct espXferComplete* xfc = (struct espXferComplete*)packetp; - processXferTimeout(xfc); - free(packetp); + addRXQueue(packetp, pktindex, RX_CMD_XTO); RXState = ZBS_RX_WAIT_HEADER; } break; @@ -196,9 +305,7 @@ void SerialRXLoop() { packetp[pktindex] = lastchar; pktindex++; if (pktindex == sizeof(struct espAvailDataReq)) { - struct espAvailDataReq* adr = (struct espAvailDataReq*)packetp; - processDataReq(adr); - free(packetp); + addRXQueue(packetp, pktindex, RX_CMD_ADR); RXState = ZBS_RX_WAIT_HEADER; } break; @@ -220,6 +327,8 @@ void SerialRXLoop() { extern uint8_t* getDataForFile(File* file); void zbsRxTask(void* parameter) { + xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 10000, NULL, configMAX_PRIORITIES - 10, NULL); + Serial1.begin(228571, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); rampTagPower(FLASHER_AP_POWER, true);