xilinx,lattice,device: add verify write into flash

This commit is contained in:
Gwenhael Goavec-Merou 2021-06-24 18:06:48 +02:00
parent b150bbdd23
commit c471d25bb5
13 changed files with 91 additions and 23 deletions

View File

@ -211,6 +211,7 @@ openFPGALoader -- a program to flash FPGA
--spi SPI mode (only for FTDI in serial mode)
-v, --verbose Produce verbose output
-h, --help Give this help list
--verify Verify write operation (SPI Flash only)
-V, --Version Print program version
Mandatory or optional arguments to long options are also mandatory or optional

View File

@ -18,7 +18,7 @@
Altera::Altera(Jtag *jtag, const std::string &filename,
const std::string &file_type, int8_t verbose):
Device(jtag, filename, file_type, verbose), _svf(_jtag, _verbose)
Device(jtag, filename, file_type, false, verbose), _svf(_jtag, _verbose)
{
if (!_file_extension.empty()) {
if (_file_extension == "svf" || _file_extension == "rbf")

View File

@ -40,7 +40,7 @@
Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type, int8_t verbose):
Device(jtag, filename, file_type, verbose), _svf(_jtag, _verbose)
Device(jtag, filename, file_type, false, verbose), _svf(_jtag, _verbose)
{
if (!_file_extension.empty()) {
if (_file_extension == "svf")

View File

@ -6,10 +6,11 @@
using namespace std;
Device::Device(Jtag *jtag, string filename, const string &file_type,
int8_t verbose):
bool verify, int8_t verbose):
_filename(filename),
_file_extension(filename.substr(filename.find_last_of(".") +1)),
_mode(NONE_MODE), _verbose(verbose > 0), _quiet(verbose < 0)
_mode(NONE_MODE), _verify(verify), _verbose(verbose > 0),
_quiet(verbose < 0)
{
if (!file_type.empty())
_file_extension = file_type;

View File

@ -26,7 +26,7 @@ class Device {
} prog_type_t;
Device(Jtag *jtag, std::string filename, const std::string &file_type,
int8_t verbose = false);
bool verify, int8_t verbose = false);
virtual ~Device();
virtual void program(unsigned int offset = 0) = 0;
virtual int idCode() = 0;
@ -37,6 +37,7 @@ class Device {
std::string _filename;
std::string _file_extension;
enum prog_mode _mode;
bool _verify; /**< verify flash write */
bool _verbose;
bool _quiet;
};

View File

@ -34,7 +34,7 @@ Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
const std::string &file_type,
uint16_t rst_pin, uint16_t done_pin,
int8_t verbose):
Device(NULL, filename, file_type, verbose), _rst_pin(rst_pin),
Device(NULL, filename, file_type, false, verbose), _rst_pin(rst_pin),
_done_pin(done_pin)
{
_spi = spi;

View File

@ -71,7 +71,7 @@ using namespace std;
Gowin::Gowin(Jtag *jtag, const string filename, const string &file_type,
Device::prog_type_t prg_type,
int8_t verbose): Device(jtag, filename, file_type, verbose),
int8_t verbose): Device(jtag, filename, file_type, false, verbose),
is_gw1n1(false)
{
_fs = NULL;

View File

@ -33,7 +33,7 @@ Ice40::Ice40(FtdiSpi* spi, const std::string &filename,
const std::string &file_type,
uint16_t rst_pin, uint16_t done_pin,
int8_t verbose):
Device(NULL, filename, file_type, verbose), _rst_pin(rst_pin),
Device(NULL, filename, file_type, false, verbose), _rst_pin(rst_pin),
_done_pin(done_pin)
{
_spi = spi;

View File

@ -69,8 +69,9 @@ using namespace std;
# define REG_STATUS_EXEC_ERR (1 << 26)
Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
Device::prog_type_t prg_type, int8_t verbose):
Device(jtag, filename, file_type, verbose), _fpga_family(UNKNOWN_FAMILY)
Device::prog_type_t prg_type, bool verify, int8_t verbose):
Device(jtag, filename, file_type, verify, verbose),
_fpga_family(UNKNOWN_FAMILY)
{
if (!_file_extension.empty()) {
if (_file_extension == "jed" || _file_extension == "mcs") {
@ -358,8 +359,10 @@ bool Lattice::program_intFlash()
return false;
}
/* verify write */
if (_verify) {
if (Verify(cfg_data) == false)
return false;
}
/* missing usercode update */
@ -454,6 +457,31 @@ bool Lattice::program_extFlash(unsigned int offset)
flash.read_status_reg();
flash.erase_and_prog(offset, data, length);
if (_verify) {
printInfo("Verifying write");
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 false;
} 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 false;
}
progress.display(i);
}
progress.done();
}
delete _bit;
return true;
}

