diff --git a/src/altera.hpp b/src/altera.hpp index ecdf84e..12af383 100644 --- a/src/altera.hpp +++ b/src/altera.hpp @@ -57,6 +57,12 @@ class Altera: public Device, SPIInterface { bool unprotect_flash() override { return SPIInterface::unprotect_flash(); } + /*! + * \brief bulk erase SPI flash + */ + bool bulk_erase_flash() override { + return SPIInterface::bulk_erase_flash(); + } int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint32_t len) override; diff --git a/src/anlogic.hpp b/src/anlogic.hpp index 3843ed0..970a3b4 100644 --- a/src/anlogic.hpp +++ b/src/anlogic.hpp @@ -40,6 +40,13 @@ class Anlogic: public Device, SPIInterface { return SPIInterface::unprotect_flash(); } + /*! + * \brief bulk erase SPI flash + */ + bool bulk_erase_flash() override { + return SPIInterface::bulk_erase_flash(); + } + /*! * \brief dump len byte from base_addr from SPI flash * \param[in] base_addr: start offset diff --git a/src/colognechip.hpp b/src/colognechip.hpp index 9b21fab..e4d081d 100644 --- a/src/colognechip.hpp +++ b/src/colognechip.hpp @@ -40,6 +40,8 @@ class CologneChip: public Device, SPIInterface { printError("protect flash not supported"); return false;} virtual bool unprotect_flash() override { printError("unprotect flash not supported"); return false;} + virtual bool bulk_erase_flash() override { + printError("bulk erase flash not supported"); return false;} void program(unsigned int offset, bool unprotect_flash) override; int idCode() override {return 0;} diff --git a/src/device.hpp b/src/device.hpp index c913402..d5b254e 100644 --- a/src/device.hpp +++ b/src/device.hpp @@ -48,6 +48,7 @@ class Device { printError("dump flash not supported"); return false;} virtual bool protect_flash(uint32_t len) = 0; virtual bool unprotect_flash() = 0; + virtual bool bulk_erase_flash() = 0; virtual int idCode() = 0; virtual void reset(); diff --git a/src/efinix.hpp b/src/efinix.hpp index fafe7cc..eae590e 100644 --- a/src/efinix.hpp +++ b/src/efinix.hpp @@ -32,6 +32,8 @@ class Efinix: public Device { printError("protect flash not supported"); return false;} virtual bool unprotect_flash() override { printError("unprotect flash not supported"); return false;} + virtual bool bulk_erase_flash() override { + printError("bulk erase flash not supported"); return false;} /* not supported in SPI Active mode */ int idCode() override {return 0;} void reset() override; diff --git a/src/gowin.hpp b/src/gowin.hpp index d1765ca..9c72664 100644 --- a/src/gowin.hpp +++ b/src/gowin.hpp @@ -34,6 +34,8 @@ class Gowin: public Device, SPIInterface { printError("protect flash not supported"); return false;} virtual bool unprotect_flash() override { printError("unprotect flash not supported"); return false;} + virtual bool bulk_erase_flash() override { + printError("bulk erase flash not supported"); return false;} int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint32_t len) override; int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override; diff --git a/src/ice40.cpp b/src/ice40.cpp index 1531b1a..9cda2a8 100644 --- a/src/ice40.cpp +++ b/src/ice40.cpp @@ -237,6 +237,26 @@ bool Ice40::unprotect_flash() return post_flash_access(); } +bool Ice40::bulk_erase_flash() +{ + /* SPI access */ + prepare_flash_access(); + /* acess */ + try { + SPIFlash flash(reinterpret_cast(_spi), false, _verbose); + /* bulk erase flash */ + if (flash.bulk_erase() == -1) + return false; + } catch (std::exception &e) { + printError("Fail"); + printError(std::string(e.what())); + return false; + } + + /* reload */ + return post_flash_access(); +} + bool Ice40::prepare_flash_access() { /* SPI access: shutdown ICE40 */ diff --git a/src/ice40.hpp b/src/ice40.hpp index 2663528..222791f 100644 --- a/src/ice40.hpp +++ b/src/ice40.hpp @@ -26,6 +26,7 @@ class Ice40: public Device, SPIInterface { bool dumpFlash(uint32_t base_addr, uint32_t len) override; bool protect_flash(uint32_t len) override; bool unprotect_flash() override; + bool bulk_erase_flash() override; /* not supported in SPI Active mode */ int idCode() override {return 0;} void reset() override; diff --git a/src/lattice.hpp b/src/lattice.hpp index 0a40f98..ef2693f 100644 --- a/src/lattice.hpp +++ b/src/lattice.hpp @@ -47,6 +47,12 @@ class Lattice: public Device, SPIInterface { bool unprotect_flash() override { return SPIInterface::unprotect_flash(); } + /*! + * \brief bulk erase SPI flash + */ + bool bulk_erase_flash() override { + return SPIInterface::bulk_erase_flash(); + } /* spi interface */ int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, diff --git a/src/main.cpp b/src/main.cpp index 4cacef9..db04aa6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,6 +74,7 @@ struct arguments { string ip_adr; uint32_t protect_flash; bool unprotect_flash; + bool bulk_erase_flash; string flash_sector; bool skip_load_bridge; bool skip_reset; @@ -104,7 +105,7 @@ int main(int argc, char **argv) false, false, "", "", "", -1, 0, false, -1, /* vid, pid, index bus_addr, device_addr */ 0, 0, -1, 0, 0, - "127.0.0.1", 0, false, "", false, false, + "127.0.0.1", 0, false, false, "", false, false, /* xvc server */ false, 3721, "-", "", false, // mcufw conmcu @@ -275,6 +276,9 @@ int main(int argc, char **argv) if (args.unprotect_flash && args.bit_file.empty()) if (!target->unprotect_flash()) spi_ret = EXIT_FAILURE; + if (args.bulk_erase_flash && args.bit_file.empty()) + if (!target->bulk_erase_flash()) + spi_ret = EXIT_FAILURE; if (args.protect_flash) if (!target->protect_flash(args.protect_flash)) spi_ret = EXIT_FAILURE; @@ -326,6 +330,9 @@ int main(int argc, char **argv) if (args.unprotect_flash && args.bit_file.empty()) if (!flash.disable_protection()) spi_ret = EXIT_FAILURE; + if (args.bulk_erase_flash && args.bit_file.empty()) + if (!flash.bulk_erase()) + spi_ret = EXIT_FAILURE; if (args.protect_flash) if (!flash.enable_protection(args.protect_flash)) spi_ret = EXIT_FAILURE; @@ -557,6 +564,11 @@ int main(int argc, char **argv) fpga->unprotect_flash(); } + /* bulk erase SPI flash */ + if (args.bulk_erase_flash && args.bit_file.empty()) { + fpga->bulk_erase_flash(); + } + /* protect SPI flash */ if (args.protect_flash != 0) { fpga->protect_flash(args.protect_flash); @@ -673,6 +685,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p cxxopts::value(args->detect)) ("dfu", "DFU mode", cxxopts::value(args->dfu)) ("dump-flash", "Dump flash mode") + ("bulk-erase", "Bulk erase flash", + cxxopts::value(args->bulk_erase_flash)) ("external-flash", "select ext flash for device with internal and external storage", cxxopts::value(args->external_flash)) @@ -873,6 +887,7 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p !args->detect && !args->protect_flash && !args->unprotect_flash && + !args->bulk_erase_flash && !args->xvc && !args->reset && !args->conmcu) { diff --git a/src/spiFlash.cpp b/src/spiFlash.cpp index e1e75b6..abcf0f8 100644 --- a/src/spiFlash.cpp +++ b/src/spiFlash.cpp @@ -79,7 +79,7 @@ SPIFlash::SPIFlash(SPIInterface *spi, bool unprotect, int8_t verbose): int SPIFlash::bulk_erase() { int ret, ret2 = 0; - uint32_t timeout=100000; + uint32_t timeout=1000000; uint8_t bp = get_bp(); if (bp != 0) { if (!_unprotect) { @@ -96,7 +96,7 @@ int SPIFlash::bulk_erase() return ret; ret2 = _spi->spi_put(FLASH_CE, NULL, NULL, 0); if (ret2 == 0) - ret2 = _spi->spi_wait(FLASH_RDSR, FLASH_RDSR_WIP, 0x00, timeout, true); + ret2 = _spi->spi_wait(FLASH_RDSR, FLASH_RDSR_WIP, 0x00, timeout); if (bp != 0) ret = enable_protection(bp); diff --git a/src/spiInterface.cpp b/src/spiInterface.cpp index 08469e7..7abe1b8 100644 --- a/src/spiInterface.cpp +++ b/src/spiInterface.cpp @@ -39,8 +39,8 @@ bool SPIInterface::protect_flash(uint32_t len) SPIFlash flash(this, false, _spif_verbose); /* configure flash protection */ - ret = flash.enable_protection(len) != 0; - if (ret != 0) + ret = (flash.enable_protection(len) == 0); + if (!ret) printError("Fail"); else printSuccess("Done"); @@ -72,7 +72,7 @@ bool SPIInterface::unprotect_flash() printInfo("unprotect_flash: ", false); ret = (flash.disable_protection() == 0); if (!ret) - printError("Fail " + std::to_string(ret)); + printError("Fail"); else printSuccess("Done"); } catch (std::exception &e) { @@ -85,6 +85,37 @@ bool SPIInterface::unprotect_flash() return post_flash_access() && ret; } +bool SPIInterface::bulk_erase_flash() +{ + bool ret = true; + printInfo("bulk_erase: ", false); + + /* move device to spi access */ + if (!prepare_flash_access()) { + printError("Fail"); + return false; + } + + /* spi flash access */ + try { + SPIFlash flash(this, false, _spif_verbose); + + /* bulk erase flash */ + ret = (flash.bulk_erase() == 0); + if (!ret) + printError("Fail"); + else + printSuccess("Done"); + } catch (std::exception &e) { + printError("Fail"); + printError(e.what()); + ret = false; + } + + /* reload bitstream */ + return post_flash_access() && ret; +} + bool SPIInterface::write(uint32_t offset, uint8_t *data, uint32_t len, bool unprotect_flash) { diff --git a/src/spiInterface.hpp b/src/spiInterface.hpp index 8d71b1c..bdaaf16 100644 --- a/src/spiInterface.hpp +++ b/src/spiInterface.hpp @@ -26,6 +26,7 @@ class SPIInterface { bool protect_flash(uint32_t len); bool unprotect_flash(); + bool bulk_erase_flash(); /*! * \brief write len byte into flash starting at offset, * optionnally verify after write and unprotect diff --git a/src/xilinx.hpp b/src/xilinx.hpp index e297268..7588e15 100644 --- a/src/xilinx.hpp +++ b/src/xilinx.hpp @@ -40,6 +40,12 @@ class Xilinx: public Device, SPIInterface { bool unprotect_flash() override { return SPIInterface::unprotect_flash(); } + /*! + * \brief erase SPI flash blocks + */ + bool bulk_erase_flash() override { + return SPIInterface::bulk_erase_flash(); + } int idCode() override; void reset() override;