diff --git a/src/ice40.cpp b/src/ice40.cpp index 4f93412..dc3cb07 100644 --- a/src/ice40.cpp +++ b/src/ice40.cpp @@ -26,6 +26,7 @@ #include "display.hpp" #include "ftdispi.hpp" #include "device.hpp" +#include "progressBar.hpp" #include "rawParser.hpp" #include "spiFlash.hpp" @@ -78,6 +79,9 @@ void Ice40::program(unsigned int offset) return; } + uint8_t *data = bit.getData(); + int length = bit.getLength() / 8; + _spi->gpio_clear(_rst_pin); SPIFlash flash(reinterpret_cast(_spi), _quiet); @@ -86,10 +90,32 @@ void Ice40::program(unsigned int offset) printf("%02x\n", flash.read_status_reg()); flash.read_id(); - flash.erase_and_prog(offset, bit.getData(), bit.getLength() / 8); + flash.erase_and_prog(offset, data, length); - if (_verify) - printWarn("writing verification not supported"); + 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"); + } + + 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); @@ -104,3 +130,56 @@ void Ice40::program(unsigned int offset) else printSuccess("DONE"); } + +bool Ice40::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/ice40.hpp b/src/ice40.hpp index 8fdcaae..b02ee57 100644 --- a/src/ice40.hpp +++ b/src/ice40.hpp @@ -32,6 +32,8 @@ class Ice40: public Device { ~Ice40(); 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 ac6c7bc..a06de85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -194,7 +194,15 @@ int main(int argc, char **argv) } else if (board->manufacturer == "lattice") { Ice40 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 { RawParser *bit = NULL; if (board->reset_pin) {