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)
|
||||
--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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
22
src/main.cpp
22
src/main.cpp
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue