From 00c1a6561267dc148d674d1cd9a1b4870d0d7377 Mon Sep 17 00:00:00 2001 From: Martin Sloup Date: Thu, 23 Feb 2017 01:23:27 +0100 Subject: [PATCH] Improvements in EspClass (#222) * Improvements in EspClass - fixed not working functions for flash chip size, speed and mode - added function to retrieve chip revision from eFuse - flashRead / flashWrite supports encrypted flash * Rename getCpuRevision function to getChipRevision * Revert: flashRead / flashWrite supports encrypted flash Reading and writing to encrypted flash has to be aligned to 16-bytes. Also NAND way of writing (i.e. flipping 1s to 0s) will not work with spi_flash_write_encrypted. Note: spi_flash_read_encrypted will always try to decrypt data, even if it wasn't encrypted in the first place. --- cores/esp32/Esp.cpp | 70 ++++++++++++++++++++++++--------------------- cores/esp32/Esp.h | 3 ++ 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp index 2d12ee5d..e80a5e92 100644 --- a/cores/esp32/Esp.cpp +++ b/cores/esp32/Esp.cpp @@ -23,9 +23,22 @@ #include "esp_deep_sleep.h" #include "esp_spi_flash.h" #include +#include +#include -//#define DEBUG_SERIAL Serial +/* Main header of binary image */ +typedef struct { + uint8_t magic; + uint8_t segment_count; + uint8_t spi_mode; /* flash read mode (esp_image_spi_mode_t as uint8_t) */ + uint8_t spi_speed: 4; /* flash frequency (esp_image_spi_freq_t as uint8_t) */ + uint8_t spi_size: 4; /* flash chip size (esp_image_flash_size_t as uint8_t) */ + uint32_t entry_addr; + uint8_t encrypt_flag; /* encrypt flag */ + uint8_t extra_header[15]; /* ESP32 additional header, unused by second bootloader */ +} esp_image_header_t; +#define ESP_IMAGE_HEADER_MAGIC 0xE9 /** * User-defined Literals @@ -104,6 +117,11 @@ uint32_t EspClass::getFreeHeap(void) return esp_get_free_heap_size(); } +uint8_t EspClass::getChipRevision(void) +{ + return (REG_READ(EFUSE_BLK0_RDATA3_REG) >> EFUSE_RD_CHIP_VER_RESERVE_S) && EFUSE_RD_CHIP_VER_RESERVE_V; +} + const char * EspClass::getSdkVersion(void) { return esp_get_idf_version(); @@ -111,57 +129,44 @@ const char * EspClass::getSdkVersion(void) uint32_t EspClass::getFlashChipSize(void) { - uint32_t data; - uint8_t * bytes = (uint8_t *) &data; - // read first 4 byte (magic byte + flash config) - if(flashRead(0x0000, &data, 4) == ESP_OK) { - return magicFlashChipSize((bytes[3] & 0xf0) >> 4); + esp_image_header_t fhdr; + if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) { + return 0; } - return 0; + return magicFlashChipSize(fhdr.spi_size); } uint32_t EspClass::getFlashChipSpeed(void) { - uint32_t data; - uint8_t * bytes = (uint8_t *) &data; - // read first 4 byte (magic byte + flash config) - if(flashRead(0x0000, &data, 4) == ESP_OK) { - return magicFlashChipSpeed(bytes[3] & 0x0F); + esp_image_header_t fhdr; + if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) { + return 0; } - return 0; + return magicFlashChipSpeed(fhdr.spi_speed); } FlashMode_t EspClass::getFlashChipMode(void) { - FlashMode_t mode = FM_UNKNOWN; - uint32_t data; - uint8_t * bytes = (uint8_t *) &data; - // read first 4 byte (magic byte + flash config) - if(flashRead(0x0000, &data, 4) == ESP_OK) { - mode = magicFlashChipMode(bytes[2]); + esp_image_header_t fhdr; + if(flashRead(0x1000, (uint32_t*)&fhdr, sizeof(esp_image_header_t)) && fhdr.magic != ESP_IMAGE_HEADER_MAGIC) { + return FM_UNKNOWN; } - return mode; + return magicFlashChipMode(fhdr.spi_mode); } uint32_t EspClass::magicFlashChipSize(uint8_t byte) { switch(byte & 0x0F) { - case 0x0: // 4 Mbit (512KB) - return (512_kB); - case 0x1: // 2 MBit (256KB) - return (256_kB); - case 0x2: // 8 MBit (1MB) + case 0x0: // 8 MBit (1MB) return (1_MB); - case 0x3: // 16 MBit (2MB) + case 0x1: // 16 MBit (2MB) return (2_MB); - case 0x4: // 32 MBit (4MB) + case 0x2: // 32 MBit (4MB) return (4_MB); - case 0x5: // 64 MBit (8MB) + case 0x3: // 64 MBit (8MB) return (8_MB); - case 0x6: // 128 MBit (16MB) + case 0x4: // 128 MBit (16MB) return (16_MB); - case 0x7: // 256 MBit (32MB) - return (32_MB); default: // fail? return 0; } @@ -186,7 +191,7 @@ uint32_t EspClass::magicFlashChipSpeed(uint8_t byte) FlashMode_t EspClass::magicFlashChipMode(uint8_t byte) { FlashMode_t mode = (FlashMode_t) byte; - if(mode > FM_DOUT) { + if(mode > FM_SLOW_READ) { mode = FM_UNKNOWN; } return mode; @@ -197,6 +202,7 @@ bool EspClass::flashEraseSector(uint32_t sector) return spi_flash_erase_sector(sector) == ESP_OK; } +// Warning: These functions do not work with encrypted flash bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { return spi_flash_write(offset, (uint32_t*) data, size) == ESP_OK; diff --git a/cores/esp32/Esp.h b/cores/esp32/Esp.h index 334a4899..2af27de9 100644 --- a/cores/esp32/Esp.h +++ b/cores/esp32/Esp.h @@ -45,6 +45,8 @@ typedef enum { FM_QOUT = 0x01, FM_DIO = 0x02, FM_DOUT = 0x03, + FM_FAST_READ = 0x04, + FM_SLOW_READ = 0x05, FM_UNKNOWN = 0xff } FlashMode_t; @@ -55,6 +57,7 @@ public: ~EspClass() {} void restart(); uint32_t getFreeHeap(); + uint8_t getChipRevision(); uint8_t getCpuFreqMHz(){ return CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; } uint32_t getCycleCount(); const char * getSdkVersion();