All devices: new CLI argument to bypass file type autodetection
This commit is contained in:
parent
7cc5676e8e
commit
df52d523bf
|
|
@ -139,6 +139,8 @@ openFPGALoader -- a program to flash FPGA
|
|||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to A-D)
|
||||
-d, --device arg device to use (/dev/ttyUSBx)
|
||||
--detect detect FPGA
|
||||
--file-type arg provides file type instead of let's deduced by
|
||||
using extension
|
||||
--freq arg jtag frequency (Hz)
|
||||
-f, --write-flash write bitstream in flash (default: false, only for
|
||||
Gowin and ECP5 devices)
|
||||
|
|
@ -205,6 +207,11 @@ openFPGALoader [options] -r
|
|||
openFPGALoader [options] /path/to/bitstream.ext
|
||||
```
|
||||
|
||||
#### Automatic file type detection bypass
|
||||
|
||||
Default behavior is to use file extension to determine file parser. To avoid
|
||||
this mecanism `--file-type type` must be used.
|
||||
|
||||
#### bitbang mode and pins configuration
|
||||
|
||||
*FT232R* and *ft231X* may be used as JTAG programmer. JTAG communications are
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
// DATA_DIR is defined at compile time.
|
||||
#define BIT_FOR_FLASH (DATA_DIR "/openFPGALoader/test_sfl.svf")
|
||||
|
||||
Altera::Altera(Jtag *jtag, const std::string &filename, int8_t verbose):
|
||||
Device(jtag, filename, verbose), _svf(_jtag, _verbose)
|
||||
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)
|
||||
{
|
||||
if (_filename != "") {
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "svf" || _file_extension == "rbf")
|
||||
_mode = Device::MEM_MODE;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
class Altera: public Device {
|
||||
public:
|
||||
Altera(Jtag *jtag, const std::string &filename, int8_t verbose);
|
||||
Altera(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type, int8_t verbose);
|
||||
~Altera();
|
||||
|
||||
void programMem();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "anlogic.hpp"
|
||||
#include "anlogicBitParser.hpp"
|
||||
#include "jtag.hpp"
|
||||
|
|
@ -34,10 +37,11 @@
|
|||
#define IRLENGTH 8
|
||||
|
||||
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, verbose), _svf(_jtag, _verbose)
|
||||
Device(jtag, filename, file_type, verbose), _svf(_jtag, _verbose)
|
||||
{
|
||||
if (_filename != "") {
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "svf")
|
||||
_mode = Device::MEM_MODE;
|
||||
else if (_file_extension == "bit") {
|
||||
|
|
@ -46,7 +50,7 @@ Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
|
|||
else
|
||||
_mode = Device::SPI_MODE;
|
||||
} else
|
||||
throw std::exception();
|
||||
throw std::runtime_error("incompatible file format");
|
||||
}
|
||||
}
|
||||
Anlogic::~Anlogic()
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
class Anlogic: public Device, SPIInterface {
|
||||
public:
|
||||
Anlogic(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type, int8_t verbose);
|
||||
~Anlogic();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
Device::Device(Jtag *jtag, string filename, int8_t verbose):
|
||||
Device::Device(Jtag *jtag, string filename, const string &file_type,
|
||||
int8_t verbose):
|
||||
_filename(filename),
|
||||
_file_extension(filename.substr(filename.find_last_of(".") +1)),
|
||||
_mode(NONE_MODE), _verbose(verbose > 0), _quiet(verbose < 0)
|
||||
{
|
||||
if (!file_type.empty())
|
||||
_file_extension = file_type;
|
||||
_jtag = jtag;
|
||||
if (verbose > 0)
|
||||
cout << "File type : " << _file_extension << endl;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ class Device {
|
|||
WR_FLASH = 1
|
||||
} prog_type_t;
|
||||
|
||||
Device(Jtag *jtag, std::string filename, int8_t verbose = false);
|
||||
Device(Jtag *jtag, std::string filename, const std::string &file_type,
|
||||
int8_t verbose = false);
|
||||
virtual ~Device();
|
||||
virtual void program(unsigned int offset = 0) = 0;
|
||||
virtual int idCode() = 0;
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@
|
|||
#include "spiFlash.hpp"
|
||||
|
||||
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, verbose), _rst_pin(rst_pin),
|
||||
Device(NULL, filename, file_type, verbose), _rst_pin(rst_pin),
|
||||
_done_pin(done_pin)
|
||||
{
|
||||
_spi = spi;
|
||||
|
|
@ -65,7 +66,7 @@ void Efinix::program(unsigned int offset)
|
|||
{
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
if (_filename == "")
|
||||
if (_file_extension.empty())
|
||||
return;
|
||||
|
||||
ConfigBitstreamParser *bit;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
class Efinix: public Device {
|
||||
public:
|
||||
Efinix(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
uint16_t rst_pin, uint16_t done_pin,
|
||||
int8_t verbose);
|
||||
~Efinix();
|
||||
|
|
|
|||
|
|
@ -69,11 +69,13 @@ using namespace std;
|
|||
#define EF_PROGRAM 0x71
|
||||
#define EFLASH_ERASE 0x75
|
||||
|
||||
Gowin::Gowin(Jtag *jtag, const string filename, Device::prog_type_t prg_type,
|
||||
int8_t verbose): Device(jtag, filename, verbose), is_gw1n1(false)
|
||||
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),
|
||||
is_gw1n1(false)
|
||||
{
|
||||
_fs = NULL;
|
||||
if (_filename != "") {
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "fs") {
|
||||
if (prg_type == Device::WR_FLASH)
|
||||
_mode = Device::FLASH_MODE;
|
||||
|
|
@ -161,7 +163,7 @@ void Gowin::program(unsigned int offset)
|
|||
uint32_t status;
|
||||
int length;
|
||||
|
||||
if (_filename == "" || !_fs)
|
||||
if (_mode == NONE_MODE || !_fs)
|
||||
return;
|
||||
|
||||
if (_mode == FLASH_MODE) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
|
||||
class Gowin: public Device {
|
||||
public:
|
||||
Gowin(Jtag *jtag, std::string filename, Device::prog_type_t prg_type,
|
||||
Gowin(Jtag *jtag, std::string filename, const std::string &file_type,
|
||||
Device::prog_type_t prg_type,
|
||||
int8_t verbose);
|
||||
~Gowin();
|
||||
int idCode() override;
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@
|
|||
#include "spiFlash.hpp"
|
||||
|
||||
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, verbose), _rst_pin(rst_pin),
|
||||
Device(NULL, filename, file_type, verbose), _rst_pin(rst_pin),
|
||||
_done_pin(done_pin)
|
||||
{
|
||||
_spi = spi;
|
||||
|
|
@ -64,7 +65,7 @@ void Ice40::program(unsigned int offset)
|
|||
{
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
if (_filename == "")
|
||||
if (_file_extension.empty())
|
||||
return;
|
||||
|
||||
RawParser bit(_filename, false);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
class Ice40: public Device {
|
||||
public:
|
||||
Ice40(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
uint16_t rst_pin, uint16_t done_pin,
|
||||
int8_t verbose);
|
||||
~Ice40();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "jtag.hpp"
|
||||
#include "lattice.hpp"
|
||||
|
|
@ -67,11 +68,11 @@ using namespace std;
|
|||
# define REG_STATUS_CNF_CHK_MASK (0x7 << 23)
|
||||
# define REG_STATUS_EXEC_ERR (1 << 26)
|
||||
|
||||
Lattice::Lattice(Jtag *jtag, const string filename,
|
||||
Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
|
||||
Device::prog_type_t prg_type, int8_t verbose):
|
||||
Device(jtag, filename, verbose), _fpga_family(UNKNOWN_FAMILY)
|
||||
Device(jtag, filename, file_type, verbose), _fpga_family(UNKNOWN_FAMILY)
|
||||
{
|
||||
if (_filename != "") {
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "jed" || _file_extension == "mcs") {
|
||||
_mode = Device::FLASH_MODE;
|
||||
} else if (_file_extension == "bit") {
|
||||
|
|
@ -83,7 +84,7 @@ Lattice::Lattice(Jtag *jtag, const string filename,
|
|||
// for raw bin to flash at offset != 0
|
||||
_mode = Device::FLASH_MODE;
|
||||
} else {
|
||||
throw std::exception();
|
||||
throw std::runtime_error("incompatible file format");
|
||||
}
|
||||
}
|
||||
/* check device family */
|
||||
|
|
@ -162,7 +163,7 @@ bool Lattice::program_mem()
|
|||
bool err;
|
||||
LatticeBitParser _bit(_filename, _verbose);
|
||||
|
||||
printInfo("Open file " + _filename + " ", false);
|
||||
printInfo("Open file ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _bit.parse();
|
||||
|
|
@ -280,12 +281,12 @@ bool Lattice::program_intFlash()
|
|||
bool err;
|
||||
uint64_t featuresRow;
|
||||
uint16_t feabits;
|
||||
uint8_t eraseMode;
|
||||
uint8_t eraseMode = 0;
|
||||
vector<string> ufm_data, cfg_data, ebr_data;
|
||||
|
||||
JedParser _jed(_filename, _verbose);
|
||||
|
||||
printInfo("Open file " + _filename + " ", false);
|
||||
printInfo("Open file ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _jed.parse();
|
||||
|
|
@ -422,7 +423,7 @@ bool Lattice::program_extFlash(unsigned int offset)
|
|||
_bit = new RawParser(_filename, false);
|
||||
}
|
||||
|
||||
printInfo("Open file " + _filename + " ", false);
|
||||
printInfo("Open file ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
int err = _bit->parse();
|
||||
|
|
@ -430,6 +431,7 @@ bool Lattice::program_extFlash(unsigned int offset)
|
|||
printInfo("Parse file ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
delete _bit;
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
class Lattice: public Device, SPIInterface {
|
||||
public:
|
||||
Lattice(Jtag *jtag, std::string filename, Device::prog_type_t prg_type,
|
||||
Lattice(Jtag *jtag, std::string filename, const std::string &file_type,
|
||||
Device::prog_type_t prg_type,
|
||||
int8_t verbose);
|
||||
int idCode() override;
|
||||
int userCode();
|
||||
|
|
|
|||
37
src/main.cpp
37
src/main.cpp
|
|
@ -61,6 +61,7 @@ struct arguments {
|
|||
Device::prog_type_t prg_type;
|
||||
bool is_list_command;
|
||||
bool spi;
|
||||
string file_type;
|
||||
};
|
||||
|
||||
int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *pins_config);
|
||||
|
|
@ -75,7 +76,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* command line args. */
|
||||
struct arguments args = {0, false, false, 0, "", "", "-", "", -1, 6000000, "-",
|
||||
false, false, false, false, Device::WR_SRAM, false, false};
|
||||
false, false, false, false, Device::WR_SRAM, false, false, ""};
|
||||
/* parse arguments */
|
||||
try {
|
||||
if (parse_opt(argc, argv, &args, &pins_config))
|
||||
|
|
@ -166,12 +167,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (board->manufacturer == "efinix") {
|
||||
Efinix target(spi, args.bit_file, board->reset_pin, board->done_pin,
|
||||
args.verbose);
|
||||
Efinix target(spi, args.bit_file, args.file_type,
|
||||
board->reset_pin, board->done_pin, args.verbose);
|
||||
target.program(args.offset);
|
||||
} else if (board->manufacturer == "lattice") {
|
||||
Ice40 target(spi, args.bit_file, board->reset_pin, board->done_pin,
|
||||
args.verbose);
|
||||
Ice40 target(spi, args.bit_file, args.file_type,
|
||||
board->reset_pin, board->done_pin, args.verbose);
|
||||
target.program(args.offset);
|
||||
} else {
|
||||
RawParser *bit = NULL;
|
||||
|
|
@ -185,7 +186,7 @@ int main(int argc, char **argv)
|
|||
flash.reset();
|
||||
flash.read_id();
|
||||
|
||||
if (!args.bit_file.empty()) {
|
||||
if (!args.bit_file.empty() || !args.file_type.empty()) {
|
||||
printInfo("Open file " + args.bit_file + " ", false);
|
||||
try {
|
||||
bit = new RawParser(args.bit_file, false);
|
||||
|
|
@ -267,26 +268,27 @@ int main(int argc, char **argv)
|
|||
Device *fpga;
|
||||
try {
|
||||
if (fab == "xilinx") {
|
||||
fpga = new Xilinx(jtag, args.bit_file, args.prg_type,
|
||||
args.verbose);
|
||||
fpga = new Xilinx(jtag, args.bit_file, args.file_type,
|
||||
args.prg_type, args.verbose);
|
||||
} else if (fab == "altera") {
|
||||
fpga = new Altera(jtag, args.bit_file, args.verbose);
|
||||
fpga = new Altera(jtag, args.bit_file, args.file_type,
|
||||
args.verbose);
|
||||
} else if (fab == "anlogic") {
|
||||
fpga = new Anlogic(jtag, args.bit_file, args.prg_type,
|
||||
args.verbose);
|
||||
fpga = new Anlogic(jtag, args.bit_file, args.file_type,
|
||||
args.prg_type, args.verbose);
|
||||
} else if (fab == "Gowin") {
|
||||
fpga = new Gowin(jtag, args.bit_file, args.prg_type,
|
||||
args.verbose);
|
||||
fpga = new Gowin(jtag, args.bit_file, args.file_type,
|
||||
args.prg_type, args.verbose);
|
||||
} else if (fab == "lattice") {
|
||||
fpga = new Lattice(jtag, args.bit_file, args.prg_type,
|
||||
args.verbose);
|
||||
fpga = new Lattice(jtag, args.bit_file, args.file_type,
|
||||
args.prg_type, args.verbose);
|
||||
} else {
|
||||
printError("Error: manufacturer " + fab + " not supported");
|
||||
delete(jtag);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
printError("Error: Failed to claim FPGA device");
|
||||
printError("Error: Failed to claim FPGA device: " + string(e.what()));
|
||||
delete(jtag);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
@ -366,6 +368,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
|
|||
#endif
|
||||
("detect", "detect FPGA",
|
||||
cxxopts::value<bool>(args->detect))
|
||||
("file-type", "provides file type instead of let's deduced by using extension",
|
||||
cxxopts::value<string>(args->file_type))
|
||||
("freq", "jtag frequency (Hz)", cxxopts::value<string>(freqo))
|
||||
("f,write-flash",
|
||||
"write bitstream in flash (default: false, only for Gowin and ECP5 devices)")
|
||||
|
|
@ -499,6 +503,7 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
|
|||
args->is_list_command = true;
|
||||
|
||||
if (args->bit_file.empty() &&
|
||||
args->file_type.empty() &&
|
||||
!args->is_list_command &&
|
||||
!args->detect &&
|
||||
!args->reset) {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
#include "progressBar.hpp"
|
||||
|
||||
Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type, int8_t verbose):
|
||||
Device(jtag, filename, verbose)
|
||||
Device(jtag, filename, file_type, verbose)
|
||||
{
|
||||
if (_filename != ""){
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "mcs") {
|
||||
_mode = Device::SPI_MODE;
|
||||
} else if (_file_extension == "bit" || _file_extension == "bin") {
|
||||
|
|
@ -83,7 +84,7 @@ void Xilinx::program(unsigned int offset)
|
|||
if (_mode == Device::MEM_MODE)
|
||||
reverse = true;
|
||||
|
||||
printInfo("Open file " + _filename + " ", false);
|
||||
printInfo("Open file ", false);
|
||||
try {
|
||||
if (_file_extension == "bit")
|
||||
bit = new BitParser(_filename, reverse, _verbose);
|
||||
|
|
@ -138,7 +139,7 @@ void Xilinx::program_spi(ConfigBitstreamParser * bit, unsigned int offset)
|
|||
|
||||
void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
|
||||
{
|
||||
if (_filename == "") return;
|
||||
if (_file_extension.empty()) return;
|
||||
std::cout << "load program" << std::endl;
|
||||
unsigned char tx_buf, rx_buf;
|
||||
/* comment TDI TMS TCK
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
class Xilinx: public Device, SPIInterface {
|
||||
public:
|
||||
Xilinx(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type, int8_t verbose);
|
||||
~Xilinx();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue