Skip to content

Commit 4c04c63

Browse files
TD-erdevyte
authored andcommitted
Rewrite PUYA patch to be more universal and mem friendly. (#5504)
* [PUYA] Applied ESPeasy puya_v3.patch Applied the patch to get the starting point as described in #5493 * [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 * [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. * [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. * [PUYA] Lower PUYA flash buffer to 1 page (256 B) As discussed here: #5493 (comment) * [PUYA] Fix indents naming and return conditions * [PUYA] Move Puya write code to spi_flash_write_puya * [PUYA] Make spi_flash_write_puya static and define PUYA_SUPPORT * [PUYA] Add some SPI flash vendor IDs As requested by @igrr #5504 (comment) * [PUYA] All suggested changes. See: #5504 (review)
1 parent d6c7430 commit 4c04c63

File tree

2 files changed

+117
-8
lines changed

2 files changed

+117
-8
lines changed

Diff for: cores/esp8266/Esp.cpp

+69-8
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,18 @@ uint64_t EspClass::deepSleepMax()
132132

133133
}
134134

135-
/*
135+
/*
136136
Layout of RTC Memory is as follows:
137137
Ref: Espressif doc 2C-ESP8266_Non_OS_SDK_API_Reference, section 3.3.23 (system_rtc_mem_write)
138138
139139
|<------system data (256 bytes)------->|<-----------------user data (512 bytes)--------------->|
140140
141-
SDK function signature:
141+
SDK function signature:
142142
bool system_rtc_mem_read (
143-
uint32 des_addr,
144-
void * src_addr,
143+
uint32 des_addr,
144+
void * src_addr,
145145
uint32 save_size
146-
)
146+
)
147147
148148
The system data section can't be used by the user, so:
149149
des_addr must be >=64 (i.e.: 256/4) and <192 (i.e.: 768/4)
@@ -160,7 +160,7 @@ Same for write
160160
Note: If the Updater class is in play, e.g.: the application uses OTA, the eboot
161161
command will be stored into the first 128 bytes of user data, then it will be
162162
retrieved by eboot on boot. That means that user data present there will be lost.
163-
Ref:
163+
Ref:
164164
- discussion in PR #5330.
165165
- https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map#memmory-mapped-io-registers
166166
- Arduino/bootloaders/eboot/eboot_command.h RTC_MEM definition
@@ -266,7 +266,16 @@ uint8_t EspClass::getCpuFreqMHz(void)
266266

267267
uint32_t EspClass::getFlashChipId(void)
268268
{
269-
return spi_flash_get_id();
269+
static uint32_t flash_chip_id = 0;
270+
if (flash_chip_id == 0) {
271+
flash_chip_id = spi_flash_get_id();
272+
}
273+
return flash_chip_id;
274+
}
275+
276+
uint8_t EspClass::getFlashChipVendorId(void)
277+
{
278+
return (getFlashChipId() & 0x000000ff);
270279
}
271280

272281
uint32_t EspClass::getFlashChipRealSize(void)
@@ -569,9 +578,61 @@ bool EspClass::flashEraseSector(uint32_t sector) {
569578
return rc == 0;
570579
}
571580

581+
#if PUYA_SUPPORT
582+
static int spi_flash_write_puya(uint32_t offset, uint32_t *data, size_t size) {
583+
if (data == nullptr) {
584+
return 1; // SPI_FLASH_RESULT_ERR
585+
}
586+
// PUYA flash chips need to read existing data, update in memory and write modified data again.
587+
static uint32_t *flash_write_puya_buf = nullptr;
588+
int rc = 0;
589+
uint32_t* ptr = data;
590+
591+
if (flash_write_puya_buf == nullptr) {
592+
flash_write_puya_buf = (uint32_t*) malloc(PUYA_BUFFER_SIZE);
593+
// No need to ever free this, since the flash chip will never change at runtime.
594+
if (flash_write_puya_buf == nullptr) {
595+
// Memory could not be allocated.
596+
return 1; // SPI_FLASH_RESULT_ERR
597+
}
598+
}
599+
size_t bytesLeft = size;
600+
uint32_t pos = offset;
601+
while (bytesLeft > 0 && rc == 0) {
602+
size_t bytesNow = bytesLeft;
603+
if (bytesNow > PUYA_BUFFER_SIZE) {
604+
bytesNow = PUYA_BUFFER_SIZE;
605+
bytesLeft -= PUYA_BUFFER_SIZE;
606+
} else {
607+
bytesLeft = 0;
608+
}
609+
rc = spi_flash_read(pos, flash_write_puya_buf, bytesNow);
610+
if (rc != 0) {
611+
return rc;
612+
}
613+
for (size_t i = 0; i < bytesNow / 4; ++i) {
614+
flash_write_puya_buf[i] &= *ptr;
615+
++ptr;
616+
}
617+
rc = spi_flash_write(pos, flash_write_puya_buf, bytesNow);
618+
pos += bytesNow;
619+
}
620+
return rc;
621+
}
622+
#endif
623+
572624
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) {
573625
ets_isr_mask(FLASH_INT_MASK);
574-
int rc = spi_flash_write(offset, (uint32_t*) data, size);
626+
int rc = 0;
627+
#if PUYA_SUPPORT
628+
if (getFlashChipVendorId() == SPI_FLASH_VENDOR_PUYA) {
629+
rc = spi_flash_write_puya(offset, data, size);
630+
}
631+
else
632+
#endif
633+
{
634+
rc = spi_flash_write(offset, data, size);
635+
}
575636
ets_isr_unmask(FLASH_INT_MASK);
576637
return rc == 0;
577638
}

Diff for: cores/esp8266/Esp.h

+48
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,52 @@
2323

2424
#include <Arduino.h>
2525

26+
#ifndef PUYA_SUPPORT
27+
#define PUYA_SUPPORT 0
28+
#endif
29+
#ifndef PUYA_BUFFER_SIZE
30+
// Good alternative for buffer size is: SPI_FLASH_SEC_SIZE (= 4k)
31+
// Always use a multiple of flash page size (256 bytes)
32+
#define PUYA_BUFFER_SIZE 256
33+
#endif
34+
35+
// Vendor IDs taken from Flashrom project
36+
// https://review.coreboot.org/cgit/flashrom.git/tree/flashchips.h?h=1.0.x
37+
typedef enum {
38+
SPI_FLASH_VENDOR_ALLIANCE = 0x52, /* Alliance Semiconductor */
39+
SPI_FLASH_VENDOR_AMD = 0x01, /* AMD */
40+
SPI_FLASH_VENDOR_AMIC = 0x37, /* AMIC */
41+
SPI_FLASH_VENDOR_ATMEL = 0x1F, /* Atmel (now used by Adesto) */
42+
SPI_FLASH_VENDOR_BRIGHT = 0xAD, /* Bright Microelectronics */
43+
SPI_FLASH_VENDOR_CATALYST = 0x31, /* Catalyst */
44+
SPI_FLASH_VENDOR_EON = 0x1C, /* EON Silicon Devices, missing 0x7F prefix */
45+
SPI_FLASH_VENDOR_ESMT = 0x8C, /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */
46+
SPI_FLASH_VENDOR_EXCEL = 0x4A, /* ESI, missing 0x7F prefix */
47+
SPI_FLASH_VENDOR_FIDELIX = 0xF8, /* Fidelix */
48+
SPI_FLASH_VENDOR_FUJITSU = 0x04, /* Fujitsu */
49+
SPI_FLASH_VENDOR_GIGADEVICE = 0xC8, /* GigaDevice */
50+
SPI_FLASH_VENDOR_HYUNDAI = 0xAD, /* Hyundai */
51+
SPI_FLASH_VENDOR_INTEL = 0x89, /* Intel */
52+
SPI_FLASH_VENDOR_ISSI = 0xD5, /* ISSI Integrated Silicon Solutions, see also PMC. */
53+
SPI_FLASH_VENDOR_MACRONIX = 0xC2, /* Macronix (MX) */
54+
SPI_FLASH_VENDOR_NANTRONICS = 0xD5, /* Nantronics, missing prefix */
55+
SPI_FLASH_VENDOR_PMC = 0x9D, /* PMC, missing 0x7F prefix */
56+
SPI_FLASH_VENDOR_PUYA = 0x85, /* Puya semiconductor (shanghai) co. ltd */
57+
SPI_FLASH_VENDOR_SANYO = 0x62, /* Sanyo */
58+
SPI_FLASH_VENDOR_SHARP = 0xB0, /* Sharp */
59+
SPI_FLASH_VENDOR_SPANSION = 0x01, /* Spansion, same ID as AMD */
60+
SPI_FLASH_VENDOR_SST = 0xBF, /* SST */
61+
SPI_FLASH_VENDOR_ST = 0x20, /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */
62+
SPI_FLASH_VENDOR_SYNCMOS_MVC = 0x40, /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */
63+
SPI_FLASH_VENDOR_TENX = 0x5E, /* Tenx Technologies */
64+
SPI_FLASH_VENDOR_TI = 0x97, /* Texas Instruments */
65+
SPI_FLASH_VENDOR_TI_OLD = 0x01, /* TI chips from last century */
66+
SPI_FLASH_VENDOR_WINBOND = 0xDA, /* Winbond */
67+
SPI_FLASH_VENDOR_WINBOND_NEX = 0xEF, /* Winbond (ex Nexcom) serial flashes */
68+
69+
SPI_FLASH_VENDOR_UNKNOWN = 0xFF
70+
} SPI_FLASH_VENDOR_t;
71+
2672
/**
2773
* AVR macros for WDT managment
2874
*/
@@ -123,6 +169,8 @@ class EspClass {
123169
uint8_t getCpuFreqMHz();
124170

125171
uint32_t getFlashChipId();
172+
uint8_t getFlashChipVendorId();
173+
126174
//gets the actual chip size based on the flash id
127175
uint32_t getFlashChipRealSize();
128176
//gets the size of the flash as set by the compiler

0 commit comments

Comments
 (0)