From a835833d944d5b40a86546e2db9c24e8ff64a764 Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 14 Dec 2018 11:57:19 +0100 Subject: [PATCH 01/10] [PUYA] Applied ESPeasy puya_v3.patch Applied the patch to get the starting point as described in https://github.com/esp8266/Arduino/issues/5493 --- cores/esp8266/Esp.cpp | 30 ++++++++++++++++++++++++++---- cores/esp8266/Esp.h | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 8dc37ff2a5..24884c38f7 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -569,11 +569,33 @@ bool EspClass::flashEraseSector(uint32_t sector) { return rc == 0; } +static uint32_t flash_chip_id = 0; + +bool EspClass::flashIsPuya(){ + return ((flash_chip_id & 0x000000ff) == 0x85); // 0x146085 PUYA +} + bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { - ets_isr_mask(FLASH_INT_MASK); - int rc = spi_flash_write(offset, (uint32_t*) data, size); - ets_isr_unmask(FLASH_INT_MASK); - return rc == 0; + if (flash_chip_id == 0) + flash_chip_id = getFlashChipId(); + ets_isr_mask(FLASH_INT_MASK); + int rc; + uint32_t* ptr = data; + if (flashIsPuya()) { + static uint32_t read_buf[SPI_FLASH_SEC_SIZE / 4]; + rc = spi_flash_read(offset, read_buf, size); + if (rc != 0) { + ets_isr_unmask(FLASH_INT_MASK); + return false; + } + for (size_t i = 0; i < size / 4; ++i) { + read_buf[i] &= data[i]; + } + ptr = read_buf; + } + rc = spi_flash_write(offset, ptr, size); + ets_isr_unmask(FLASH_INT_MASK); + return rc == 0; } bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) { diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index b2ee09144b..d4d11fe203 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -23,6 +23,8 @@ #include +#define PUYASUPPORT + /** * AVR macros for WDT managment */ @@ -141,6 +143,7 @@ class EspClass { bool flashWrite(uint32_t offset, uint32_t *data, size_t size); bool flashRead(uint32_t offset, uint32_t *data, size_t size); + bool flashIsPuya(); uint32_t getSketchSize(); String getSketchMD5(); uint32_t getFreeSketchSpace(); From 0293a9e8b450144830ff5835bd6c3426def77cc3 Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 14 Dec 2018 15:14:43 +0100 Subject: [PATCH 02/10] [PUYA] Only allocate memory when PUYA detected core 2.5.0 PUYA patch, no puya: Description Function #calls call/sec min (ms) Avg (ms) max (ms) Save File 4 0.25 34.755 45.264 67.620 Free Mem: 16168 core 2.5.0 PUYA patch, Faked Puya detect: Description Function #calls call/sec min (ms) Avg (ms) max (ms) Save File 2 0.04 41.332 57.544 73.756 Free Mem: 11560 --- cores/esp8266/Esp.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 24884c38f7..45a46fa832 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -571,8 +571,20 @@ bool EspClass::flashEraseSector(uint32_t sector) { static uint32_t flash_chip_id = 0; +// PUYA flash chips need to read entire sector, update in memory and write sector again. +static uint32_t *flash_write_puya_buf = 0; + bool EspClass::flashIsPuya(){ - return ((flash_chip_id & 0x000000ff) == 0x85); // 0x146085 PUYA + if (flash_write_puya_buf != 0) { + // Already detected PUYA and allocated buffer. + return true; + } + bool isPuya = ((flash_chip_id & 0x000000ff) == 0x85); // 0x146085 PUYA + if (isPuya) { + flash_write_puya_buf = (uint32_t*) malloc((SPI_FLASH_SEC_SIZE / 4) * sizeof(uint32_t)); + // No need to ever free this, since the flash chip will never change at runtime. + } + return isPuya; } bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { @@ -581,17 +593,21 @@ bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { ets_isr_mask(FLASH_INT_MASK); int rc; uint32_t* ptr = data; + if (flashIsPuya()) { - static uint32_t read_buf[SPI_FLASH_SEC_SIZE / 4]; - rc = spi_flash_read(offset, read_buf, size); + if (flash_write_puya_buf == 0) { + // Memory could not be allocated. + return false; + } + rc = spi_flash_read(offset, flash_write_puya_buf, size); if (rc != 0) { ets_isr_unmask(FLASH_INT_MASK); return false; } for (size_t i = 0; i < size / 4; ++i) { - read_buf[i] &= data[i]; + flash_write_puya_buf[i] &= data[i]; } - ptr = read_buf; + ptr = flash_write_puya_buf; } rc = spi_flash_write(offset, ptr, size); ets_isr_unmask(FLASH_INT_MASK); From 715fc998496754f9ebadcf5c21a605fc9fdedf4d Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 14 Dec 2018 15:51:02 +0100 Subject: [PATCH 03/10] [PUYA] Check for PUYA chip as soon as possible at boot Check for PUYA chip in call for `getFlashChipId()` This will only be done once and the result of the get function is also cached. --- cores/esp8266/Esp.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 45a46fa832..fe202a9bbd 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -266,7 +266,13 @@ uint8_t EspClass::getCpuFreqMHz(void) uint32_t EspClass::getFlashChipId(void) { - return spi_flash_get_id(); + static uint32_t flash_chip_id = 0; + if (flash_chip_id == 0) { + flash_chip_id = spi_flash_get_id(); + // Check for PUYA chip and allocate buffer as soon as possible. + flashIsPuya(); + } + return flash_chip_id; } uint32_t EspClass::getFlashChipRealSize(void) @@ -569,8 +575,6 @@ bool EspClass::flashEraseSector(uint32_t sector) { return rc == 0; } -static uint32_t flash_chip_id = 0; - // PUYA flash chips need to read entire sector, update in memory and write sector again. static uint32_t *flash_write_puya_buf = 0; @@ -579,7 +583,7 @@ bool EspClass::flashIsPuya(){ // Already detected PUYA and allocated buffer. return true; } - bool isPuya = ((flash_chip_id & 0x000000ff) == 0x85); // 0x146085 PUYA + bool isPuya = ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA if (isPuya) { flash_write_puya_buf = (uint32_t*) malloc((SPI_FLASH_SEC_SIZE / 4) * sizeof(uint32_t)); // No need to ever free this, since the flash chip will never change at runtime. @@ -588,8 +592,6 @@ bool EspClass::flashIsPuya(){ } bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { - if (flash_chip_id == 0) - flash_chip_id = getFlashChipId(); ets_isr_mask(FLASH_INT_MASK); int rc; uint32_t* ptr = data; From ed5a14e412ae14049e56a65f2c29ca6395b1937f Mon Sep 17 00:00:00 2001 From: TD-er Date: Sat, 15 Dec 2018 00:40:00 +0100 Subject: [PATCH 04/10] [PUYA] Use limited buffer (512 byte) allocated at first write No need to allocate a buffer when not writing to flash. The default buffer size is 512 bytes, which is 2 pages in the flash chip. --- cores/esp8266/Esp.cpp | 53 ++++++++++++++++++++++++++----------------- cores/esp8266/Esp.h | 6 +++++ 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index fe202a9bbd..0b8d463ebd 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -269,8 +269,6 @@ uint32_t EspClass::getFlashChipId(void) static uint32_t flash_chip_id = 0; if (flash_chip_id == 0) { flash_chip_id = spi_flash_get_id(); - // Check for PUYA chip and allocate buffer as soon as possible. - flashIsPuya(); } return flash_chip_id; } @@ -575,7 +573,7 @@ bool EspClass::flashEraseSector(uint32_t sector) { return rc == 0; } -// PUYA flash chips need to read entire sector, update in memory and write sector again. +// PUYA flash chips need to read existing data, update in memory and write modified data again. static uint32_t *flash_write_puya_buf = 0; bool EspClass::flashIsPuya(){ @@ -583,35 +581,48 @@ bool EspClass::flashIsPuya(){ // Already detected PUYA and allocated buffer. return true; } - bool isPuya = ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA - if (isPuya) { - flash_write_puya_buf = (uint32_t*) malloc((SPI_FLASH_SEC_SIZE / 4) * sizeof(uint32_t)); - // No need to ever free this, since the flash chip will never change at runtime. - } - return isPuya; + return ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA } bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { ets_isr_mask(FLASH_INT_MASK); - int rc; + int rc = 0; uint32_t* ptr = data; if (flashIsPuya()) { if (flash_write_puya_buf == 0) { - // Memory could not be allocated. - return false; - } - rc = spi_flash_read(offset, flash_write_puya_buf, size); - if (rc != 0) { - ets_isr_unmask(FLASH_INT_MASK); - return false; + flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); + // No need to ever free this, since the flash chip will never change at runtime. + if (flash_write_puya_buf == 0) { + // Memory could not be allocated. + return false; + } } - for (size_t i = 0; i < size / 4; ++i) { - flash_write_puya_buf[i] &= data[i]; + size_t bytesLeft = size; + uint32_t pos = offset; + while (bytesLeft > 0 && rc == 0) { + size_t bytes_now = bytesLeft; + if (bytes_now > PUYA_BUFFER_SIZE) { + bytes_now = PUYA_BUFFER_SIZE; + bytesLeft -= PUYA_BUFFER_SIZE; + } else { + bytesLeft = 0; + } + rc = spi_flash_read(pos, flash_write_puya_buf, bytes_now); + if (rc != 0) { + ets_isr_unmask(FLASH_INT_MASK); + return false; + } + for (size_t i = 0; i < bytes_now / 4; ++i) { + flash_write_puya_buf[i] &= *ptr; + ++ptr; + } + rc = spi_flash_write(pos, flash_write_puya_buf, bytes_now); + pos += bytes_now; } - ptr = flash_write_puya_buf; + } else { + rc = spi_flash_write(offset, ptr, size); } - rc = spi_flash_write(offset, ptr, size); ets_isr_unmask(FLASH_INT_MASK); return rc == 0; } diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index d4d11fe203..aa86119b44 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -24,6 +24,12 @@ #include #define PUYASUPPORT +#ifndef PUYA_BUFFER_SIZE + // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE + // 512 bytes is a reasonable trade-off between memory use and write cycles. + // Always use a multiple of flash page size (256 bytes) + #define PUYA_BUFFER_SIZE 512 +#endif /** * AVR macros for WDT managment From 620cd385be6938ee144fbc5fdfcaf183086974bf Mon Sep 17 00:00:00 2001 From: Gijs Noorlander Date: Sat, 15 Dec 2018 17:21:43 +0100 Subject: [PATCH 05/10] [PUYA] Lower PUYA flash buffer to 1 page (256 B) As discussed here: https://github.com/esp8266/Arduino/issues/5493#issuecomment-447543279 --- cores/esp8266/Esp.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index aa86119b44..88823c05fa 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -25,10 +25,9 @@ #define PUYASUPPORT #ifndef PUYA_BUFFER_SIZE - // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE - // 512 bytes is a reasonable trade-off between memory use and write cycles. + // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE (= 4k) // Always use a multiple of flash page size (256 bytes) - #define PUYA_BUFFER_SIZE 512 + #define PUYA_BUFFER_SIZE 256 #endif /** From 765fd725af05d230cc1b73c3ff9b61f62d47e6ac Mon Sep 17 00:00:00 2001 From: TD-er Date: Sun, 16 Dec 2018 10:37:54 +0000 Subject: [PATCH 06/10] [PUYA] Fix indents naming and return conditions --- cores/esp8266/Esp.cpp | 95 ++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 0b8d463ebd..ac19f0d806 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -267,9 +267,9 @@ uint8_t EspClass::getCpuFreqMHz(void) uint32_t EspClass::getFlashChipId(void) { static uint32_t flash_chip_id = 0; - if (flash_chip_id == 0) { - flash_chip_id = spi_flash_get_id(); - } + if (flash_chip_id == 0) { + flash_chip_id = spi_flash_get_id(); + } return flash_chip_id; } @@ -577,54 +577,55 @@ bool EspClass::flashEraseSector(uint32_t sector) { static uint32_t *flash_write_puya_buf = 0; bool EspClass::flashIsPuya(){ - if (flash_write_puya_buf != 0) { - // Already detected PUYA and allocated buffer. - return true; - } - return ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA + if (flash_write_puya_buf != 0) { + // Already detected PUYA and allocated buffer. + return true; + } + return ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA } bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { - ets_isr_mask(FLASH_INT_MASK); - int rc = 0; - uint32_t* ptr = data; - - if (flashIsPuya()) { - if (flash_write_puya_buf == 0) { + ets_isr_mask(FLASH_INT_MASK); + int rc = 0; + uint32_t* ptr = data; + + if (flashIsPuya()) { + if (flash_write_puya_buf == 0) { flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); - // No need to ever free this, since the flash chip will never change at runtime. - if (flash_write_puya_buf == 0) { - // Memory could not be allocated. - return false; - } - } - size_t bytesLeft = size; - uint32_t pos = offset; - while (bytesLeft > 0 && rc == 0) { - size_t bytes_now = bytesLeft; - if (bytes_now > PUYA_BUFFER_SIZE) { - bytes_now = PUYA_BUFFER_SIZE; - bytesLeft -= PUYA_BUFFER_SIZE; - } else { - bytesLeft = 0; - } - rc = spi_flash_read(pos, flash_write_puya_buf, bytes_now); - if (rc != 0) { - ets_isr_unmask(FLASH_INT_MASK); - return false; - } - for (size_t i = 0; i < bytes_now / 4; ++i) { - flash_write_puya_buf[i] &= *ptr; - ++ptr; - } - rc = spi_flash_write(pos, flash_write_puya_buf, bytes_now); - pos += bytes_now; - } - } else { - rc = spi_flash_write(offset, ptr, size); - } - ets_isr_unmask(FLASH_INT_MASK); - return rc == 0; + // No need to ever free this, since the flash chip will never change at runtime. + if (flash_write_puya_buf == 0) { + // Memory could not be allocated. + ets_isr_unmask(FLASH_INT_MASK); + return false; + } + } + size_t bytesLeft = size; + uint32_t pos = offset; + while (bytesLeft > 0 && rc == 0) { + size_t bytesNow = bytesLeft; + if (bytesNow > PUYA_BUFFER_SIZE) { + bytesNow = PUYA_BUFFER_SIZE; + bytesLeft -= PUYA_BUFFER_SIZE; + } else { + bytesLeft = 0; + } + rc = spi_flash_read(pos, flash_write_puya_buf, bytesNow); + if (rc != 0) { + ets_isr_unmask(FLASH_INT_MASK); + return false; + } + for (size_t i = 0; i < bytesNow / 4; ++i) { + flash_write_puya_buf[i] &= *ptr; + ++ptr; + } + rc = spi_flash_write(pos, flash_write_puya_buf, bytesNow); + pos += bytesNow; + } + } else { + rc = spi_flash_write(offset, ptr, size); + } + ets_isr_unmask(FLASH_INT_MASK); + return rc == 0; } bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) { From 154970049d2761124077b02e457c8535c6734927 Mon Sep 17 00:00:00 2001 From: TD-er Date: Sun, 16 Dec 2018 11:26:06 +0000 Subject: [PATCH 07/10] [PUYA] Move Puya write code to spi_flash_write_puya --- cores/esp8266/Esp.cpp | 78 +++++++++++++++++++++---------------------- cores/esp8266/Esp.h | 3 ++ 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index ac19f0d806..7109966915 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -573,56 +573,56 @@ bool EspClass::flashEraseSector(uint32_t sector) { return rc == 0; } -// PUYA flash chips need to read existing data, update in memory and write modified data again. -static uint32_t *flash_write_puya_buf = 0; - bool EspClass::flashIsPuya(){ - if (flash_write_puya_buf != 0) { - // Already detected PUYA and allocated buffer. - return true; - } return ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA } -bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { - ets_isr_mask(FLASH_INT_MASK); +int EspClass::spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) { + // PUYA flash chips need to read existing data, update in memory and write modified data again. + static uint32_t *flash_write_puya_buf = 0; int rc = 0; uint32_t* ptr = data; - if (flashIsPuya()) { + if (flash_write_puya_buf == 0) { + flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); + // No need to ever free this, since the flash chip will never change at runtime. if (flash_write_puya_buf == 0) { - flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); - // No need to ever free this, since the flash chip will never change at runtime. - if (flash_write_puya_buf == 0) { - // Memory could not be allocated. - ets_isr_unmask(FLASH_INT_MASK); - return false; - } + // Memory could not be allocated. + return 1; // SPI_FLASH_RESULT_ERR + } + } + size_t bytesLeft = size; + uint32_t pos = offset; + while (bytesLeft > 0 && rc == 0) { + size_t bytesNow = bytesLeft; + if (bytesNow > PUYA_BUFFER_SIZE) { + bytesNow = PUYA_BUFFER_SIZE; + bytesLeft -= PUYA_BUFFER_SIZE; + } else { + bytesLeft = 0; + } + rc = spi_flash_read(pos, flash_write_puya_buf, bytesNow); + if (rc != 0) { + return rc; } - size_t bytesLeft = size; - uint32_t pos = offset; - while (bytesLeft > 0 && rc == 0) { - size_t bytesNow = bytesLeft; - if (bytesNow > PUYA_BUFFER_SIZE) { - bytesNow = PUYA_BUFFER_SIZE; - bytesLeft -= PUYA_BUFFER_SIZE; - } else { - bytesLeft = 0; - } - rc = spi_flash_read(pos, flash_write_puya_buf, bytesNow); - if (rc != 0) { - ets_isr_unmask(FLASH_INT_MASK); - return false; - } - for (size_t i = 0; i < bytesNow / 4; ++i) { - flash_write_puya_buf[i] &= *ptr; - ++ptr; - } - rc = spi_flash_write(pos, flash_write_puya_buf, bytesNow); - pos += bytesNow; + for (size_t i = 0; i < bytesNow / 4; ++i) { + flash_write_puya_buf[i] &= *ptr; + ++ptr; } + rc = spi_flash_write(pos, flash_write_puya_buf, bytesNow); + pos += bytesNow; + } + return rc; +} + +bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { + ets_isr_mask(FLASH_INT_MASK); + int rc = 0; + + if (flashIsPuya()) { + rc = spi_flash_write_puya(offset, data, size); } else { - rc = spi_flash_write(offset, ptr, size); + rc = spi_flash_write(offset, data, size); } ets_isr_unmask(FLASH_INT_MASK); return rc == 0; diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 88823c05fa..bf178406e3 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -161,6 +161,9 @@ class EspClass { bool eraseConfig(); inline uint32_t getCycleCount(); + + private: + int spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size); }; uint32_t EspClass::getCycleCount() From a32f15772313d8b67970f89f6333a4977a9d0771 Mon Sep 17 00:00:00 2001 From: TD-er Date: Sun, 16 Dec 2018 12:06:02 +0000 Subject: [PATCH 08/10] [PUYA] Make spi_flash_write_puya static and define PUYA_SUPPORT --- cores/esp8266/Esp.cpp | 22 ++++++++++++++-------- cores/esp8266/Esp.h | 10 +++++----- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 7109966915..bffda03d34 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -273,6 +273,11 @@ uint32_t EspClass::getFlashChipId(void) return flash_chip_id; } +uint8_t EspClass::getFlashChipVendorId(void) +{ + return (getFlashChipId() & 0x000000ff); +} + uint32_t EspClass::getFlashChipRealSize(void) { return (1 << ((spi_flash_get_id() >> 16) & 0xFF)); @@ -573,11 +578,8 @@ bool EspClass::flashEraseSector(uint32_t sector) { return rc == 0; } -bool EspClass::flashIsPuya(){ - return ((getFlashChipId() & 0x000000ff) == 0x85); // 0x146085 PUYA -} - -int EspClass::spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) { +#if PUYA_SUPPORT +static int spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) { // PUYA flash chips need to read existing data, update in memory and write modified data again. static uint32_t *flash_write_puya_buf = 0; int rc = 0; @@ -614,14 +616,18 @@ int EspClass::spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) } return rc; } +#endif bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { ets_isr_mask(FLASH_INT_MASK); int rc = 0; - - if (flashIsPuya()) { +#if PUYA_SUPPORT + if (getFlashChipVendorId() == 0x85) { // 0x146085 PUYA rc = spi_flash_write_puya(offset, data, size); - } else { + } + else +#endif + { rc = spi_flash_write(offset, data, size); } ets_isr_unmask(FLASH_INT_MASK); diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index bf178406e3..b4c61f80dd 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -23,7 +23,9 @@ #include -#define PUYASUPPORT +#ifndef PUYA_SUPPORT + #define PUYA_SUPPORT 1 +#endif #ifndef PUYA_BUFFER_SIZE // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE (= 4k) // Always use a multiple of flash page size (256 bytes) @@ -130,6 +132,8 @@ class EspClass { uint8_t getCpuFreqMHz(); uint32_t getFlashChipId(); + uint8_t getFlashChipVendorId(); + //gets the actual chip size based on the flash id uint32_t getFlashChipRealSize(); //gets the size of the flash as set by the compiler @@ -148,7 +152,6 @@ class EspClass { bool flashWrite(uint32_t offset, uint32_t *data, size_t size); bool flashRead(uint32_t offset, uint32_t *data, size_t size); - bool flashIsPuya(); uint32_t getSketchSize(); String getSketchMD5(); uint32_t getFreeSketchSpace(); @@ -161,9 +164,6 @@ class EspClass { bool eraseConfig(); inline uint32_t getCycleCount(); - - private: - int spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size); }; uint32_t EspClass::getCycleCount() From 618a19cceda402e635f7b74878c2503eb779635a Mon Sep 17 00:00:00 2001 From: TD-er Date: Mon, 17 Dec 2018 09:50:28 +0100 Subject: [PATCH 09/10] [PUYA] Add some SPI flash vendor IDs As requested by @igrr https://github.com/esp8266/Arduino/pull/5504#discussion_r242016184 --- cores/esp8266/Esp.cpp | 14 +++++++------- cores/esp8266/Esp.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index bffda03d34..bce8f0f919 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -132,18 +132,18 @@ uint64_t EspClass::deepSleepMax() } -/* +/* Layout of RTC Memory is as follows: Ref: Espressif doc 2C-ESP8266_Non_OS_SDK_API_Reference, section 3.3.23 (system_rtc_mem_write) |<------system data (256 bytes)------->|<-----------------user data (512 bytes)--------------->| -SDK function signature: +SDK function signature: bool system_rtc_mem_read ( - uint32 des_addr, - void * src_addr, + uint32 des_addr, + void * src_addr, uint32 save_size -) +) The system data section can't be used by the user, so: des_addr must be >=64 (i.e.: 256/4) and <192 (i.e.: 768/4) @@ -160,7 +160,7 @@ Same for write Note: If the Updater class is in play, e.g.: the application uses OTA, the eboot command will be stored into the first 128 bytes of user data, then it will be retrieved by eboot on boot. That means that user data present there will be lost. -Ref: +Ref: - discussion in PR #5330. - https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map#memmory-mapped-io-registers - Arduino/bootloaders/eboot/eboot_command.h RTC_MEM definition @@ -622,7 +622,7 @@ bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { ets_isr_mask(FLASH_INT_MASK); int rc = 0; #if PUYA_SUPPORT - if (getFlashChipVendorId() == 0x85) { // 0x146085 PUYA + if (getFlashChipVendorId() == SPI_FLASH_VENDOR_PUYA) { rc = spi_flash_write_puya(offset, data, size); } else diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index b4c61f80dd..0bdfc30e93 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -32,6 +32,39 @@ #define PUYA_BUFFER_SIZE 256 #endif +// Vendor IDs taken from Flashrom project +// https://review.coreboot.org/cgit/flashrom.git/tree/flashchips.h?h=1.0.x +#define SPI_FLASH_VENDOR_ALLIANCE 0x52 /* Alliance Semiconductor */ +#define SPI_FLASH_VENDOR_AMD 0x01 /* AMD */ +#define SPI_FLASH_VENDOR_AMIC 0x37 /* AMIC */ +#define SPI_FLASH_VENDOR_ATMEL 0x1F /* Atmel (now used by Adesto) */ +#define SPI_FLASH_VENDOR_BRIGHT 0xAD /* Bright Microelectronics */ +#define SPI_FLASH_VENDOR_CATALYST 0x31 /* Catalyst */ +#define SPI_FLASH_VENDOR_EON 0x1C /* EON Silicon Devices, missing 0x7F prefix */ +#define SPI_FLASH_VENDOR_ESMT 0x8C /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */ +#define SPI_FLASH_VENDOR_EXCEL 0x4A /* ESI, missing 0x7F prefix */ +#define SPI_FLASH_VENDOR_FIDELIX 0xF8 /* Fidelix */ +#define SPI_FLASH_VENDOR_FUJITSU 0x04 /* Fujitsu */ +#define SPI_FLASH_VENDOR_GIGADEVICE 0xC8 /* GigaDevice */ +#define SPI_FLASH_VENDOR_HYUNDAI 0xAD /* Hyundai */ +#define SPI_FLASH_VENDOR_INTEL 0x89 /* Intel */ +#define SPI_FLASH_VENDOR_ISSI 0xD5 /* ISSI Integrated Silicon Solutions, see also PMC. */ +#define SPI_FLASH_VENDOR_MACRONIX 0xC2 /* Macronix (MX) */ +#define SPI_FLASH_VENDOR_NANTRONICS 0xD5 /* Nantronics, missing prefix */ +#define SPI_FLASH_VENDOR_PMC 0x9D /* PMC, missing 0x7F prefix */ +#define SPI_FLASH_VENDOR_PUYA 0x85 /* Puya semiconductor (shanghai) co. ltd */ +#define SPI_FLASH_VENDOR_SANYO 0x62 /* Sanyo */ +#define SPI_FLASH_VENDOR_SHARP 0xB0 /* Sharp */ +#define SPI_FLASH_VENDOR_SPANSION 0x01 /* Spansion, same ID as AMD */ +#define SPI_FLASH_VENDOR_SST 0xBF /* SST */ +#define SPI_FLASH_VENDOR_ST 0x20 /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */ +#define SPI_FLASH_VENDOR_SYNCMOS_MVC 0x40 /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */ +#define SPI_FLASH_VENDOR_TENX 0x5E /* Tenx Technologies */ +#define SPI_FLASH_VENDOR_TI 0x97 /* Texas Instruments */ +#define SPI_FLASH_VENDOR_TI_OLD 0x01 /* TI chips from last century */ +#define SPI_FLASH_VENDOR_WINBOND 0xDA /* Winbond */ +#define SPI_FLASH_VENDOR_WINBOND_NEX 0xEF /* Winbond (ex Nexcom) serial flashes */ + /** * AVR macros for WDT managment */ From 1caac01c8dfdc6e614e8ecb6b50187c8bd1cac34 Mon Sep 17 00:00:00 2001 From: TD-er Date: Wed, 19 Dec 2018 00:47:13 +0100 Subject: [PATCH 10/10] [PUYA] All suggested changes. See: https://github.com/esp8266/Arduino/pull/5504#pullrequestreview-186145820 --- cores/esp8266/Esp.cpp | 9 ++++-- cores/esp8266/Esp.h | 66 +++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index bce8f0f919..d95c94516e 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -580,15 +580,18 @@ bool EspClass::flashEraseSector(uint32_t sector) { #if PUYA_SUPPORT static int spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) { + if (data == nullptr) { + return 1; // SPI_FLASH_RESULT_ERR + } // PUYA flash chips need to read existing data, update in memory and write modified data again. - static uint32_t *flash_write_puya_buf = 0; + static uint32_t *flash_write_puya_buf = nullptr; int rc = 0; uint32_t* ptr = data; - if (flash_write_puya_buf == 0) { + if (flash_write_puya_buf == nullptr) { flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE); // No need to ever free this, since the flash chip will never change at runtime. - if (flash_write_puya_buf == 0) { + if (flash_write_puya_buf == nullptr) { // Memory could not be allocated. return 1; // SPI_FLASH_RESULT_ERR } diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 0bdfc30e93..21dff08523 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -24,7 +24,7 @@ #include #ifndef PUYA_SUPPORT - #define PUYA_SUPPORT 1 + #define PUYA_SUPPORT 0 #endif #ifndef PUYA_BUFFER_SIZE // Good alternative for buffer size is: SPI_FLASH_SEC_SIZE (= 4k) @@ -34,36 +34,40 @@ // Vendor IDs taken from Flashrom project // https://review.coreboot.org/cgit/flashrom.git/tree/flashchips.h?h=1.0.x -#define SPI_FLASH_VENDOR_ALLIANCE 0x52 /* Alliance Semiconductor */ -#define SPI_FLASH_VENDOR_AMD 0x01 /* AMD */ -#define SPI_FLASH_VENDOR_AMIC 0x37 /* AMIC */ -#define SPI_FLASH_VENDOR_ATMEL 0x1F /* Atmel (now used by Adesto) */ -#define SPI_FLASH_VENDOR_BRIGHT 0xAD /* Bright Microelectronics */ -#define SPI_FLASH_VENDOR_CATALYST 0x31 /* Catalyst */ -#define SPI_FLASH_VENDOR_EON 0x1C /* EON Silicon Devices, missing 0x7F prefix */ -#define SPI_FLASH_VENDOR_ESMT 0x8C /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */ -#define SPI_FLASH_VENDOR_EXCEL 0x4A /* ESI, missing 0x7F prefix */ -#define SPI_FLASH_VENDOR_FIDELIX 0xF8 /* Fidelix */ -#define SPI_FLASH_VENDOR_FUJITSU 0x04 /* Fujitsu */ -#define SPI_FLASH_VENDOR_GIGADEVICE 0xC8 /* GigaDevice */ -#define SPI_FLASH_VENDOR_HYUNDAI 0xAD /* Hyundai */ -#define SPI_FLASH_VENDOR_INTEL 0x89 /* Intel */ -#define SPI_FLASH_VENDOR_ISSI 0xD5 /* ISSI Integrated Silicon Solutions, see also PMC. */ -#define SPI_FLASH_VENDOR_MACRONIX 0xC2 /* Macronix (MX) */ -#define SPI_FLASH_VENDOR_NANTRONICS 0xD5 /* Nantronics, missing prefix */ -#define SPI_FLASH_VENDOR_PMC 0x9D /* PMC, missing 0x7F prefix */ -#define SPI_FLASH_VENDOR_PUYA 0x85 /* Puya semiconductor (shanghai) co. ltd */ -#define SPI_FLASH_VENDOR_SANYO 0x62 /* Sanyo */ -#define SPI_FLASH_VENDOR_SHARP 0xB0 /* Sharp */ -#define SPI_FLASH_VENDOR_SPANSION 0x01 /* Spansion, same ID as AMD */ -#define SPI_FLASH_VENDOR_SST 0xBF /* SST */ -#define SPI_FLASH_VENDOR_ST 0x20 /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */ -#define SPI_FLASH_VENDOR_SYNCMOS_MVC 0x40 /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */ -#define SPI_FLASH_VENDOR_TENX 0x5E /* Tenx Technologies */ -#define SPI_FLASH_VENDOR_TI 0x97 /* Texas Instruments */ -#define SPI_FLASH_VENDOR_TI_OLD 0x01 /* TI chips from last century */ -#define SPI_FLASH_VENDOR_WINBOND 0xDA /* Winbond */ -#define SPI_FLASH_VENDOR_WINBOND_NEX 0xEF /* Winbond (ex Nexcom) serial flashes */ +typedef enum { + SPI_FLASH_VENDOR_ALLIANCE = 0x52, /* Alliance Semiconductor */ + SPI_FLASH_VENDOR_AMD = 0x01, /* AMD */ + SPI_FLASH_VENDOR_AMIC = 0x37, /* AMIC */ + SPI_FLASH_VENDOR_ATMEL = 0x1F, /* Atmel (now used by Adesto) */ + SPI_FLASH_VENDOR_BRIGHT = 0xAD, /* Bright Microelectronics */ + SPI_FLASH_VENDOR_CATALYST = 0x31, /* Catalyst */ + SPI_FLASH_VENDOR_EON = 0x1C, /* EON Silicon Devices, missing 0x7F prefix */ + SPI_FLASH_VENDOR_ESMT = 0x8C, /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */ + SPI_FLASH_VENDOR_EXCEL = 0x4A, /* ESI, missing 0x7F prefix */ + SPI_FLASH_VENDOR_FIDELIX = 0xF8, /* Fidelix */ + SPI_FLASH_VENDOR_FUJITSU = 0x04, /* Fujitsu */ + SPI_FLASH_VENDOR_GIGADEVICE = 0xC8, /* GigaDevice */ + SPI_FLASH_VENDOR_HYUNDAI = 0xAD, /* Hyundai */ + SPI_FLASH_VENDOR_INTEL = 0x89, /* Intel */ + SPI_FLASH_VENDOR_ISSI = 0xD5, /* ISSI Integrated Silicon Solutions, see also PMC. */ + SPI_FLASH_VENDOR_MACRONIX = 0xC2, /* Macronix (MX) */ + SPI_FLASH_VENDOR_NANTRONICS = 0xD5, /* Nantronics, missing prefix */ + SPI_FLASH_VENDOR_PMC = 0x9D, /* PMC, missing 0x7F prefix */ + SPI_FLASH_VENDOR_PUYA = 0x85, /* Puya semiconductor (shanghai) co. ltd */ + SPI_FLASH_VENDOR_SANYO = 0x62, /* Sanyo */ + SPI_FLASH_VENDOR_SHARP = 0xB0, /* Sharp */ + SPI_FLASH_VENDOR_SPANSION = 0x01, /* Spansion, same ID as AMD */ + SPI_FLASH_VENDOR_SST = 0xBF, /* SST */ + SPI_FLASH_VENDOR_ST = 0x20, /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */ + SPI_FLASH_VENDOR_SYNCMOS_MVC = 0x40, /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */ + SPI_FLASH_VENDOR_TENX = 0x5E, /* Tenx Technologies */ + SPI_FLASH_VENDOR_TI = 0x97, /* Texas Instruments */ + SPI_FLASH_VENDOR_TI_OLD = 0x01, /* TI chips from last century */ + SPI_FLASH_VENDOR_WINBOND = 0xDA, /* Winbond */ + SPI_FLASH_VENDOR_WINBOND_NEX = 0xEF, /* Winbond (ex Nexcom) serial flashes */ + + SPI_FLASH_VENDOR_UNKNOWN = 0xFF +} SPI_FLASH_VENDOR_t; /** * AVR macros for WDT managment