diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index f4a89a8e9..a46809e26 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -220,14 +220,12 @@ extern "C" { uint32_t EspFlashBaseAddress(void) { const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr); if (!partition) { return 0; } - return partition->address; // For tasmota 0x00010000 or 0x00200000 } uint32_t EspFlashBaseEndAddress(void) { const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr); if (!partition) { return 0; } - return partition->address + partition->size; // For tasmota 0x00200000 or 0x003F0000 } @@ -409,18 +407,13 @@ uint32_t FlashWriteMaxSector(void) { uint8_t* FlashDirectAccess(void) { uint32_t address = FlashWriteStartSector() * SPI_FLASH_SEC_SIZE; uint8_t* data = EspFlashMmap(address); - /* AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Flash start address 0x%08X, Mmap address 0x%08X"), address, data); uint8_t buf[32]; memcpy(buf, data, sizeof(buf)); AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buf, 32); - - memcpy(buf, data, sizeof(buf)); - AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buf + , 32); */ - return data; } #endif // ESP32 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 43631ef21..8f387e4a0 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2591,7 +2591,7 @@ uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) { } } BUpload.spi_sector_cursor++; - if (!ESP.flashWrite((BUpload.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((BUpload.spi_sector_cursor -1) * 2048), (uint32_t*)buf, size)) { + if (!ESP.flashWrite((BUpload.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((BUpload.spi_sector_cursor -1) * HTTP_UPLOAD_BUFLEN), (uint32_t*)buf, size)) { return 7; // Upload aborted - flash failed } BUpload.spi_hex_size += size; @@ -2824,6 +2824,8 @@ void HandleUploadLoop(void) #ifdef USE_WEB_FW_UPGRADE else if (BUpload.active) { // Write a block +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Size %d"), upload.currentSize); +// AddLogBuffer(LOG_LEVEL_DEBUG, upload.buf, 32); Web.upload_error = BUploadWriteBuffer(upload.buf, upload.currentSize); if (Web.upload_error != 0) { return; } } @@ -2905,7 +2907,7 @@ void HandleUploadLoop(void) #endif // USE_RF_FLASH #ifdef USE_TASMOTA_CLIENT if (UPL_TASMOTACLIENT == Web.upload_file_type) { - error = TasmotaClient_Flash(FlashWriteStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size); + error = TasmotaClient_Flash(data, BUpload.spi_hex_size); } #endif // USE_TASMOTA_CLIENT #ifdef SHELLY_FW_UPGRADE diff --git a/tasmota/xdrv_31_tasmota_client.ino b/tasmota/xdrv_31_tasmota_client.ino index 0982520d8..70bdd2c41 100644 --- a/tasmota/xdrv_31_tasmota_client.ino +++ b/tasmota/xdrv_31_tasmota_client.ino @@ -22,122 +22,115 @@ * Tasmota to microcontroller \*********************************************************************************************/ -#define XDRV_31 31 +#define XDRV_31 31 #ifndef USE_TASMOTA_CLIENT_FLASH_SPEED -#define USE_TASMOTA_CLIENT_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants +#define USE_TASMOTA_CLIENT_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants #endif #ifndef USE_TASMOTA_CLIENT_SERIAL_SPEED -#define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini +#define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini #endif -#define CONST_STK_CRC_EOP 0x20 +#define TASMOTA_CLIENT_LIB_VERSION 20191129 +#define TASMOTA_CLIENT_TIMEOUT 250 // mSeconds -#define CMND_STK_GET_SYNC 0x30 -#define CMND_STK_SET_DEVICE 0x42 -#define CMND_STK_SET_DEVICE_EXT 0x45 -#define CMND_STK_ENTER_PROGMODE 0x50 -#define CMND_STK_LEAVE_PROGMODE 0x51 -#define CMND_STK_LOAD_ADDRESS 0x55 -#define CMND_STK_PROG_PAGE 0x64 +#define CONST_STK_CRC_EOP 0x20 + +#define CMND_STK_GET_SYNC 0x30 +#define CMND_STK_SET_DEVICE 0x42 +#define CMND_STK_SET_DEVICE_EXT 0x45 +#define CMND_STK_ENTER_PROGMODE 0x50 +#define CMND_STK_LEAVE_PROGMODE 0x51 +#define CMND_STK_LOAD_ADDRESS 0x55 +#define CMND_STK_PROG_PAGE 0x64 /*************************************************\ * Tasmota Client Specific Commands \*************************************************/ -#define CMND_START 0xFC -#define CMND_END 0xFD +#define CMND_START 0xFC +#define CMND_END 0xFD -#define CMND_FEATURES 0x01 -#define CMND_JSON 0x02 -#define CMND_FUNC_EVERY_SECOND 0x03 -#define CMND_FUNC_EVERY_100_MSECOND 0x04 -#define CMND_CLIENT_SEND 0x05 -#define CMND_PUBLISH_TELE 0x06 -#define CMND_EXECUTE_CMND 0x07 +#define CMND_FEATURES 0x01 +#define CMND_JSON 0x02 +#define CMND_FUNC_EVERY_SECOND 0x03 +#define CMND_FUNC_EVERY_100_MSECOND 0x04 +#define CMND_CLIENT_SEND 0x05 +#define CMND_PUBLISH_TELE 0x06 +#define CMND_EXECUTE_CMND 0x07 -#define PARAM_DATA_START 0xFE -#define PARAM_DATA_END 0xFF +#define PARAM_DATA_START 0xFE +#define PARAM_DATA_END 0xFF #include -/* - * Embedding class in here since its rather specific to Arduino bootloader - */ - -class SimpleHexParse { - public: - SimpleHexParse(void); - uint8_t parseLine(char *hexline); - uint8_t ptr_l = 0; - uint8_t ptr_h = 0; - bool PageIsReady = false; - bool firstrun = true; - bool EndOfFile = false; - uint8_t FlashPage[128]; - uint8_t FlashPageIdx = 0; - uint8_t layoverBuffer[16]; - uint8_t layoverIdx = 0; - uint8_t getByte(char *hexline, uint8_t idx); -}; - -SimpleHexParse::SimpleHexParse(void) { +struct SimpleHexParse { + uint8_t FlashPage[128]; + uint8_t layoverBuffer[16]; + uint8_t FlashPageIdx; + uint8_t layoverIdx; + uint8_t ptr_l; + uint8_t ptr_h; + bool firstrun; + bool EndOfFile; +} SHParse; +uint8_t SimpleHexParseGetByte(char* hexline, uint8_t idx) { + char buff[3]; + buff[3] = '\0'; + memcpy(&buff, &hexline[(idx*2)-2], 2); + return strtol(buff, 0, 16); } -uint8_t SimpleHexParse::parseLine(char *hexline) { - if (layoverIdx) { - memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); - FlashPageIdx = layoverIdx; - layoverIdx = 0; +uint32_t SimpleHexParseLine(char *hexline) { + if (SHParse.layoverIdx) { + memcpy(&SHParse.FlashPage, &SHParse.layoverBuffer, SHParse.layoverIdx); + SHParse.FlashPageIdx = SHParse.layoverIdx; + SHParse.layoverIdx = 0; } - uint8_t len = getByte(hexline, 1); - uint8_t addr_h = getByte(hexline, 2); - uint8_t addr_l = getByte(hexline, 3); - uint8_t rectype = getByte(hexline, 4); + + // 10 00 00 00 0C945D000C9485000C9485000C948500 84 + uint8_t len = SimpleHexParseGetByte(hexline, 1); + uint8_t addr_h = SimpleHexParseGetByte(hexline, 2); + uint8_t addr_l = SimpleHexParseGetByte(hexline, 3); + uint8_t rectype = SimpleHexParseGetByte(hexline, 4); + +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Hexline |%s|, Len %d, Address 0x%02X%02X, RecType %d"), hexline, len, addr_h, addr_l, rectype); + + if (len > 16) { return 4; } // Error 4: Line too long + if (rectype > 1) { return 5; } // Error 5: Invalid record type + for (uint8_t idx = 0; idx < len; idx++) { - if (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = getByte(hexline, idx+5); - FlashPageIdx++; - } else { // We have layover bytes - layoverBuffer[layoverIdx] = getByte(hexline, idx+5); - layoverIdx++; - } - } - if (1 == rectype) { - EndOfFile = true; - while (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = 0xFF; - FlashPageIdx++; + if (SHParse.FlashPageIdx < sizeof(SHParse.FlashPage)) { + SHParse.FlashPage[SHParse.FlashPageIdx] = SimpleHexParseGetByte(hexline, idx+5); + SHParse.FlashPageIdx++; + } else { // We have layover bytes + SHParse.layoverBuffer[SHParse.layoverIdx] = SimpleHexParseGetByte(hexline, idx+5); + SHParse.layoverIdx++; } } - if (FlashPageIdx == 128) { - if (firstrun) { - firstrun = false; + + if (1 == rectype) { + SHParse.EndOfFile = true; + while (SHParse.FlashPageIdx < sizeof(SHParse.FlashPage)) { + SHParse.FlashPage[SHParse.FlashPageIdx] = 0xFF; + SHParse.FlashPageIdx++; + } + } + + if (SHParse.FlashPageIdx == sizeof(SHParse.FlashPage)) { + if (SHParse.firstrun) { + SHParse.firstrun = false; } else { - ptr_l += 0x40; - if (ptr_l == 0) { - ptr_l = 0; - ptr_h++; + SHParse.ptr_l += 0x40; + if (SHParse.ptr_l == 0) { + SHParse.ptr_h++; } } - firstrun = false; - PageIsReady = true; } return 0; } -uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) { - char buff[3]; - buff[3] = '\0'; - memcpy(&buff, &hexline[(idx*2)-1], 2); - return strtol(buff, 0, 16); -} - -/* - * End of embedded class SimpleHexParse - */ - struct TCLIENT { uint8_t inverted = LOW; bool type = false; @@ -226,9 +219,37 @@ uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout) { return 0; } +uint8_t TasmotaClient_receiveData(char* buffer, int size) { + uint8_t index = 255; + int timer = 0; + while (timer < TASMOTA_CLIENT_TIMEOUT) { + int data = TasmotaClient_Serial->read(); + if (data >= 0) { + if (PARAM_DATA_START == data) { index = 0; } // Start of data + else if (PARAM_DATA_END == data) { break; } // End of data + else if (index < 255) { + buffer[index++] = (char)data; // Data + if (index == size) { break; } // No EoD received or done + } + } else { + delay(1); + timer++; + } + } + if (255 == index) { index = 0; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TCL: ReceiveData")); + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)buffer, index); + + return index; +} + uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("TCL: SendBytes")); +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&bytes, count); + TasmotaClient_Serial->write(bytes, count); - TasmotaClient_waitForSerialData(2, 250); + TasmotaClient_waitForSerialData(2, TASMOTA_CLIENT_TIMEOUT); uint8_t sync = TasmotaClient_Serial->read(); uint8_t ok = TasmotaClient_Serial->read(); if ((sync == 0x14) && (ok == 0x10)) { @@ -261,10 +282,16 @@ uint8_t TasmotaClient_exitProgMode(void) { uint8_t TasmotaClient_SetupFlash(void) { uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; + +/* + TasmotaClient_Serial->end(); + delay(10); + TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_FLASH_SPEED); if (TasmotaClient_Serial->hardwareSerial()) { ClaimSerial(); } +*/ TasmotaClient_Reset(); @@ -313,7 +340,7 @@ uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo) { return TasmotaClient_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); } -void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { +void TasmotaClient_flashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; TasmotaClient_loadAddress(addr_h, addr_l); TasmotaClient_Serial->write(Header, 4); @@ -321,58 +348,73 @@ void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) { TasmotaClient_Serial->write(data[i]); } TasmotaClient_Serial->write(CONST_STK_CRC_EOP); - TasmotaClient_waitForSerialData(2, 250); + TasmotaClient_waitForSerialData(2, TASMOTA_CLIENT_TIMEOUT); TasmotaClient_Serial->read(); TasmotaClient_Serial->read(); } -uint32_t TasmotaClient_Flash(uint32_t data, size_t size) { +uint32_t TasmotaClient_Flash(uint8_t* data, size_t size) { if (!TasmotaClient_SetupFlash()) { // AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Flashing aborted!")); - return 1; + return 1; // Error 1: Flashing aborted } + SHParse.FlashPageIdx = 0; + SHParse.layoverIdx = 0; + SHParse.ptr_l = 0; + SHParse.ptr_h = 0; + SHParse.firstrun = true; + SHParse.EndOfFile = false; + + char flash_buffer[512]; + char thishexline[50]; uint32_t read = 0; uint32_t processed = 0; - char thishexline[50]; - uint8_t position = 0; + uint32_t position = 0; - SimpleHexParse hexParse = SimpleHexParse(); - char* flash_buffer = new char[SPI_FLASH_SEC_SIZE]; - uint32_t flash_start = data; - bool reading = true; - while (reading) { - ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); - read = read + SPI_FLASH_SEC_SIZE; - if (read >= size) { - reading = false; - } - for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { + uint32_t error = 0; + while (read < size) { + memcpy(flash_buffer, data + read, sizeof(flash_buffer)); + +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)flash_buffer, 32); + + read = read + sizeof(flash_buffer); + for (uint32_t ca = 0; ca < sizeof(flash_buffer); ca++) { processed++; - if ((processed <= size) && (!hexParse.EndOfFile)) { + if ((processed <= size) && (!SHParse.EndOfFile)) { + // flash_buffer = :100000000C945D000C9485000C9485000C94850084<0x0D><0x0A> if (':' == flash_buffer[ca]) { position = 0; } - if (0x0D == flash_buffer[ca]) { + else if (0xFF == (uint8_t)flash_buffer[ca]) { +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Size %d, Processed %d"), size, processed); +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&flash_buffer[ca], 8); + error = 3; // Error 3: Invalid data + break; + } + else if (0x0D == flash_buffer[ca]) { + // 100000000C945D000C9485000C9485000C94850084 thishexline[position] = 0; - hexParse.parseLine(thishexline); - if (hexParse.PageIsReady) { - TasmotaClient_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); - hexParse.PageIsReady = false; - hexParse.FlashPageIdx = 0; + error = SimpleHexParseLine(thishexline); + if (error) { break; } // Error 4 and 5 + if (SHParse.FlashPageIdx == sizeof(SHParse.FlashPage)) { + TasmotaClient_flashPage(SHParse.ptr_h, SHParse.ptr_l, SHParse.FlashPage); + SHParse.FlashPageIdx = 0; } - } else { - if (0x0A != flash_buffer[ca]) { - thishexline[position] = flash_buffer[ca]; - position++; + } + else if (0x0A != flash_buffer[ca]) { + if (position < sizeof(thishexline) -2) { + thishexline[position++] = flash_buffer[ca]; } } } } + if (error) { break; } } + TasmotaClient_exitProgMode(); // AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Flash done!")); - return 0; + return error; } void TasmotaClient_Init(void) { @@ -391,7 +433,6 @@ void TasmotaClient_Init(void) { if (TasmotaClient_Serial->hardwareSerial()) { ClaimSerial(); } - TasmotaClient_Serial->setTimeout(100); // Theo 20200502 - increase from 50 if (PinUsed(GPIO_TASMOTACLIENT_RST_INV)) { SetPin(Pin(GPIO_TASMOTACLIENT_RST_INV), AGPIO(GPIO_TASMOTACLIENT_RST)); TClient.inverted = HIGH; @@ -405,20 +446,19 @@ void TasmotaClient_Init(void) { } if (TClient.SerialEnabled) { // All go for hardware now we need to detect features if there are any TasmotaClient_sendCmnd(CMND_FEATURES, 0); - char buffer[32] = { 0 }; - TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); - uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); - if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } // Theo 20200502 - DMP: 99 17 34 01 02 00 00 00 - - memcpy(&TClientSettings, &buffer, sizeof(TClientSettings)); - if (20191129 == TClientSettings.features_version) { - TClient.type = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version); - } else { - if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version); - TClient.unsupported = true; + char buffer[sizeof(TClientSettings)]; + uint8_t len = TasmotaClient_receiveData(buffer, sizeof(buffer)); // 99 17 34 01 02 00 00 00 + if (len == sizeof(TClientSettings)) { + memcpy(&TClientSettings, &buffer, sizeof(TClientSettings)); + if (TASMOTA_CLIENT_LIB_VERSION == TClientSettings.features_version) { + TClient.type = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version); + } else { + if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version); + TClient.unsupported = true; + } } } } @@ -430,10 +470,11 @@ bool TasmotaClient_Available(void) { void TasmotaClient_Show(void) { if ((TClient.type) && (TClientSettings.features.func_json_append)) { - char buffer[100]; TasmotaClient_sendCmnd(CMND_JSON, 0); - TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); - uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); + + char buffer[100]; + uint8_t len = TasmotaClient_receiveData(buffer, sizeof(buffer) -1); + buffer[len] = '\0'; ResponseAppend_P(PSTR(",\"TasmotaClient\":%s"), buffer); } @@ -447,7 +488,8 @@ void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param) { memcpy(&buffer[1], &TClientCommand, sizeof(TClientCommand)); buffer[sizeof(TClientCommand)+1] = CMND_END; - TasmotaClient_Serial->flush(); // Theo 20200502 +// AddLog_P(LOG_LEVEL_DEBUG, PSTR("TCL: SendCmnd")); +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buffer, sizeof(buffer)); for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { TasmotaClient_Serial->write(buffer[ca]);