Skip to content

Rewrite PUYA patch to be more universal and mem friendly. #5504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 69 additions & 8 deletions cores/esp8266/Esp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -266,7 +266,16 @@ 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();
}
return flash_chip_id;
}

uint8_t EspClass::getFlashChipVendorId(void)
{
return (getFlashChipId() & 0x000000ff);
}

uint32_t EspClass::getFlashChipRealSize(void)
Expand Down Expand Up @@ -569,9 +578,61 @@ bool EspClass::flashEraseSector(uint32_t sector) {
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) {
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);
return rc == 0;
}
Expand Down
48 changes: 48 additions & 0 deletions cores/esp8266/Esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,52 @@

#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
*/
Expand Down Expand Up @@ -123,6 +169,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
Expand Down