lattice,device: introduce method to dump flash content

This commit is contained in:
Gwenhael Goavec-Merou 2021-06-24 18:19:09 +02:00
parent c471d25bb5
commit fe0a315456
5 changed files with 107 additions and 6 deletions

View File

@ -191,6 +191,9 @@ openFPGALoader -- a program to flash FPGA
-d, --device arg device to use (/dev/ttyUSBx)
--detect detect FPGA
--dfu DFU mode
--dump-flash Dump flash mode
--file-size arg provides size in Byte to dump, must be used with
dump-flash
--file-type arg provides file type instead of let's deduced by
using extension
--fpga-part arg fpga model flavor + package

View File

@ -17,18 +17,23 @@ class Device {
NONE_MODE = 0,
SPI_MODE = 1,
FLASH_MODE = 1,
MEM_MODE = 2
MEM_MODE = 2,
READ_MODE = 3,
};
typedef enum {
WR_SRAM = 0,
WR_FLASH = 1
WR_FLASH = 1,
RD_FLASH = 2
} prog_type_t;
Device(Jtag *jtag, std::string filename, const std::string &file_type,
bool verify, int8_t verbose = false);
virtual ~Device();
virtual void program(unsigned int offset = 0) = 0;
virtual bool dumpFlash(const std::string &filename,
uint32_t base_addr, uint32_t len) {
(void)filename; (void) base_addr; (void) len; return false;}
virtual int idCode() = 0;
virtual void reset();

View File

@ -73,7 +73,9 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
Device(jtag, filename, file_type, verify, verbose),
_fpga_family(UNKNOWN_FAMILY)
{
if (!_file_extension.empty()) {
if (prg_type == Device::RD_FLASH) {
_mode = READ_MODE;
} else if (!_file_extension.empty()) {
if (_file_extension == "jed" || _file_extension == "mcs") {
_mode = Device::FLASH_MODE;
} else if (_file_extension == "bit" || _file_extension == "bin") {
@ -556,6 +558,79 @@ void Lattice::program(unsigned int offset)
program_mem();
}
bool Lattice::dumpFlash(const string &filename,
uint32_t base_addr, uint32_t len)
{
/* idem program */
/* preload 0x1C */
uint8_t tx_buf[26];
memset(tx_buf, 0xff, 26);
wr_rd(0x1C, tx_buf, 26, NULL, 0);
wr_rd(0xFf, NULL, 0, NULL, 0);
/* ISC Enable 0xC6 */
printInfo("Enable configuration: ", false);
if (!EnableISC(0x00)) {
printError("FAIL");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
/* ISC ERASE */
printInfo("SRAM erase: ", false);
if (flashErase(FLASH_ERASE_SRAM) == false) {
printError("FAIL");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
DisableISC();
string data;
data.resize(len);
/* switch to SPI mode */
_jtag->shiftIR(0x3A, 8, Jtag::EXIT1_IR);
uint8_t tmp[2] = {0xFE, 0x68};
_jtag->shiftDR(tmp, NULL, 16);
/* prepare SPI access */
SPIFlash flash(this, _verbose);
flash.reset();
flash.read_id();
flash.read_status_reg();
flash.read(base_addr, (uint8_t*)&data[0], len);
FILE *fd = fopen(filename.c_str(), "wb");
if (!fd) {
return false;
}
fwrite(data.c_str(), sizeof(uint8_t), len, fd);
fclose(fd);
/* ISC REFRESH 0x79 */
printInfo("Refresh: ", false);
if (loadConfiguration() == false) {
printError("FAIL");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
/* bypass */
wr_rd(0xff, NULL, 0, NULL, 0);
_jtag->go_test_logic_reset();
return true;
}
/* flash mode :
*/
bool Lattice::EnableISC(uint8_t flash_mode)

View File

@ -41,6 +41,8 @@ class Lattice: public Device, SPIInterface {
bool program_mem();
bool program_flash(unsigned int offset);
bool Verify(std::vector<std::string> data, bool unlock = false);
bool dumpFlash(const std::string &filename,
uint32_t base_addr, uint32_t len) override;
/* spi interface */
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,

View File

@ -67,6 +67,7 @@ struct arguments {
string fpga_part;
string probe_firmware;
int index_chain;
unsigned int file_size;
};
int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *pins_config);
@ -82,7 +83,7 @@ int main(int argc, char **argv)
/* command line args. */
struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1,
6000000, "-", false, false, false, false, Device::WR_SRAM, false,
false, false, "", "", "", -1};
false, false, "", "", "", -1, 0};
/* parse arguments */
try {
if (parse_opt(argc, argv, &args, &pins_config))
@ -379,7 +380,8 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
if (!args.bit_file.empty() || !args.file_type.empty()) {
if ((!args.bit_file.empty() || !args.file_type.empty())
&& args.prg_type != Device::RD_FLASH) {
try {
fpga->program(args.offset);
} catch (std::exception &e) {
@ -389,6 +391,14 @@ int main(int argc, char **argv)
}
}
if (args.prg_type == Device::RD_FLASH) {
if (args.file_size == 0) {
printError("Error: 0 size for dump");
} else {
fpga->dumpFlash(args.bit_file, args.offset, args.file_size);
}
}
if (args.reset)
fpga->reset();
@ -455,6 +465,9 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
("detect", "detect FPGA",
cxxopts::value<bool>(args->detect))
("dfu", "DFU mode", cxxopts::value<bool>(args->dfu))
("dump-flash", "Dump flash mode")
("file-size", "provides size in Byte to dump, must be used with dump-flash",
cxxopts::value<unsigned int>(args->file_size))
("file-type", "provides file type instead of let's deduced by using extension",
cxxopts::value<string>(args->file_type))
("fpga-part", "fpga model flavor + package", cxxopts::value<string>(args->fpga_part))
@ -511,7 +524,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
return 1;
}
if (result.count("write-flash") && result.count("write-sram")) {
if (result.count("write-flash") && result.count("write-sram") &&
result.count("dump-flash")) {
printError("Error: both write to flash and write to ram enabled");
throw std::exception();
}
@ -520,6 +534,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
args->prg_type = Device::WR_FLASH;
else if (result.count("write-sram"))
args->prg_type = Device::WR_SRAM;
else if (result.count("dump-flash"))
args->prg_type = Device::RD_FLASH;
if (result.count("freq")) {
double freq;