diff --git a/src/spiFlash.cpp b/src/spiFlash.cpp index 6773c98..d9e734f 100644 --- a/src/spiFlash.cpp +++ b/src/spiFlash.cpp @@ -7,12 +7,13 @@ #include #include #include +#include #include -#include "ftdipp_mpsse.hpp" #include "progressBar.hpp" #include "display.hpp" #include "spiFlash.hpp" +#include "spiFlashdb.hpp" #include "spiInterface.hpp" /* read/write status register : 0B addr + 0 dummy */ @@ -55,8 +56,10 @@ /* Global Block Protection unlock */ #define FLASH_ULBPR 0x98 -SPIFlash::SPIFlash(SPIInterface *spi, int8_t verbose):_spi(spi), _verbose(verbose) +SPIFlash::SPIFlash(SPIInterface *spi, int8_t verbose):_spi(spi), + _verbose(verbose), _jedec_id(0), _flash_model(NULL) { + read_id(); } int SPIFlash::bulk_erase() @@ -281,30 +284,39 @@ void SPIFlash::read_id() if (_verbose > 0) printf("read %x\n", _jedec_id); + auto t = flash_list.find(_jedec_id >> 8); + if (t != flash_list.end()) { + _flash_model = &(*t).second; + char content[256]; + snprintf(content, 256, "Detected: %s %s %u sectors size: %uMb", + _flash_model->manufacturer.c_str(), _flash_model->model.c_str(), + _flash_model->nr_sector, _flash_model->nr_sector * 0x80000 / 1048576); + printInfo(content); + } else { + /* read extented */ + if ((_jedec_id & 0xff) != 0) { + has_edid = true; + len += (_jedec_id & 0x0ff); + _spi->spi_put(0x9F, NULL, rx, len); + } - /* read extented */ - if ((_jedec_id & 0xff) != 0) { - has_edid = true; - len += (_jedec_id & 0x0ff); - _spi->spi_put(0x9F, NULL, rx, len); - } + /* must be 0x20BA1810 ... */ - /* must be 0x20BA1810 ... */ - - printf("Detail: \n"); - printf("Jedec ID : %02x\n", rx[0]); - printf("memory type : %02x\n", rx[1]); - printf("memory capacity : %02x\n", rx[2]); - if (has_edid) { - printf("EDID + CFD length : %02x\n", rx[3]); - printf("EDID : %02x%02x\n", rx[5], rx[4]); - printf("CFD : "); - if (_verbose > 0) { - for (int i = 6; i < len; i++) - printf("%02x ", rx[i]); - printf("\n"); - } else { - printf("\n"); + printf("Detail: \n"); + printf("Jedec ID : %02x\n", rx[0]); + printf("memory type : %02x\n", rx[1]); + printf("memory capacity : %02x\n", rx[2]); + if (has_edid) { + printf("EDID + CFD length : %02x\n", rx[3]); + printf("EDID : %02x%02x\n", rx[5], rx[4]); + printf("CFD : "); + if (_verbose > 0) { + for (int i = 6; i < len; i++) + printf("%02x ", rx[i]); + printf("\n"); + } else { + printf("\n"); + } } } } @@ -391,6 +403,45 @@ int SPIFlash::disable_protection() return 0; } +/* convert bp area (status register) to len in byte */ +uint32_t SPIFlash::bp_to_len(uint8_t bp) +{ + /* 0 -> no sectors protected */ + if (bp == 0) + return 0; + + /* reconstruct code based on each BPx bit */ + uint8_t tmp = 0; + for (int i = 0; i < 4; i++) + if ((bp & _flash_model->bp_offset[i])) + tmp |= (1 << i); + /* bp code is 2^(bp-1) sectors */ + uint16_t nr_sectors = (1 << (tmp-1)); + + return nr_sectors * 0x10000; +} + +/* convert len (in byte) to bp (sector protection) */ +uint8_t SPIFlash::len_to_bp(uint32_t len) +{ + /* 0 -> no sector to protect */ + if (len == 0) + return 0; + + /* round and divide by sector size */ + len = ((len + 0xffff) & ~0xffff) / 0x10000; + + /* convert size to basic BP code */ + uint8_t bp = 1 + static_cast(ceil(log2(len))); + /* reconstruct code based on each BPx bit */ + uint8_t tmp = 0; + for (int i = 0; i < 4; i++) + if (bp >> i) + tmp |= _flash_model->bp_offset[i]; + + return tmp; +} + /* microchip SST26VF032B has a dedicated register * to read sectors (un)lock status and another one to unlock * sectors diff --git a/src/spiFlash.hpp b/src/spiFlash.hpp index 7bd80a0..c059b5a 100644 --- a/src/spiFlash.hpp +++ b/src/spiFlash.hpp @@ -3,10 +3,13 @@ * Copyright (C) 2019 Gwenhael Goavec-Merou */ -#ifndef SPIFLASH_HPP -#define SPIFLASH_HPP +#ifndef SRC_SPIFLASH_HPP_ +#define SRC_SPIFLASH_HPP_ + +#include #include "spiInterface.hpp" +#include "spiFlashdb.hpp" class SPIFlash { public: @@ -18,6 +21,10 @@ class SPIFlash { /* protection */ int write_enable(); int write_disable(); + /*! + * \brief disable protection for all sectors + * \return -1 if write enable or disabling failed + */ int disable_protection(); /*! * \brief unlock all sectors: specific to @@ -27,7 +34,13 @@ class SPIFlash { bool global_unlock(); /* erase */ int bulk_erase(); + /*! + * \brief erase one sector (64Kb) + */ int sector_erase(int addr); + /*! + * \brief erase n sectors starting at base_addr + */ int sectors_erase(int base_addr, int len); /* write */ int write_page(int addr, uint8_t *data, int len); @@ -62,10 +75,25 @@ class SPIFlash { virtual void read_id(); uint16_t readNonVolatileCfgReg(); uint16_t readVolatileCfgReg(); + protected: + /*! + * \brief convert bit protect to len in byte + * \param[in] bp: byte protection + * \return protect area in byte + */ + uint32_t bp_to_len(uint8_t bp); + /*! + * \brief convert len (in byte) to corresponding bit protect + * \param[in] len: len in byte + * \return bp code (based on chip bp[x] position + */ + uint8_t len_to_bp(uint32_t len); + SPIInterface *_spi; int8_t _verbose; uint32_t _jedec_id; /**< CHIP ID */ + flash_t *_flash_model; /**< detect flash model */ }; -#endif +#endif // SRC_SPIFLASH_HPP_