Merge pull request #298 from barbedo/vcu118-flash-cli-options
Add target-flash and secondary-bitstream CLI options for VCU118
This commit is contained in:
commit
e8fbc1539a
125
README.md
125
README.md
|
|
@ -49,68 +49,73 @@ openFPGALoader -c cmsisdap fpga_bitstream.bit
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage: ./openFPGALoader [OPTION...] BIT_FILE
|
Usage: openFPGALoader [OPTION...] BIT_FILE
|
||||||
openFPGALoader -- a program to flash FPGA
|
openFPGALoader -- a program to flash FPGA
|
||||||
|
|
||||||
--altsetting arg DFU interface altsetting (only for DFU mode)
|
--altsetting arg DFU interface altsetting (only for DFU mode)
|
||||||
--bitstream arg bitstream
|
--bitstream arg bitstream
|
||||||
-b, --board arg board name, may be used instead of cable
|
--secondary-bitstream arg
|
||||||
-B, --bridge arg disable spiOverJtag model detection by providing
|
secondary bitstream (some Xilinx UltraScale
|
||||||
bitstream(intel/xilinx)
|
boards)
|
||||||
-c, --cable arg jtag interface
|
-b, --board arg board name, may be used instead of cable
|
||||||
--invert-read-edge JTAG mode / FTDI: read on negative edge instead
|
-B, --bridge arg disable spiOverJtag model detection by
|
||||||
of positive
|
providing bitstream(intel/xilinx)
|
||||||
--vid arg probe Vendor ID
|
-c, --cable arg jtag interface
|
||||||
--pid arg probe Product ID
|
--invert-read-edge JTAG mode / FTDI: read on negative edge
|
||||||
--cable-index arg probe index (FTDI and cmsisDAP)
|
instead of positive
|
||||||
--busdev-num arg select a probe by it bus and device number
|
--vid arg probe Vendor ID
|
||||||
(bus_num:device_addr)
|
--pid arg probe Product ID
|
||||||
--ftdi-serial arg FTDI chip serial number
|
--cable-index arg probe index (FTDI and cmsisDAP)
|
||||||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
--busdev-num arg select a probe by it bus and device number
|
||||||
A-D)
|
(bus_num:device_addr)
|
||||||
-d, --device arg device to use (/dev/ttyUSBx)
|
--ftdi-serial arg FTDI chip serial number
|
||||||
--detect detect FPGA
|
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
||||||
--dfu DFU mode
|
A-D)
|
||||||
--dump-flash Dump flash mode
|
--detect detect FPGA
|
||||||
--external-flash select ext flash for device with internal and
|
--dfu DFU mode
|
||||||
external storage
|
--dump-flash Dump flash mode
|
||||||
--file-size arg provides size in Byte to dump, must be used with
|
--bulk-erase Bulk erase flash
|
||||||
dump-flash
|
--target-flash arg for boards with multiple flash chips (some
|
||||||
--file-type arg provides file type instead of let's deduced by
|
Xilinx UltraScale boards), select the target
|
||||||
using extension
|
flash: primary (default), secondary or both
|
||||||
--flash-sector arg flash sector (Lattice parts only)
|
--external-flash select ext flash for device with internal and
|
||||||
--fpga-part arg fpga model flavor + package
|
external storage
|
||||||
--freq arg jtag frequency (Hz)
|
--file-size arg provides size in Byte to dump, must be used
|
||||||
-f, --write-flash write bitstream in flash (default: false)
|
with dump-flash
|
||||||
--index-chain arg device index in JTAG-chain
|
--file-type arg provides file type instead of let's deduced
|
||||||
--ip arg IP address (only for XVC client)
|
by using extension
|
||||||
--list-boards list all supported boards
|
--flash-sector arg flash sector (Lattice parts only)
|
||||||
--list-cables list all supported cables
|
--fpga-part arg fpga model flavor + package
|
||||||
--list-fpga list all supported FPGA
|
--freq arg jtag frequency (Hz)
|
||||||
-m, --write-sram write bitstream in SRAM (default: true)
|
-f, --write-flash write bitstream in flash (default: false)
|
||||||
-o, --offset arg start offset in EEPROM
|
--index-chain arg device index in JTAG-chain
|
||||||
--pins arg pin config TDI:TDO:TCK:TMS
|
--ip arg IP address (only for XVC client)
|
||||||
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
--list-boards list all supported boards
|
||||||
--protect-flash arg protect SPI flash area
|
--list-cables list all supported cables
|
||||||
--quiet Produce quiet output (no progress bar)
|
--list-fpga list all supported FPGA
|
||||||
-r, --reset reset FPGA after operations
|
-m, --write-sram write bitstream in SRAM (default: true)
|
||||||
--scan-usb scan USB to display connected probes
|
-o, --offset arg start offset in EEPROM
|
||||||
--skip-load-bridge skip writing bridge to SRAM when in write-flash
|
--pins arg pin config TDI:TDO:TCK:TMS
|
||||||
mode
|
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
||||||
--skip-reset skip resetting the device when in write-flash
|
--protect-flash arg protect SPI flash area
|
||||||
mode
|
--quiet Produce quiet output (no progress bar)
|
||||||
--spi SPI mode (only for FTDI in serial mode)
|
-r, --reset reset FPGA after operations
|
||||||
--unprotect-flash Unprotect flash blocks
|
--scan-usb scan USB to display connected probes
|
||||||
-v, --verbose Produce verbose output
|
--skip-load-bridge skip writing bridge to SRAM when in
|
||||||
--verbose-level arg verbose level -1: quiet, 0: normal, 1:verbose,
|
write-flash mode
|
||||||
2:debug
|
--skip-reset skip resetting the device when in write-flash
|
||||||
-h, --help Give this help list
|
mode
|
||||||
--verify Verify write operation (SPI Flash only)
|
--spi SPI mode (only for FTDI in serial mode)
|
||||||
--xvc Xilinx Virtual Cable Functions
|
--unprotect-flash Unprotect flash blocks
|
||||||
--port arg Xilinx Virtual Cable Port (default 3721)
|
-v, --verbose Produce verbose output
|
||||||
--mcufw arg Microcontroller firmware
|
--verbose-level arg verbose level -1: quiet, 0: normal,
|
||||||
--conmcu Connect JTAG to MCU
|
1:verbose, 2:debug
|
||||||
-V, --Version Print program version
|
-h, --help Give this help list
|
||||||
|
--verify Verify write operation (SPI Flash only)
|
||||||
|
--port arg Xilinx Virtual Cable Port (default 3721)
|
||||||
|
--mcufw arg Microcontroller firmware
|
||||||
|
--conmcu Connect JTAG to MCU
|
||||||
|
-V, --Version Print program version
|
||||||
|
|
||||||
Mandatory or optional arguments to long options are also mandatory or optional
|
Mandatory or optional arguments to long options are also mandatory or optional
|
||||||
for any corresponding short options.
|
for any corresponding short options.
|
||||||
|
|
|
||||||
|
|
@ -689,4 +689,4 @@
|
||||||
URL: https://www.xilinx.com/products/boards-and-kits/vcu118.html
|
URL: https://www.xilinx.com/products/boards-and-kits/vcu118.html
|
||||||
FPGA: Virtex UltraScale+ xcvu9p-flga2104
|
FPGA: Virtex UltraScale+ xcvu9p-flga2104
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: NA
|
Flash: OK
|
||||||
|
|
|
||||||
41
src/main.cpp
41
src/main.cpp
|
|
@ -47,6 +47,7 @@ struct arguments {
|
||||||
bool reset, detect, verify, scan_usb;
|
bool reset, detect, verify, scan_usb;
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
string bit_file;
|
string bit_file;
|
||||||
|
string secondary_bit_file;
|
||||||
string device;
|
string device;
|
||||||
string cable;
|
string cable;
|
||||||
string ftdi_serial;
|
string ftdi_serial;
|
||||||
|
|
@ -68,6 +69,7 @@ struct arguments {
|
||||||
string probe_firmware;
|
string probe_firmware;
|
||||||
int index_chain;
|
int index_chain;
|
||||||
unsigned int file_size;
|
unsigned int file_size;
|
||||||
|
string target_flash;
|
||||||
bool external_flash;
|
bool external_flash;
|
||||||
int16_t altsetting;
|
int16_t altsetting;
|
||||||
uint16_t vid;
|
uint16_t vid;
|
||||||
|
|
@ -105,12 +107,12 @@ int main(int argc, char **argv)
|
||||||
jtag_pins_conf_t pins_config = {0, 0, 0, 0};
|
jtag_pins_conf_t pins_config = {0, 0, 0, 0};
|
||||||
|
|
||||||
/* command line args. */
|
/* command line args. */
|
||||||
struct arguments args = {0, false, false, false, false, 0, "", "", "-", "", -1,
|
struct arguments args = {0, false, false, false, false, 0, "", "", "", "-", "", -1,
|
||||||
0, false, "-", false, false, false, false, Device::PRG_NONE, false,
|
0, false, "-", false, false, false, false, Device::PRG_NONE, false,
|
||||||
/* spi dfu file_type fpga_part bridge_path probe_firmware */
|
/* spi dfu file_type fpga_part bridge_path probe_firmware */
|
||||||
false, false, "", "", "", "",
|
false, false, "", "", "", "",
|
||||||
/* index_chain file_size external_flash altsetting */
|
/* index_chain file_size target_flash external_flash altsetting */
|
||||||
-1, 0, false, -1,
|
-1, 0, "primary", false, -1,
|
||||||
/* vid, pid, index bus_addr, device_addr */
|
/* vid, pid, index bus_addr, device_addr */
|
||||||
0, 0, -1, 0, 0,
|
0, 0, -1, 0, 0,
|
||||||
"127.0.0.1", 0, false, false, "", false, false,
|
"127.0.0.1", 0, false, false, "", false, false,
|
||||||
|
|
@ -536,9 +538,9 @@ int main(int argc, char **argv)
|
||||||
Device *fpga;
|
Device *fpga;
|
||||||
try {
|
try {
|
||||||
if (fab == "xilinx") {
|
if (fab == "xilinx") {
|
||||||
fpga = new Xilinx(jtag, args.bit_file, args.file_type,
|
fpga = new Xilinx(jtag, args.bit_file, args.secondary_bit_file,
|
||||||
args.prg_type, args.fpga_part, args.bridge_path, args.verify,
|
args.file_type, args.prg_type, args.fpga_part, args.bridge_path,
|
||||||
args.verbose);
|
args.target_flash, args.verify, args.verbose);
|
||||||
} else if (fab == "altera") {
|
} else if (fab == "altera") {
|
||||||
fpga = new Altera(jtag, args.bit_file, args.file_type,
|
fpga = new Altera(jtag, args.bit_file, args.file_type,
|
||||||
args.prg_type, args.fpga_part, args.bridge_path, args.verify,
|
args.prg_type, args.fpga_part, args.bridge_path, args.verify,
|
||||||
|
|
@ -569,7 +571,9 @@ 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.secondary_bit_file.empty() ||
|
||||||
|
!args.file_type.empty())
|
||||||
&& args.prg_type != Device::RD_FLASH) {
|
&& args.prg_type != Device::RD_FLASH) {
|
||||||
try {
|
try {
|
||||||
fpga->program(args.offset, args.unprotect_flash);
|
fpga->program(args.offset, args.unprotect_flash);
|
||||||
|
|
@ -691,6 +695,9 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
cxxopts::value<int16_t>(args->altsetting))
|
cxxopts::value<int16_t>(args->altsetting))
|
||||||
("bitstream", "bitstream",
|
("bitstream", "bitstream",
|
||||||
cxxopts::value<std::string>(args->bit_file))
|
cxxopts::value<std::string>(args->bit_file))
|
||||||
|
("secondary-bitstream", "secondary bitstream (some Xilinx"
|
||||||
|
" UltraScale boards)",
|
||||||
|
cxxopts::value<std::string>(args->secondary_bit_file))
|
||||||
("b,board", "board name, may be used instead of cable",
|
("b,board", "board name, may be used instead of cable",
|
||||||
cxxopts::value<string>(args->board))
|
cxxopts::value<string>(args->board))
|
||||||
("B,bridge", "disable spiOverJtag model detection by providing "
|
("B,bridge", "disable spiOverJtag model detection by providing "
|
||||||
|
|
@ -722,8 +729,12 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
("dump-flash", "Dump flash mode")
|
("dump-flash", "Dump flash mode")
|
||||||
("bulk-erase", "Bulk erase flash",
|
("bulk-erase", "Bulk erase flash",
|
||||||
cxxopts::value<bool>(args->bulk_erase_flash))
|
cxxopts::value<bool>(args->bulk_erase_flash))
|
||||||
|
("target-flash",
|
||||||
|
"for boards with multiple flash chips (some Xilinx UltraScale"
|
||||||
|
" boards), select the target flash: primary (default), secondary or both",
|
||||||
|
cxxopts::value<string>(args->target_flash))
|
||||||
("external-flash",
|
("external-flash",
|
||||||
"select ext flash for device with internal and external storage",
|
"select ext flash for device with internal and external storage",
|
||||||
cxxopts::value<bool>(args->external_flash))
|
cxxopts::value<bool>(args->external_flash))
|
||||||
("file-size",
|
("file-size",
|
||||||
"provides size in Byte to dump, must be used with dump-flash",
|
"provides size in Byte to dump, must be used with dump-flash",
|
||||||
|
|
@ -918,11 +929,25 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
args->pin_config = true;
|
args->pin_config = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args->target_flash == "both" || args->target_flash == "secondary") {
|
||||||
|
if ((args->prg_type == Device::WR_FLASH || args->prg_type == Device::RD_FLASH) &&
|
||||||
|
args->secondary_bit_file.empty() &&
|
||||||
|
!args->protect_flash &&
|
||||||
|
!args->unprotect_flash &&
|
||||||
|
!args->bulk_erase_flash
|
||||||
|
) {
|
||||||
|
printError("Error: secondary bitfile not specified");
|
||||||
|
cout << options.help() << endl;
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args->list_cables || args->list_boards || args->list_fpga ||
|
if (args->list_cables || args->list_boards || args->list_fpga ||
|
||||||
args->scan_usb)
|
args->scan_usb)
|
||||||
args->is_list_command = true;
|
args->is_list_command = true;
|
||||||
|
|
||||||
if (args->bit_file.empty() &&
|
if (args->bit_file.empty() &&
|
||||||
|
args->secondary_bit_file.empty() &&
|
||||||
args->file_type.empty() &&
|
args->file_type.empty() &&
|
||||||
!args->is_list_command &&
|
!args->is_list_command &&
|
||||||
!args->detect &&
|
!args->detect &&
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ class SPIInterface {
|
||||||
bool protect_flash(uint32_t len);
|
bool protect_flash(uint32_t len);
|
||||||
bool unprotect_flash();
|
bool unprotect_flash();
|
||||||
bool bulk_erase_flash();
|
bool bulk_erase_flash();
|
||||||
|
void set_filename(const std::string &filename) {_spif_filename = filename;}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief write len byte into flash starting at offset,
|
* \brief write len byte into flash starting at offset,
|
||||||
* optionally verify after write and unprotect
|
* optionally verify after write and unprotect
|
||||||
|
|
|
||||||
169
src/xilinx.cpp
169
src/xilinx.cpp
|
|
@ -20,6 +20,7 @@
|
||||||
#include "rawParser.hpp"
|
#include "rawParser.hpp"
|
||||||
|
|
||||||
#include "display.hpp"
|
#include "display.hpp"
|
||||||
|
#include "spiInterface.hpp"
|
||||||
#include "xilinx.hpp"
|
#include "xilinx.hpp"
|
||||||
#include "xilinxMapParser.hpp"
|
#include "xilinxMapParser.hpp"
|
||||||
#include "part.hpp"
|
#include "part.hpp"
|
||||||
|
|
@ -98,15 +99,40 @@ static uint8_t *get_ircode(
|
||||||
return inst_map.at(inst).data();
|
return inst_map.at(inst).data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void open_bitfile(
|
||||||
|
const std::string &filename, const std::string &extension,
|
||||||
|
ConfigBitstreamParser **parser, bool reverse, bool verbose)
|
||||||
|
{
|
||||||
|
printInfo("Open file ", false);
|
||||||
|
if (extension == "bit") {
|
||||||
|
*parser = new BitParser(filename, reverse, verbose);
|
||||||
|
} else if (extension == "mcs") {
|
||||||
|
*parser = new McsParser(filename, reverse, verbose);
|
||||||
|
} else {
|
||||||
|
*parser = new RawParser(filename, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
printSuccess("DONE");
|
||||||
|
|
||||||
|
printInfo("Parse file ", false);
|
||||||
|
if ((*parser)->parse() == EXIT_FAILURE) {
|
||||||
|
throw std::runtime_error("Failed to parse bitstream");
|
||||||
|
}
|
||||||
|
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
||||||
|
const std::string &secondary_filename,
|
||||||
const std::string &file_type,
|
const std::string &file_type,
|
||||||
Device::prog_type_t prg_type,
|
Device::prog_type_t prg_type,
|
||||||
const std::string &device_package, const std::string &spiOverJtagPath,
|
const std::string &device_package, const std::string &spiOverJtagPath,
|
||||||
|
const std::string &target_flash,
|
||||||
bool verify, int8_t verbose):
|
bool verify, int8_t verbose):
|
||||||
Device(jtag, filename, file_type, verify, verbose),
|
Device(jtag, filename, file_type, verify, verbose),
|
||||||
SPIInterface(filename, verbose, 256, verify),
|
SPIInterface(filename, verbose, 256, verify),
|
||||||
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
||||||
_irlen(6)
|
_irlen(6), _filename(filename), _secondary_filename(secondary_filename)
|
||||||
{
|
{
|
||||||
if (prg_type == Device::RD_FLASH) {
|
if (prg_type == Device::RD_FLASH) {
|
||||||
_mode = Device::READ_MODE;
|
_mode = Device::READ_MODE;
|
||||||
|
|
@ -125,7 +151,23 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_user_instruction = "USER1";
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
|
||||||
|
if (target_flash == "primary") {
|
||||||
|
_flash_chips = PRIMARY_FLASH;
|
||||||
|
} else if (target_flash == "secondary") {
|
||||||
|
_flash_chips = SECONDARY_FLASH;
|
||||||
|
} else if (target_flash == "both") {
|
||||||
|
_flash_chips = (PRIMARY_FLASH | SECONDARY_FLASH);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Error: unknown flash target: " + target_flash);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
_secondary_file_extension = secondary_filename.substr(
|
||||||
|
secondary_filename.find_last_of(".") + 1);
|
||||||
|
_mode = Device::SPI_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t idcode = _jtag->get_target_device_id();
|
uint32_t idcode = _jtag->get_target_device_id();
|
||||||
std::string family = fpga_list[idcode].family;
|
std::string family = fpga_list[idcode].family;
|
||||||
|
|
@ -299,7 +341,8 @@ int Xilinx::idCode()
|
||||||
|
|
||||||
void Xilinx::program(unsigned int offset, bool unprotect_flash)
|
void Xilinx::program(unsigned int offset, bool unprotect_flash)
|
||||||
{
|
{
|
||||||
ConfigBitstreamParser *bit;
|
ConfigBitstreamParser *bit = nullptr;
|
||||||
|
ConfigBitstreamParser *secondary_bit = nullptr;
|
||||||
bool reverse = false;
|
bool reverse = false;
|
||||||
|
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
|
|
@ -334,33 +377,30 @@ void Xilinx::program(unsigned int offset, bool unprotect_flash)
|
||||||
if (_mode == Device::MEM_MODE || _fpga_family == XCF_FAMILY)
|
if (_mode == Device::MEM_MODE || _fpga_family == XCF_FAMILY)
|
||||||
reverse = true;
|
reverse = true;
|
||||||
|
|
||||||
printInfo("Open file ", false);
|
|
||||||
try {
|
try {
|
||||||
if (_file_extension == "bit")
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
bit = new BitParser(_filename, reverse, _verbose);
|
open_bitfile(_filename, _file_extension, &bit, reverse, _verbose);
|
||||||
else if (_file_extension == "mcs")
|
}
|
||||||
bit = new McsParser(_filename, reverse, _verbose);
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
else
|
open_bitfile(_secondary_filename, _secondary_file_extension,
|
||||||
bit = new RawParser(_filename, reverse);
|
&secondary_bit, reverse, _verbose);
|
||||||
|
}
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
|
if (bit)
|
||||||
|
delete bit;
|
||||||
|
if (secondary_bit)
|
||||||
|
delete secondary_bit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printSuccess("DONE");
|
if (_verbose) {
|
||||||
|
if (bit)
|
||||||
printInfo("Parse file ", false);
|
bit->displayHeader();
|
||||||
if (bit->parse() == EXIT_FAILURE) {
|
if (secondary_bit)
|
||||||
printError("FAIL");
|
secondary_bit->displayHeader();
|
||||||
delete bit;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
printSuccess("DONE");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_verbose)
|
|
||||||
bit->displayHeader();
|
|
||||||
|
|
||||||
if (_fpga_family == XCF_FAMILY) {
|
if (_fpga_family == XCF_FAMILY) {
|
||||||
xcf_program(bit);
|
xcf_program(bit);
|
||||||
delete bit;
|
delete bit;
|
||||||
|
|
@ -368,7 +408,17 @@ void Xilinx::program(unsigned int offset, bool unprotect_flash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mode == Device::SPI_MODE) {
|
if (_mode == Device::SPI_MODE) {
|
||||||
program_spi(bit, offset, unprotect_flash);
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
program_spi(bit, offset, unprotect_flash);
|
||||||
|
}
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
select_flash_chip(SECONDARY_FLASH);
|
||||||
|
program_spi(secondary_bit, offset, unprotect_flash);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (_fpga_family == SPARTAN3_FAMILY)
|
if (_fpga_family == SPARTAN3_FAMILY)
|
||||||
xc3s_flow_program(bit);
|
xc3s_flow_program(bit);
|
||||||
|
|
@ -570,8 +620,65 @@ bool Xilinx::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump SPI Flash */
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
return SPIInterface::dump(base_addr, len);
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
SPIInterface::set_filename(_filename);
|
||||||
|
if (!SPIInterface::dump(base_addr, len))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
select_flash_chip(SECONDARY_FLASH);
|
||||||
|
SPIInterface::set_filename(_secondary_filename);
|
||||||
|
if (!SPIInterface::dump(base_addr, len))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Xilinx::protect_flash(uint32_t len)
|
||||||
|
{
|
||||||
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
if (!SPIInterface::protect_flash(len))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
select_flash_chip(SECONDARY_FLASH);
|
||||||
|
if (!SPIInterface::protect_flash(len))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Xilinx::unprotect_flash()
|
||||||
|
{
|
||||||
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
if (!SPIInterface::unprotect_flash())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
select_flash_chip(SECONDARY_FLASH);
|
||||||
|
if (!SPIInterface::unprotect_flash())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Xilinx::bulk_erase_flash()
|
||||||
|
{
|
||||||
|
if (_flash_chips & PRIMARY_FLASH) {
|
||||||
|
select_flash_chip(PRIMARY_FLASH);
|
||||||
|
if (!SPIInterface::bulk_erase_flash())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_flash_chips & SECONDARY_FLASH) {
|
||||||
|
select_flash_chip(SECONDARY_FLASH);
|
||||||
|
if (!SPIInterface::bulk_erase_flash())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flow program for xc3s (legacy mode) */
|
/* flow program for xc3s (legacy mode) */
|
||||||
|
|
@ -1460,3 +1567,15 @@ int Xilinx::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Xilinx::select_flash_chip(xilinx_flash_chip_t flash_chip) {
|
||||||
|
switch (flash_chip) {
|
||||||
|
case SECONDARY_FLASH:
|
||||||
|
_user_instruction = "USER2";
|
||||||
|
break;
|
||||||
|
case PRIMARY_FLASH:
|
||||||
|
default:
|
||||||
|
_user_instruction = "USER1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,17 @@
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
#include "spiInterface.hpp"
|
#include "spiInterface.hpp"
|
||||||
|
#include "jedParser.hpp"
|
||||||
|
|
||||||
class Xilinx: public Device, SPIInterface {
|
class Xilinx: public Device, SPIInterface {
|
||||||
public:
|
public:
|
||||||
Xilinx(Jtag *jtag, const std::string &filename,
|
Xilinx(Jtag *jtag, const std::string &filename,
|
||||||
|
const std::string &secondary_filename,
|
||||||
const std::string &file_type,
|
const std::string &file_type,
|
||||||
Device::prog_type_t prg_type,
|
Device::prog_type_t prg_type,
|
||||||
const std::string &device_package,
|
const std::string &device_package,
|
||||||
const std::string &spiOverJtagPath,
|
const std::string &spiOverJtagPath,
|
||||||
|
const std::string &target_flash,
|
||||||
bool verify, int8_t verbose);
|
bool verify, int8_t verbose);
|
||||||
~Xilinx();
|
~Xilinx();
|
||||||
|
|
||||||
|
|
@ -32,21 +35,15 @@ class Xilinx: public Device, SPIInterface {
|
||||||
/*!
|
/*!
|
||||||
* \brief protect SPI flash blocks
|
* \brief protect SPI flash blocks
|
||||||
*/
|
*/
|
||||||
bool protect_flash(uint32_t len) override {
|
bool protect_flash(uint32_t len) override;
|
||||||
return SPIInterface::protect_flash(len);
|
|
||||||
}
|
|
||||||
/*!
|
/*!
|
||||||
* \brief unprotect SPI flash blocks
|
* \brief unprotect SPI flash blocks
|
||||||
*/
|
*/
|
||||||
bool unprotect_flash() override {
|
bool unprotect_flash() override;
|
||||||
return SPIInterface::unprotect_flash();
|
|
||||||
}
|
|
||||||
/*!
|
/*!
|
||||||
* \brief erase SPI flash blocks
|
* \brief erase SPI flash blocks
|
||||||
*/
|
*/
|
||||||
bool bulk_erase_flash() override {
|
bool bulk_erase_flash() override;
|
||||||
return SPIInterface::bulk_erase_flash();
|
|
||||||
}
|
|
||||||
|
|
||||||
int idCode() override;
|
int idCode() override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
@ -185,6 +182,20 @@ class Xilinx: public Device, SPIInterface {
|
||||||
* \return false if missing device mode, true otherwise
|
* \return false if missing device mode, true otherwise
|
||||||
*/
|
*/
|
||||||
bool load_bridge();
|
bool load_bridge();
|
||||||
|
|
||||||
|
enum xilinx_flash_chip_t {
|
||||||
|
PRIMARY_FLASH = 0x1,
|
||||||
|
SECONDARY_FLASH = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Starting from UltraScale, Xilinx devices can support dual
|
||||||
|
* QSPI flash configuration, with two different flash chips
|
||||||
|
* on the board. Target the selected one via the bridge by
|
||||||
|
* chaging the USER instruction to use.
|
||||||
|
*/
|
||||||
|
void select_flash_chip(xilinx_flash_chip_t flash_chip);
|
||||||
|
|
||||||
std::string _device_package;
|
std::string _device_package;
|
||||||
std::string _spiOverJtagPath; /**< spiOverJtag explicit path */
|
std::string _spiOverJtagPath; /**< spiOverJtag explicit path */
|
||||||
int _xc95_line_len; /**< xc95 only: number of col by flash line */
|
int _xc95_line_len; /**< xc95 only: number of col by flash line */
|
||||||
|
|
@ -194,6 +205,10 @@ class Xilinx: public Device, SPIInterface {
|
||||||
char _cpld_base_name[7]; /**< cpld name (without package size) */
|
char _cpld_base_name[7]; /**< cpld name (without package size) */
|
||||||
int _irlen; /**< IR bit length */
|
int _irlen; /**< IR bit length */
|
||||||
std::map<std::string, std::vector<uint8_t>> _ircode_map; /**< bscan instructions based on model */
|
std::map<std::string, std::vector<uint8_t>> _ircode_map; /**< bscan instructions based on model */
|
||||||
|
std::string _filename; /* path to the primary flash file */
|
||||||
|
std::string _secondary_filename; /* path to the secondary flash file (SPIx8) */
|
||||||
|
std::string _secondary_file_extension; /* file type for the secondary flash file */
|
||||||
|
int _flash_chips; /* bitfield to select the target in boards with two flash chips */
|
||||||
std::string _user_instruction; /* which USER bscan instruction to interface with SPI */
|
std::string _user_instruction; /* which USER bscan instruction to interface with SPI */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue