diff --git a/examples/Brain/program_esp32_uart/program_esp32_uart.ino b/examples/Brain/program_esp32_uart/program_esp32_uart.ino index a9344d6..01a35f3 100644 --- a/examples/Brain/program_esp32_uart/program_esp32_uart.ino +++ b/examples/Brain/program_esp32_uart/program_esp32_uart.ino @@ -21,7 +21,7 @@ #define ESP32_SUPPORTS_ENCRYPTED_FLASH false #define ESP32_BAUDRATE 921600 -// #define ESP32_BAUDRATE 115200 +//#define ESP32_BAUDRATE 115200 // Bin files on SDCard to program // These files can be generated by any of Arduino sketches @@ -106,7 +106,7 @@ void setup() { } print_speed(total_bytes, millis() - ms); - Brain.esp32_end(); + Brain.esp32_end(false); // reset ESP32 to run new firmware Brain.targetReset(); @@ -131,6 +131,7 @@ void setup1() { // core1's loop: process usb host task on core1 void loop1() { Brain.USBHost.task(); + // Serial.flush(); } //--------------------------------------------------------------------+ diff --git a/src/Adafruit_TestBed_Brains.cpp b/src/Adafruit_TestBed_Brains.cpp index e415546..ca0a913 100644 --- a/src/Adafruit_TestBed_Brains.cpp +++ b/src/Adafruit_TestBed_Brains.cpp @@ -414,8 +414,8 @@ bool Adafruit_TestBed_Brains::esp32_begin(ESP32BootROMClass *bootrom, return ret; } -void Adafruit_TestBed_Brains::esp32_end(void) { - esp32boot->endFlash(false); +void Adafruit_TestBed_Brains::esp32_end(bool reset_esp) { + esp32boot->endFlash(reset_esp); esp32boot->end(); } @@ -473,8 +473,9 @@ size_t Adafruit_TestBed_Brains::essp32_programFlash(const char *fpath, // Stub only writes each block to flash after 'ack'ing the receive, // so do a final dummy operation which will not be 'ack'ed // until the last block has actually been written out to flash - // esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout) - (void) esp32boot->read_chip_detect(); + if ( esp32boot->isRunningStub() ) { + while ( !esp32boot->read_chip_detect() ) {} + } //------------- MD5 verification -------------// md5.calculate(); diff --git a/src/Adafruit_TestBed_Brains.h b/src/Adafruit_TestBed_Brains.h index a0b942c..d2e77c9 100644 --- a/src/Adafruit_TestBed_Brains.h +++ b/src/Adafruit_TestBed_Brains.h @@ -85,7 +85,7 @@ public: //--------------------------------------------------------------------+ bool esp32_begin(ESP32BootROMClass *bootrom, uint32_t baudrate); - void esp32_end(void); + void esp32_end(bool reset_esp); // program esp32 target with file from SDCard // return number of programmed bytes diff --git a/src/ESP32BootROM.cpp b/src/ESP32BootROM.cpp index 1be63a3..3fe3616 100644 --- a/src/ESP32BootROM.cpp +++ b/src/ESP32BootROM.cpp @@ -218,6 +218,7 @@ int ESP32BootROMClass::begin(unsigned long baudrate) { if (need_stub) { VERIFY(uploadStub()); + VERIFY(syncStub(3000)); } if (baudrate != 115200) { @@ -263,8 +264,15 @@ int ESP32BootROMClass::sync() { return (results[0] == 0); } -int ESP32BootROMClass::changeBaudrate(unsigned long baudrate) { - const uint32_t data[2] = {baudrate, 0}; +int ESP32BootROMClass::changeBaudrate(uint32_t baudrate) { + // Two 32-bit words: + // - new baud rate, and + // - 0 if we are talking to the ROM loader or the current/old baud rate if we are talking to the stub loader. + uint32_t data[2] = {baudrate, 0}; + + if (_stub_running) { + data[1] = 115200; // we only changed from 115200 to higher baud + } command(ESP_CHANGE_BAUDRATE, data, sizeof(data)); return (response(ESP_CHANGE_BAUDRATE, 3000) == 0); @@ -278,6 +286,10 @@ int ESP32BootROMClass::spiAttach() { return (response(ESP_SPI_ATTACH, 3000) == 0); } +bool ESP32BootROMClass::isRunningStub(void) { + return _stub_running; +} + uint32_t ESP32BootROMClass::getFlashWriteSize(void) { return _stub_running ? FLASH_WRITE_SIZE_STUB : FLASH_WRITE_SIZE_NOSTUB; } @@ -297,20 +309,14 @@ int ESP32BootROMClass::beginFlash(uint32_t offset, uint32_t size, } int ESP32BootROMClass::dataFlash(const void *data, uint32_t length) { - uint32_t cmdData[4 + (_chunkSize / 4)]; + uint32_t header[4]; - cmdData[0] = length; - cmdData[1] = _flashSequenceNumber++; - cmdData[2] = 0; - cmdData[3] = 0; + header[0] = length; + header[1] = _flashSequenceNumber++; + header[2] = 0; + header[3] = 0; - memcpy(&cmdData[4], data, length); - - if (length < _chunkSize) { - memset(&cmdData[4 + (length / 4)], 0xff, _chunkSize - length); - } - - command(ESP_FLASH_DATA, cmdData, sizeof(cmdData)); + command(ESP_FLASH_DATA, header, sizeof(header), data, length); return (response(ESP_FLASH_DATA, 3000) == 0); } @@ -330,14 +336,14 @@ bool ESP32BootROMClass::md5Flash(uint32_t offset, uint32_t size, command(ESP_SPI_FLASH_MD5, data, sizeof(data)); uint8_t resp[32]; - VERIFY(0 == response(ESP_SPI_FLASH_MD5, 3000, resp)); + VERIFY(0 == response(ESP_SPI_FLASH_MD5, 5000, resp)); // Note that the ESP32 ROM loader returns the md5sum as 32 hex encoded ASCII // bytes, whereas the stub loader returns the md5sum as 16 raw data bytes of // MD5 followed by 2 status bytes. if (_stub_running) { memcpy(result, resp, 16); - }else { + } else { char temp[3] = {0, 0, 0}; for (int i = 0; i < 16; i++) { @@ -440,11 +446,13 @@ bool ESP32BootROMClass::syncStub(uint32_t timeout_ms) { uint8_t buf[4]; uint8_t count = 0; + Serial.println("Syncing stub..."); + if (!readSLIP(timeout_ms)) { return -1; } - if ( 4 != readBytes(buf, 4, timeout_ms) ) { + if (4 != readBytes(buf, 4, timeout_ms)) { return -1; } @@ -501,10 +509,6 @@ bool ESP32BootROMClass::uploadStub(void) { Serial.println("Running stub..."); VERIFY(endMem(stub_esp32_entry)); - // sync stub - Serial.println("Syncing stub..."); - VERIFY(syncStub(3000)); - _stub_running = true; return true; @@ -515,25 +519,33 @@ bool ESP32BootROMClass::uploadStub(void) { //--------------------------------------------------------------------+ void ESP32BootROMClass::command(uint8_t opcode, const void *data, - uint16_t length) { + uint16_t len, const void* data2, uint16_t len2) { uint32_t checksum = 0; + // for FLASH_DATA and MEM_DATA: data is header, data2 is actual payload if (opcode == ESP_FLASH_DATA || opcode == ESP_MEM_DATA) { checksum = ESP_CHECKSUM_MAGIC; // seed - for (uint16_t i = 16; i < length; i++) { - checksum ^= ((const uint8_t *)data)[i]; + for (uint16_t i = 0; i < len2; i++) { + checksum ^= ((const uint8_t *)data2)[i]; } } - DBG_PRINTF("=> c0 00 %02x %02x %02x ", opcode, length & 0x00ff, length >> 8); + uint16_t const total_len = len + len2; + + DBG_PRINTF("=> c0 00 %02x %04x ", opcode, total_len); _serial->write(0xc0); _serial->write((uint8_t)0x00); // direction _serial->write(opcode); - _serial->write((uint8_t *)&length, sizeof(length)); + _serial->write((uint8_t *)&total_len, 2); + writeEscapedBytes((uint8_t *)&checksum, sizeof(checksum)); - writeEscapedBytes((uint8_t *)data, length); + writeEscapedBytes((uint8_t *)data, len); + if ( data2 && len2 ) { + writeEscapedBytes((uint8_t *)data2, len2); + } + _serial->write(0xc0); _serial->flush(); @@ -563,15 +575,17 @@ uint16_t ESP32BootROMClass::readBytes(void *buf, uint16_t length, uint8_t ch = (uint8_t)_serial->read(); // escape - if ( ch == 0xdb ) { - while(!_serial->available() && ((millis() - start) < timeout_ms) ) { yield(); } - uint8_t ch2 = (uint8_t) _serial->read(); + if (ch == 0xdb) { + while (!_serial->available() && ((millis() - start) < timeout_ms)) { + yield(); + } + uint8_t ch2 = (uint8_t)_serial->read(); - if ( ch2 == 0xdb ) { + if (ch2 == 0xdb) { ch = 0xdb; - }else if ( ch2 == 0xdc ) { + } else if (ch2 == 0xdc) { ch = 0xc0; - }else { + } else { // should not reach here, must be an error or uart noise break; } @@ -601,7 +615,7 @@ int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms, void *body, uint32_t reg_value; // Response value used by READ_REG command. Zero otherwise. } fixed_resp; - uint8_t status[4] = { 0 }; + uint8_t status[4] = {0}; uint8_t const status_len = (_stub_running ? 2 : 4); #if 1 @@ -619,7 +633,7 @@ int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms, void *body, // read variable payload if any uint16_t const payload_len = fixed_resp.length - status_len; - uint8_t data[100]; + uint8_t data[payload_len]; if (payload_len) { if (payload_len != readBytes(data, payload_len, end_ms - millis())) { @@ -640,7 +654,7 @@ int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms, void *body, return -1; // probably timeout } - if ( !readSLIP(end_ms - millis()) ) { + if (!readSLIP(end_ms - millis())) { return -1; } @@ -654,7 +668,6 @@ int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms, void *body, Serial.printf("%02x ", status[i]); } Serial.println("c0"); - Serial.flush(); #endif // check direction, opcode and status @@ -663,7 +676,8 @@ int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms, void *body, return 0; // status[0]; } - Serial.printf("response failed status = %02x %02x!\r\n", status[0], status[1]); + Serial.printf("response failed status = %02x %02x!\r\n", status[0], + status[1]); return -1; @@ -729,7 +743,7 @@ void ESP32BootROMClass::writeEscapedBytes(const uint8_t *data, #if DEBUG // skip flashing data since it is a lot to print - bool const print_payload = (length > 1024) ? false : true; + bool const print_payload = (length >= 1024) ? false : true; #endif while (written < length) { diff --git a/src/ESP32BootROM.h b/src/ESP32BootROM.h index 6366ad2..fef06fb 100644 --- a/src/ESP32BootROM.h +++ b/src/ESP32BootROM.h @@ -39,6 +39,7 @@ public: bool read_MAC(uint8_t mac[6]); uint32_t read_chip_detect(void); + bool isRunningStub(void); uint32_t getFlashWriteSize(void); int beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize); @@ -48,10 +49,10 @@ public: private: int sync(); - int changeBaudrate(unsigned long baudrate); + int changeBaudrate(uint32_t baudrate); int spiAttach(); - void command(uint8_t opcode, const void *data, uint16_t length); + void command(uint8_t opcode, const void *data, uint16_t length, const void* data2 = NULL, uint16_t len2 = 0); int response(uint8_t opcode, uint32_t timeout_ms, void *body = NULL, uint16_t maxlen = 4);