lattice,device: introduce method to dump flash content
This commit is contained in:
parent
c471d25bb5
commit
fe0a315456
|
|
@ -191,6 +191,9 @@ openFPGALoader -- a program to flash FPGA
|
||||||
-d, --device arg device to use (/dev/ttyUSBx)
|
-d, --device arg device to use (/dev/ttyUSBx)
|
||||||
--detect detect FPGA
|
--detect detect FPGA
|
||||||
--dfu DFU mode
|
--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
|
--file-type arg provides file type instead of let's deduced by
|
||||||
using extension
|
using extension
|
||||||
--fpga-part arg fpga model flavor + package
|
--fpga-part arg fpga model flavor + package
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,23 @@ class Device {
|
||||||
NONE_MODE = 0,
|
NONE_MODE = 0,
|
||||||
SPI_MODE = 1,
|
SPI_MODE = 1,
|
||||||
FLASH_MODE = 1,
|
FLASH_MODE = 1,
|
||||||
MEM_MODE = 2
|
MEM_MODE = 2,
|
||||||
|
READ_MODE = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WR_SRAM = 0,
|
WR_SRAM = 0,
|
||||||
WR_FLASH = 1
|
WR_FLASH = 1,
|
||||||
|
RD_FLASH = 2
|
||||||
} prog_type_t;
|
} prog_type_t;
|
||||||
|
|
||||||
Device(Jtag *jtag, std::string filename, const std::string &file_type,
|
Device(Jtag *jtag, std::string filename, const std::string &file_type,
|
||||||
bool verify, int8_t verbose = false);
|
bool verify, int8_t verbose = false);
|
||||||
virtual ~Device();
|
virtual ~Device();
|
||||||
virtual void program(unsigned int offset = 0) = 0;
|
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 int idCode() = 0;
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,9 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
|
||||||
Device(jtag, filename, file_type, verify, verbose),
|
Device(jtag, filename, file_type, verify, verbose),
|
||||||
_fpga_family(UNKNOWN_FAMILY)
|
_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") {
|
if (_file_extension == "jed" || _file_extension == "mcs") {
|
||||||
_mode = Device::FLASH_MODE;
|
_mode = Device::FLASH_MODE;
|
||||||
} else if (_file_extension == "bit" || _file_extension == "bin") {
|
} else if (_file_extension == "bit" || _file_extension == "bin") {
|
||||||
|
|
@ -556,6 +558,79 @@ void Lattice::program(unsigned int offset)
|
||||||
program_mem();
|
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 :
|
/* flash mode :
|
||||||
*/
|
*/
|
||||||
bool Lattice::EnableISC(uint8_t flash_mode)
|
bool Lattice::EnableISC(uint8_t flash_mode)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ class Lattice: public Device, SPIInterface {
|
||||||
bool program_mem();
|
bool program_mem();
|
||||||
bool program_flash(unsigned int offset);
|
bool program_flash(unsigned int offset);
|
||||||
bool Verify(std::vector<std::string> data, bool unlock = false);
|
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 */
|
/* spi interface */
|
||||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||||
|
|
|
||||||
22
src/main.cpp
22
src/main.cpp
|
|
@ -67,6 +67,7 @@ struct arguments {
|
||||||
string fpga_part;
|
string fpga_part;
|
||||||
string probe_firmware;
|
string probe_firmware;
|
||||||
int index_chain;
|
int index_chain;
|
||||||
|
unsigned int file_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *pins_config);
|
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. */
|
/* command line args. */
|
||||||
struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1,
|
struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1,
|
||||||
6000000, "-", false, false, false, false, Device::WR_SRAM, false,
|
6000000, "-", false, false, false, false, Device::WR_SRAM, false,
|
||||||
false, false, "", "", "", -1};
|
false, false, "", "", "", -1, 0};
|
||||||
/* parse arguments */
|
/* parse arguments */
|
||||||
try {
|
try {
|
||||||
if (parse_opt(argc, argv, &args, &pins_config))
|
if (parse_opt(argc, argv, &args, &pins_config))
|
||||||
|
|
@ -379,7 +380,8 @@ int main(int argc, char **argv)
|
||||||
return EXIT_FAILURE;
|
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 {
|
try {
|
||||||
fpga->program(args.offset);
|
fpga->program(args.offset);
|
||||||
} catch (std::exception &e) {
|
} 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)
|
if (args.reset)
|
||||||
fpga->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",
|
("detect", "detect FPGA",
|
||||||
cxxopts::value<bool>(args->detect))
|
cxxopts::value<bool>(args->detect))
|
||||||
("dfu", "DFU mode", cxxopts::value<bool>(args->dfu))
|
("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",
|
("file-type", "provides file type instead of let's deduced by using extension",
|
||||||
cxxopts::value<string>(args->file_type))
|
cxxopts::value<string>(args->file_type))
|
||||||
("fpga-part", "fpga model flavor + package", cxxopts::value<string>(args->fpga_part))
|
("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;
|
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");
|
printError("Error: both write to flash and write to ram enabled");
|
||||||
throw std::exception();
|
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;
|
args->prg_type = Device::WR_FLASH;
|
||||||
else if (result.count("write-sram"))
|
else if (result.count("write-sram"))
|
||||||
args->prg_type = Device::WR_SRAM;
|
args->prg_type = Device::WR_SRAM;
|
||||||
|
else if (result.count("dump-flash"))
|
||||||
|
args->prg_type = Device::RD_FLASH;
|
||||||
|
|
||||||
if (result.count("freq")) {
|
if (result.count("freq")) {
|
||||||
double freq;
|
double freq;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue