diff --git a/src/efinix.cpp b/src/efinix.cpp index 2f5493b..2d92418 100644 --- a/src/efinix.cpp +++ b/src/efinix.cpp @@ -27,6 +27,7 @@ #include "efinixHexParser.hpp" #include "ftdispi.hpp" #include "device.hpp" +#include "progressBar.hpp" #include "rawParser.hpp" #include "spiFlash.hpp" @@ -94,23 +95,49 @@ void Efinix::program(unsigned int offset) return; } + unsigned char *data = bit->getData(); + int length = bit->getLength() / 8; + if (_verbose) bit->displayHeader(); _spi->gpio_clear(_rst_pin); SPIFlash flash(reinterpret_cast(_spi), _verbose); - flash.reset(); - flash.power_up(); + flash.reset(); + flash.power_up(); - printf("%02x\n", flash.read_status_reg()); - flash.read_id(); - flash.erase_and_prog(offset, bit->getData(), bit->getLength() / 8); + printf("%02x\n", flash.read_status_reg()); + flash.read_id(); + flash.erase_and_prog(offset, data, length); - if (_verify) - printWarn("writing verification not supported"); + /* verify write if required */ + if (_verify) { + printInfo("Verifying write"); + std::string verify_data; + verify_data.resize(length); + printInfo("Read flash ", false); + if (0 != flash.read(offset, (uint8_t*)&verify_data[0], length)) { + printError("FAIL"); + return; + } else { + printSuccess("DONE"); + } - _spi->gpio_set(_rst_pin); + ProgressBar progress("Check", length, 50, _quiet); + for (int i = 0; i < length; i++) { + if ((uint8_t)verify_data[i] != data[i]) { + progress.fail(); + printError("Verification failed at " + + std::to_string(offset + i)); + return; + } + progress.display(i); + } + progress.done(); + } + + _spi->gpio_set(_rst_pin); usleep(12000); printInfo("Wait for CDONE ", false); @@ -123,3 +150,56 @@ void Efinix::program(unsigned int offset) else printSuccess("DONE"); } + +bool Efinix::dumpFlash(const std::string &filename, + uint32_t base_addr, uint32_t len) +{ + uint32_t timeout = 1000; + _spi->gpio_clear(_rst_pin); + + std::string data; + data.resize(len); + + /* prepare SPI access */ + printInfo("Read Flash ", false); + try { + SPIFlash flash(reinterpret_cast(_spi), _verbose); + flash.reset(); + flash.power_up(); + flash.read_id(); + flash.read_status_reg(); + flash.read(base_addr, (uint8_t*)&data[0], len); + } catch (std::exception &e) { + printError("Fail"); + printError(std::string(e.what())); + return false; + } + + FILE *fd = fopen(filename.c_str(), "wb"); + if (!fd) { + printError("Fail"); + return false; + } + + fwrite(data.c_str(), sizeof(uint8_t), len, fd); + fclose(fd); + + printSuccess("Done"); + + /* prepare SPI access */ + + _spi->gpio_set(_rst_pin); + usleep(12000); + + printInfo("Wait for CDONE ", false); + do { + timeout--; + usleep(12000); + } while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0); + if (timeout == 0) + printError("FAIL"); + else + printSuccess("DONE"); + + return false; +} diff --git a/src/efinix.hpp b/src/efinix.hpp index 55262a4..b9cbedd 100644 --- a/src/efinix.hpp +++ b/src/efinix.hpp @@ -32,6 +32,8 @@ class Efinix: public Device { ~Efinix(); void program(unsigned int offset = 0) override; + bool dumpFlash(const std::string &filename, + uint32_t base_addr, uint32_t len); /* not supported in SPI Active mode */ int idCode() override {return 0;} void reset() override; diff --git a/src/main.cpp b/src/main.cpp index 017efdb..ac6c7bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -182,7 +182,15 @@ int main(int argc, char **argv) if (board->manufacturer == "efinix") { Efinix target(spi, args.bit_file, args.file_type, board->reset_pin, board->done_pin, args.verify, args.verbose); - target.program(args.offset); + if (args.prg_type == Device::RD_FLASH) { + if (args.file_size == 0) { + printError("Error: 0 size for dump"); + } else { + target.dumpFlash(args.bit_file, args.offset, args.file_size); + } + } else { + target.program(args.offset); + } } else if (board->manufacturer == "lattice") { Ice40 target(spi, args.bit_file, args.file_type, board->reset_pin, board->done_pin, args.verify, args.verbose);