View File

@ -32,7 +32,7 @@
class Lattice: public Device, SPIInterface {
public:
Lattice(Jtag *jtag, std::string filename, const std::string &file_type,
Device::prog_type_t prg_type,
Device::prog_type_t prg_type, bool verify,
int8_t verbose);
int idCode() override;
int userCode();

View File

@ -46,7 +46,7 @@ using namespace std;
struct arguments {
int8_t verbose;
bool reset, detect;
bool reset, detect, verify;
unsigned int offset;
string bit_file;
string device;
@ -80,9 +80,9 @@ int main(int argc, char **argv)
jtag_pins_conf_t pins_config = {0, 0, 0, 0};
/* command line args. */
struct arguments args = {0, false, false, 0, "", "", "-", "", -1, 6000000, "-",
false, false, false, false, Device::WR_SRAM, false, false, false, "",
"", "", -1};
struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1,
6000000, "-", false, false, false, false, Device::WR_SRAM, false,
false, false, "", "", "", -1};
/* parse arguments */
try {
if (parse_opt(argc, argv, &args, &pins_config))
@ -355,7 +355,7 @@ int main(int argc, char **argv)
try {
if (fab == "xilinx") {
fpga = new Xilinx(jtag, args.bit_file, args.file_type,
args.prg_type, args.fpga_part, args.verbose);
args.prg_type, args.fpga_part, args.verify, args.verbose);
} else if (fab == "altera") {
fpga = new Altera(jtag, args.bit_file, args.file_type,
args.verbose);
@ -367,7 +367,7 @@ int main(int argc, char **argv)
args.prg_type, args.verbose);
} else if (fab == "lattice") {
fpga = new Lattice(jtag, args.bit_file, args.file_type,
args.prg_type, args.verbose);
args.prg_type, args.verify, args.verbose);
} else {
printError("Error: manufacturer " + fab + " not supported");
delete(jtag);
@ -485,6 +485,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
cxxopts::value<bool>(args->spi))
("v,verbose", "Produce verbose output", cxxopts::value<bool>(verbose))
("h,help", "Give this help list")
("verify", "Verify write operation (SPI Flash only)",
cxxopts::value<bool>(args->verify))
("V,Version", "Print program version");
options.parse_positional({"bitstream"});

View File

@ -17,8 +17,9 @@
Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type,
std::string device_package, int8_t verbose):
Device(jtag, filename, file_type, verbose),_device_package(device_package)
std::string device_package, bool verify, int8_t verbose):
Device(jtag, filename, file_type, verify, verbose),
_device_package(device_package)
{
if (!_file_extension.empty()) {
if (_file_extension == "mcs") {
@ -146,11 +147,44 @@ void Xilinx::program_spi(ConfigBitstreamParser * bit, unsigned int offset)
throw std::runtime_error(e.what());
}
uint8_t *data = bit->getData();
int length = bit->getLength() / 8;
SPIFlash spiFlash(this, (_verbose ? 1 : (_quiet ? -1 : 0)));
spiFlash.reset();
spiFlash.read_id();
spiFlash.read_status_reg();
spiFlash.erase_and_prog(offset, bit->getData(), bit->getLength()/8);
spiFlash.erase_and_prog(offset, data, length);
/* verify write if required */
if (_verify) {
std::string verify_data;
verify_data.resize(256);
ProgressBar progress("Verifying write", length, 50, _quiet);
int rd_length = 256;
for (int i = 0; i < length; i+=rd_length) {
if (rd_length + i > length)
rd_length = length - i;
if (0 != spiFlash.read(offset + i, (uint8_t*)&verify_data[0],
rd_length)) {
progress.fail();
printError("Failed to read flash");
return;
}
for (int ii = 0; ii < rd_length; ii++) {
if ((uint8_t)verify_data[ii] != data[i + ii]) {
progress.fail();
printError("Verification failed at " +
std::to_string(offset + i + ii));
return;
}
}
progress.display(i);
}
progress.done();
}
}
void Xilinx::program_mem(ConfigBitstreamParser *bitfile)

View File

@ -13,7 +13,8 @@ class Xilinx: public Device, SPIInterface {
Xilinx(Jtag *jtag, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type,
std::string device_package, int8_t verbose);
std::string device_package,
bool verify, int8_t verbose);
~Xilinx();
void program(unsigned int offset = 0) override;