1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

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 https://github.com/esp8266/Arduino/issues/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: https://github.com/esp8266/Arduino/issues/5493#issuecomment-447543279

* [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 https://github.com/esp8266/Arduino/pull/5504#discussion_r242016184

* [PUYA] All suggested changes.

See: https://github.com/esp8266/Arduino/pull/5504#pullrequestreview-186145820
This commit is contained in:
Gijs Noorlander 2018-12-19 04:59:25 +01:00 committed by Develo
parent d6c743027d
commit 4c04c63c2a
2 changed files with 117 additions and 8 deletions

View File

@ -132,18 +132,18 @@ uint64_t EspClass::deepSleepMax()
} }
/* /*
Layout of RTC Memory is as follows: 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) 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)--------------->| |<------system data (256 bytes)------->|<-----------------user data (512 bytes)--------------->|
SDK function signature: SDK function signature:
bool system_rtc_mem_read ( bool system_rtc_mem_read (
uint32 des_addr, uint32 des_addr,
void * src_addr, void * src_addr,
uint32 save_size uint32 save_size
) )
The system data section can't be used by the user, so: 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) 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 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 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. retrieved by eboot on boot. That means that user data present there will be lost.
Ref: Ref:
- discussion in PR #5330. - discussion in PR #5330.
- https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map#memmory-mapped-io-registers - https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map#memmory-mapped-io-registers
- Arduino/bootloaders/eboot/eboot_command.h RTC_MEM definition - Arduino/bootloaders/eboot/eboot_command.h RTC_MEM definition
@ -266,7 +266,16 @@ uint8_t EspClass::getCpuFreqMHz(void)
uint32_t EspClass::getFlashChipId(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();
}
return flash_chip_id;
}
uint8_t EspClass::getFlashChipVendorId(void)
{
return (getFlashChipId() & 0x000000ff);
} }
uint32_t EspClass::getFlashChipRealSize(void) uint32_t EspClass::getFlashChipRealSize(void)
@ -569,9 +578,61 @@ bool EspClass::flashEraseSector(uint32_t sector) {
return rc == 0; return rc == 0;
} }
#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 = nullptr;
int rc = 0;
uint32_t* ptr = data;
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 == nullptr) {
// 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;
}
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;
}
#endif
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) {
ets_isr_mask(FLASH_INT_MASK); ets_isr_mask(FLASH_INT_MASK);
int rc = spi_flash_write(offset, (uint32_t*) data, size); int rc = 0;
#if PUYA_SUPPORT
if (getFlashChipVendorId() == SPI_FLASH_VENDOR_PUYA) {
rc = spi_flash_write_puya(offset, data, size);
}
else
#endif
{
rc = spi_flash_write(offset, data, size);
}
ets_isr_unmask(FLASH_INT_MASK); ets_isr_unmask(FLASH_INT_MASK);
return rc == 0; return rc == 0;
} }

View File

@ -23,6 +23,52 @@
#include <Arduino.h> #include <Arduino.h>
#ifndef PUYA_SUPPORT
#define PUYA_SUPPORT 0
#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)
#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
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 * AVR macros for WDT managment
*/ */
@ -123,6 +169,8 @@ class EspClass {
uint8_t getCpuFreqMHz(); uint8_t getCpuFreqMHz();
uint32_t getFlashChipId(); uint32_t getFlashChipId();
uint8_t getFlashChipVendorId();
//gets the actual chip size based on the flash id //gets the actual chip size based on the flash id
uint32_t getFlashChipRealSize(); uint32_t getFlashChipRealSize();
//gets the size of the flash as set by the compiler //gets the size of the flash as set by the compiler