all devices: add support to (un)protect flash, implement pre/post flash access. Use new spiInterface methods
This commit is contained in:
parent
af14e9b518
commit
45f7f72030
|
|
@ -26,8 +26,9 @@
|
|||
Altera::Altera(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
const std::string &device_package, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose), _svf(_jtag, _verbose),
|
||||
_device_package(device_package),
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 256, verify),
|
||||
_svf(_jtag, _verbose), _device_package(device_package),
|
||||
_vir_addr(0x1000), _vir_length(14)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
|
|
@ -177,7 +178,7 @@ bool Altera::load_bridge()
|
|||
return true;
|
||||
}
|
||||
|
||||
void Altera::program(unsigned int offset)
|
||||
void Altera::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
if (_mode == Device::NONE_MODE)
|
||||
return;
|
||||
|
|
@ -197,14 +198,6 @@ void Altera::program(unsigned int offset)
|
|||
programMem(_bit);
|
||||
}
|
||||
} else if (_mode == Device::SPI_MODE) {
|
||||
/* try to load spiOverJtag bridge
|
||||
* to have an access to SPI flash
|
||||
*/
|
||||
if (!load_bridge()) {
|
||||
printError("Fail to load bridge");
|
||||
return;
|
||||
}
|
||||
|
||||
// reverse only bitstream raw binaries data no
|
||||
bool reverseOrder = false;
|
||||
if (_file_extension == "rbf" || _file_extension == "rpd")
|
||||
|
|
@ -224,51 +217,11 @@ void Altera::program(unsigned int offset)
|
|||
throw std::runtime_error(e.what());
|
||||
}
|
||||
|
||||
/* GGM: TODO: fix this issue */
|
||||
EPCQ epcq(this, 0);
|
||||
|
||||
try {
|
||||
epcq.reset();
|
||||
epcq.read_id();
|
||||
epcq.display_status_reg(epcq.read_status_reg());
|
||||
epcq.erase_and_prog(offset, data, length);
|
||||
} catch (std::exception &e) {
|
||||
printError(e.what());
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
|
||||
if (_verify)
|
||||
epcq.verify(offset, data, length, 256);
|
||||
reset();
|
||||
if (!SPIInterface::write(offset, data, length, unprotect_flash))
|
||||
throw std::runtime_error("Fail to write data");
|
||||
}
|
||||
}
|
||||
|
||||
bool Altera::dumpFlash(const std::string filename, uint32_t base_addr,
|
||||
uint32_t len)
|
||||
{
|
||||
int ret = true;
|
||||
/* try to load spiOverJtag bridge
|
||||
* to have an access to SPI flash
|
||||
*/
|
||||
if (!load_bridge()) {
|
||||
printError("Fail to load bridge");
|
||||
return false;
|
||||
}
|
||||
|
||||
EPCQ epcq(this, 0);
|
||||
|
||||
try {
|
||||
epcq.reset();
|
||||
ret = epcq.dump(filename, base_addr, len, 256);
|
||||
} catch (std::exception &e) {
|
||||
printError(e.what());
|
||||
ret = false;
|
||||
}
|
||||
|
||||
reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Altera::idCode()
|
||||
{
|
||||
unsigned char tx_data[4] = {IDCODE};
|
||||
|
|
@ -308,7 +261,7 @@ int Altera::spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint32_t len)
|
|||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
int Altera::spi_put(uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Altera: public Device, SPIInterface {
|
|||
~Altera();
|
||||
|
||||
void programMem(RawParser &_bit);
|
||||
void program(unsigned int offset = 0) override;
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
/*!
|
||||
* \brief read len Byte starting at base_addr and store
|
||||
* into filename
|
||||
|
|
@ -33,18 +33,40 @@ class Altera: public Device, SPIInterface {
|
|||
* \param[in] len: length (in Byte)
|
||||
* \return false if read fails or filename can't be open, true otherwise
|
||||
*/
|
||||
bool dumpFlash(const std::string filename, uint32_t base_addr,
|
||||
uint32_t len);
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len) override {
|
||||
return SPIInterface::dump(base_addr, len);
|
||||
}
|
||||
|
||||
int idCode() override;
|
||||
void reset() override;
|
||||
|
||||
/* spi interface */
|
||||
/*************************/
|
||||
/* spi interface */
|
||||
/*************************/
|
||||
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool protect_flash(uint32_t len) override {
|
||||
return SPIInterface::protect_flash(len);
|
||||
}
|
||||
/*!
|
||||
* \brief unprotect SPI flash blocks
|
||||
*/
|
||||
bool unprotect_flash() override {
|
||||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) override;
|
||||
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose = false) override;
|
||||
|
||||
protected:
|
||||
bool prepare_flash_access() override {return load_bridge();}
|
||||
bool post_flash_access() override {reset(); return true;}
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \brief with intel devices SPI flash direct access is not possible
|
||||
|
|
|
|||
|
|
@ -28,18 +28,23 @@
|
|||
Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose), _svf(_jtag, _verbose)
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 0, verify), _svf(_jtag, _verbose)
|
||||
{
|
||||
if (!_file_extension.empty()) {
|
||||
if (_file_extension == "svf")
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
_mode = Device::READ_MODE;
|
||||
} else if (!_file_extension.empty()) {
|
||||
if (_file_extension == "svf") {
|
||||
_mode = Device::MEM_MODE;
|
||||
else if (_file_extension == "bit") {
|
||||
if (prg_type == Device::WR_SRAM)
|
||||
_mode = Device::MEM_MODE;
|
||||
else
|
||||
} else if (_file_extension == "bit") {
|
||||
_mode = (prg_type == Device::WR_SRAM)? Device::MEM_MODE:
|
||||
Device::SPI_MODE;
|
||||
} else {
|
||||
if (prg_type == Device::WR_FLASH)
|
||||
_mode = Device::SPI_MODE;
|
||||
} else
|
||||
throw std::runtime_error("incompatible file format");
|
||||
else
|
||||
throw std::runtime_error("incompatible file format");
|
||||
}
|
||||
}
|
||||
}
|
||||
Anlogic::~Anlogic()
|
||||
|
|
@ -54,7 +59,7 @@ void Anlogic::reset()
|
|||
_jtag->toggleClk(200000);
|
||||
}
|
||||
|
||||
void Anlogic::program(unsigned int offset)
|
||||
void Anlogic::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
if (_mode == Device::NONE_MODE)
|
||||
return;
|
||||
|
|
@ -70,10 +75,10 @@ void Anlogic::program(unsigned int offset)
|
|||
if (bit.parse() == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
return;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
printSuccess("DONE");
|
||||
|
||||
if (_verbose)
|
||||
bit.displayHeader();
|
||||
|
||||
|
|
@ -81,47 +86,10 @@ void Anlogic::program(unsigned int offset)
|
|||
int len = bit.getLength() / 8;
|
||||
|
||||
if (_mode == Device::SPI_MODE) {
|
||||
SPIFlash flash(this, _verbose);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
//Verify Device id.
|
||||
//SIR 8 TDI (06) ;
|
||||
//SDR 32 TDI (00000000) TDO (0a014c35) MASK (ffffffff) ;
|
||||
//Boundary Scan Chain Contents
|
||||
//Position 1: BG256
|
||||
//Loading device with 'refresh' instruction.
|
||||
_jtag->shiftIR(REFRESH, IRLENGTH);
|
||||
//Loading device with 'bypass' & 'spi_program' instruction.
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
_jtag->shiftIR(SPI_PROGRAM, IRLENGTH);
|
||||
for (int i = 0; i < 4; i++)
|
||||
_jtag->toggleClk(50000);
|
||||
|
||||
flash.reset();
|
||||
flash.read_id();
|
||||
flash.display_status_reg(flash.read_status_reg());
|
||||
|
||||
flash.erase_and_prog(offset, data, len);
|
||||
|
||||
if (_verify)
|
||||
printWarn("writing verification not supported");
|
||||
|
||||
//Loading device with 'bypass' instruction.
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
////Loading device with 'refresh' instruction.
|
||||
_jtag->shiftIR(REFRESH, IRLENGTH);
|
||||
_jtag->toggleClk(20);
|
||||
////Loading device with 'bypass' instruction.
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
_jtag->toggleClk(20);
|
||||
}
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
_jtag->toggleClk(10000);
|
||||
|
||||
SPIInterface::write(offset, data, len, unprotect_flash);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mode == Device::MEM_MODE) {
|
||||
|
||||
// Loading device with 'bypass' instruction.
|
||||
|
|
@ -196,6 +164,25 @@ int Anlogic::idCode()
|
|||
((rx_data[3] << 24) & 0xff000000));
|
||||
}
|
||||
|
||||
bool Anlogic::prepare_flash_access()
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
//Verify Device id.
|
||||
//SIR 8 TDI (06) ;
|
||||
//SDR 32 TDI (00000000) TDO (0a014c35) MASK (ffffffff) ;
|
||||
//Boundary Scan Chain Contents
|
||||
//Position 1: BG256
|
||||
//Loading device with 'refresh' instruction.
|
||||
_jtag->shiftIR(REFRESH, IRLENGTH);
|
||||
//Loading device with 'bypass' & 'spi_program' instruction.
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
_jtag->shiftIR(SPI_PROGRAM, IRLENGTH);
|
||||
for (int i = 0; i < 4; i++)
|
||||
_jtag->toggleClk(50000);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SPI wrapper
|
||||
* For read operation a delay of one bit is added
|
||||
* So add one bit more and move everything by one
|
||||
|
|
|
|||
|
|
@ -21,16 +21,51 @@ class Anlogic: public Device, SPIInterface {
|
|||
Device::prog_type_t prg_type, bool verify, int8_t verbose);
|
||||
~Anlogic();
|
||||
|
||||
void program(unsigned int offset = 0) override;
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
int idCode() override;
|
||||
void reset() override;
|
||||
|
||||
/* spi interface */
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool protect_flash(uint32_t len) override {
|
||||
return SPIInterface::protect_flash(len);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool unprotect_flash() override {
|
||||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief dump len byte from base_addr from SPI flash
|
||||
* \param[in] base_addr: start offset
|
||||
* \param[in] len: dump len
|
||||
* \return false if something wrong
|
||||
*/
|
||||
virtual bool dumpFlash(uint32_t base_addr, uint32_t len) override {
|
||||
return SPIInterface::dump(base_addr, len);
|
||||
}
|
||||
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) override;
|
||||
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose=false) override;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief move device to SPI access
|
||||
*/
|
||||
virtual bool prepare_flash_access() override;
|
||||
/*!
|
||||
* \brief end of device to SPI access
|
||||
*/
|
||||
virtual bool post_flash_access() override {reset(); return true;}
|
||||
|
||||
private:
|
||||
SVF_jtag _svf;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -136,9 +136,10 @@ bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
|
|||
try {
|
||||
SPIFlash *flash;
|
||||
if (_spi) {
|
||||
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), _verbose);
|
||||
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false,
|
||||
_verbose);
|
||||
} else if (_ftdi_jtag) {
|
||||
flash = new SPIFlash(this, _verbose);
|
||||
flash = new SPIFlash(this, false, _verbose);
|
||||
}
|
||||
flash->reset();
|
||||
flash->power_up();
|
||||
|
|
@ -165,7 +166,7 @@ bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
|
|||
* Parse bitstream from *.bit or *.cfg and program FPGA in SPI or JTAG mode
|
||||
* or write configuration to external flash via SPI or JTAG-SPI-bypass.
|
||||
*/
|
||||
void CologneChip::program(unsigned int offset)
|
||||
void CologneChip::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
ConfigBitstreamParser *cfg;
|
||||
if (_file_extension == "cfg") {
|
||||
|
|
@ -188,9 +189,9 @@ void CologneChip::program(unsigned int offset)
|
|||
switch (_mode) {
|
||||
case Device::FLASH_MODE:
|
||||
if (_jtag != NULL) {
|
||||
programJTAG_flash(offset, data, length);
|
||||
programJTAG_flash(offset, data, length, unprotect_flash);
|
||||
} else if (_jtag == NULL) {
|
||||
programSPI_flash(offset, data, length);
|
||||
programSPI_flash(offset, data, length, unprotect_flash);
|
||||
}
|
||||
break;
|
||||
case Device::MEM_MODE:
|
||||
|
|
@ -227,13 +228,15 @@ void CologneChip::programSPI_sram(uint8_t *data, int length)
|
|||
* done, release reset to start FPGA in active SPI mode (load from flash).
|
||||
* CFG_MD[3:0] must be set to 0x00 (SPI active).
|
||||
*/
|
||||
void CologneChip::programSPI_flash(unsigned int offset, uint8_t *data, int length)
|
||||
void CologneChip::programSPI_flash(unsigned int offset, uint8_t *data,
|
||||
int length, bool unprotect_flash)
|
||||
{
|
||||
/* hold device in reset during flash write access */
|
||||
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
||||
usleep(SLEEP_US);
|
||||
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), _verbose);
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
|
||||
_verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
|
||||
|
|
@ -294,12 +297,13 @@ void CologneChip::programJTAG_sram(uint8_t *data, int length)
|
|||
* Write configuration to flash via JTAG-SPI-bypass. The FPGA will not start
|
||||
* as it is in JTAG mode with CFG_MD[3:0] set to 0xF0 (JTAG).
|
||||
*/
|
||||
void CologneChip::programJTAG_flash(unsigned int offset, uint8_t *data, int length)
|
||||
void CologneChip::programJTAG_flash(unsigned int offset, uint8_t *data,
|
||||
int length, bool unprotect_flash)
|
||||
{
|
||||
/* hold device in reset for a moment */
|
||||
reset();
|
||||
|
||||
SPIFlash flash(this, _verbose);
|
||||
SPIFlash flash(this, unprotect_flash, _verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,16 +35,23 @@ class CologneChip: public Device, SPIInterface {
|
|||
bool cfgDone();
|
||||
void waitCfgDone();
|
||||
bool dumpFlash(const std::string &filename, uint32_t base_addr, uint32_t len);
|
||||
void program(unsigned int offset = 0) override;
|
||||
virtual bool protect_flash(uint32_t len) override {
|
||||
(void) len;
|
||||
printError("protect flash not supported"); return false;}
|
||||
virtual bool unprotect_flash() override {
|
||||
printError("unprotect flash not supported"); return false;}
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
|
||||
int idCode() override {return 0;}
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
void programSPI_sram(uint8_t *data, int length);
|
||||
void programSPI_flash(unsigned int offset, uint8_t *data, int length);
|
||||
void programSPI_flash(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash);
|
||||
void programJTAG_sram(uint8_t *data, int length);
|
||||
void programJTAG_flash(unsigned int offset, uint8_t *data, int length);
|
||||
void programJTAG_flash(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash);
|
||||
|
||||
/* spi interface via jtag */
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ void Efinix::reset()
|
|||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
void Efinix::program(unsigned int offset)
|
||||
void Efinix::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
if (_file_extension.empty())
|
||||
return;
|
||||
|
|
@ -140,7 +140,7 @@ void Efinix::program(unsigned int offset)
|
|||
if (_ftdi_jtag)
|
||||
programJTAG(data, length);
|
||||
else
|
||||
programSPI(offset, data, length);
|
||||
programSPI(offset, data, length, unprotect_flash);
|
||||
}
|
||||
|
||||
bool Efinix::dumpFlash(const std::string &filename,
|
||||
|
|
@ -152,7 +152,7 @@ bool Efinix::dumpFlash(const std::string &filename,
|
|||
/* prepare SPI access */
|
||||
printInfo("Read Flash ", false);
|
||||
try {
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), _verbose);
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
flash.dump(filename, base_addr, len);
|
||||
|
|
@ -179,13 +179,15 @@ bool Efinix::dumpFlash(const std::string &filename,
|
|||
return false;
|
||||
}
|
||||
|
||||
void Efinix::programSPI(unsigned int offset, uint8_t *data, int length)
|
||||
void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash)
|
||||
{
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
_spi->gpio_clear(_rst_pin | _oe_pin);
|
||||
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), _verbose);
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
|
||||
_verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
|
||||
|
|
|
|||
|
|
@ -25,15 +25,21 @@ class Efinix: public Device {
|
|||
bool verify, int8_t verbose);
|
||||
~Efinix();
|
||||
|
||||
void program(unsigned int offset = 0) override;
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len);
|
||||
virtual bool protect_flash(uint32_t len) override {
|
||||
(void) len;
|
||||
printError("protect flash not supported"); return false;}
|
||||
virtual bool unprotect_flash() override {
|
||||
printError("unprotect flash not supported"); return false;}
|
||||
/* not supported in SPI Active mode */
|
||||
int idCode() override {return 0;}
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
void programSPI(unsigned int offset, uint8_t *data, int length);
|
||||
void programSPI(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash);
|
||||
void programJTAG(uint8_t *data, int length);
|
||||
FtdiSpi *_spi;
|
||||
FtdiJtagMPSSE *_ftdi_jtag;
|
||||
|
|
|
|||
11
src/epcq.cpp
11
src/epcq.cpp
|
|
@ -62,8 +62,15 @@ void EPCQ::read_id()
|
|||
printf("silicon id 0x%x attendu 0x14\n", _silicon_id);
|
||||
}
|
||||
|
||||
EPCQ::EPCQ(SPIInterface *spi, int8_t verbose):SPIFlash(spi, verbose),
|
||||
_device_id(0), _silicon_id(0)
|
||||
void EPCQ::reset()
|
||||
{
|
||||
printf("reset\n");
|
||||
_spi->spi_put(0x66, NULL, NULL, 0);
|
||||
_spi->spi_put(0x99, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
EPCQ::EPCQ(SPIInterface *spi, bool unprotect_flash, int8_t verbose):
|
||||
SPIFlash(spi, unprotect_flash, verbose), _device_id(0), _silicon_id(0)
|
||||
{}
|
||||
|
||||
EPCQ::~EPCQ()
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@ using namespace std;
|
|||
|
||||
class EPCQ: public SPIFlash {
|
||||
public:
|
||||
EPCQ(SPIInterface *spi, int8_t verbose);
|
||||
EPCQ(SPIInterface *spi, bool unprotect_flash, int8_t verbose);
|
||||
~EPCQ();
|
||||
|
||||
void read_id() override;
|
||||
|
||||
void reset() override;
|
||||
|
||||
/* not supported */
|
||||
void power_up() override {}
|
||||
void power_down() override {}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ void Gowin::programFlash()
|
|||
displayReadReg(readStatusReg());
|
||||
}
|
||||
|
||||
void Gowin::program(unsigned int offset)
|
||||
void Gowin::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
(void) offset;
|
||||
|
||||
|
|
@ -235,7 +235,8 @@ void Gowin::program(unsigned int offset)
|
|||
|
||||
wr_rd(0x3D, NULL, 0, NULL, 0);
|
||||
|
||||
SPIFlash spiFlash(this, (_verbose ? 1 : (_quiet ? -1 : 0)));
|
||||
SPIFlash spiFlash(this, unprotect_flash,
|
||||
(_verbose ? 1 : (_quiet ? -1 : 0)));
|
||||
spiFlash.reset();
|
||||
spiFlash.read_id();
|
||||
spiFlash.display_status_reg(spiFlash.read_status_reg());
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ class Gowin: public Device, SPIInterface {
|
|||
~Gowin();
|
||||
int idCode() override;
|
||||
void reset() override;
|
||||
void program(unsigned int offset) override;
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
void programFlash();
|
||||
|
||||
/* spi interface */
|
||||
virtual bool protect_flash(uint32_t len) override {
|
||||
(void) len;
|
||||
printError("protect flash not supported"); return false;}
|
||||
virtual bool unprotect_flash() override {
|
||||
printError("unprotect flash not supported"); return false;}
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) override;
|
||||
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||
|
|
|
|||
|
|
@ -40,17 +40,18 @@ void Ice40::reset()
|
|||
usleep(1000);
|
||||
_spi->gpio_set(_rst_pin);
|
||||
printInfo("Reset ", false);
|
||||
usleep(12000);
|
||||
do {
|
||||
timeout--;
|
||||
usleep(12000);
|
||||
} while (((_spi->gpio_get(true) & _done_pin) == 0) || timeout > 0);
|
||||
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
|
||||
if (timeout == 0)
|
||||
printError("FAIL");
|
||||
else
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
void Ice40::program(unsigned int offset)
|
||||
void Ice40::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
|
|
@ -72,7 +73,8 @@ void Ice40::program(unsigned int offset)
|
|||
|
||||
_spi->gpio_clear(_rst_pin);
|
||||
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), _quiet);
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
|
||||
_quiet);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
|
||||
|
|
@ -97,8 +99,7 @@ void Ice40::program(unsigned int offset)
|
|||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
bool Ice40::dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len)
|
||||
bool Ice40::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||
{
|
||||
uint32_t timeout = 1000;
|
||||
_spi->gpio_clear(_rst_pin);
|
||||
|
|
@ -106,10 +107,10 @@ bool Ice40::dumpFlash(const std::string &filename,
|
|||
/* prepare SPI access */
|
||||
printInfo("Read Flash ", false);
|
||||
try {
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), _verbose);
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
flash.dump(filename, base_addr, len);
|
||||
flash.dump(_filename, base_addr, len);
|
||||
} catch (std::exception &e) {
|
||||
printError("Fail");
|
||||
printError(std::string(e.what()));
|
||||
|
|
@ -133,3 +134,57 @@ bool Ice40::dumpFlash(const std::string &filename,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ice40::protect_flash(uint32_t len)
|
||||
{
|
||||
/* SPI access */
|
||||
prepare_flash_access();
|
||||
/* acess */
|
||||
try {
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||
/* configure flash protection */
|
||||
if (flash.enable_protection(len) == -1)
|
||||
return false;
|
||||
} catch (std::exception &e) {
|
||||
printError("Fail");
|
||||
printError(std::string(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* reload */
|
||||
return post_flash_access();
|
||||
}
|
||||
|
||||
bool Ice40::unprotect_flash()
|
||||
{
|
||||
/* SPI access */
|
||||
prepare_flash_access();
|
||||
/* acess */
|
||||
try {
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||
/* configure flash protection */
|
||||
if (flash.disable_protection() == -1)
|
||||
return false;
|
||||
} catch (std::exception &e) {
|
||||
printError("Fail");
|
||||
printError(std::string(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* reload */
|
||||
return post_flash_access();
|
||||
}
|
||||
|
||||
bool Ice40::prepare_flash_access()
|
||||
{
|
||||
/* SPI access: shutdown ICE40 */
|
||||
_spi->gpio_clear(_rst_pin);
|
||||
usleep(1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ice40::post_flash_access()
|
||||
{
|
||||
reset();
|
||||
return ((_spi->gpio_get(true) & _done_pin) == 0) ? false : true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
#include "device.hpp"
|
||||
#include "ftdispi.hpp"
|
||||
#include "spiInterface.hpp"
|
||||
|
||||
class Ice40: public Device {
|
||||
class Ice40: public Device, SPIInterface {
|
||||
public:
|
||||
Ice40(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
|
|
@ -19,13 +20,39 @@ class Ice40: public Device {
|
|||
bool verify, int8_t verbose);
|
||||
~Ice40();
|
||||
|
||||
void program(unsigned int offset = 0) override;
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len);
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len);
|
||||
bool protect_flash(uint32_t len) override;
|
||||
bool unprotect_flash() override;
|
||||
/* not supported in SPI Active mode */
|
||||
int idCode() override {return 0;}
|
||||
void reset() override;
|
||||
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) {
|
||||
(void)cmd; (void)tx; (void)rx; (void)len;
|
||||
return 0;
|
||||
}
|
||||
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) {
|
||||
(void)tx; (void)rx; (void)len;
|
||||
return 0;
|
||||
}
|
||||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose = false) {
|
||||
(void)cmd; (void)mask; (void)cond; (void)timeout; (void) verbose;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief prepare SPI flash access
|
||||
*/
|
||||
bool prepare_flash_access() override;
|
||||
/*!
|
||||
* \brief end of SPI flash access
|
||||
*/
|
||||
bool post_flash_access() override;
|
||||
|
||||
private:
|
||||
FtdiSpi *_spi;
|
||||
uint16_t _rst_pin;
|
||||
|
|
|
|||
246
src/lattice.cpp
246
src/lattice.cpp
|
|
@ -139,6 +139,7 @@ using namespace std;
|
|||
Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
|
||||
Device::prog_type_t prg_type, std::string flash_sector, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 0, verify),
|
||||
_fpga_family(UNKNOWN_FAMILY), _flash_sector(LATTICE_FLASH_UNDEFINED)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
|
|
@ -512,46 +513,11 @@ bool Lattice::program_intFlash(JedParser& _jed)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::program_extFlash(unsigned int offset)
|
||||
bool Lattice::prepare_flash_access()
|
||||
{
|
||||
ConfigBitstreamParser *_bit;
|
||||
if (_file_extension == "mcs")
|
||||
_bit = new McsParser(_filename, true, _verbose);
|
||||
else if (_file_extension == "bit")
|
||||
_bit = new LatticeBitParser(_filename, _verbose);
|
||||
else
|
||||
_bit = new RawParser(_filename, false);
|
||||
|
||||
printInfo("Open file ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
int err = _bit->parse();
|
||||
|
||||
printInfo("Parse file ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
delete _bit;
|
||||
/* clear SRAM before SPI access */
|
||||
if (!clearSRAM())
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
if (_verbose)
|
||||
_bit->displayHeader();
|
||||
|
||||
if (_file_extension == "bit") {
|
||||
uint32_t bit_idcode = std::stoul(_bit->getHeaderVal("idcode").c_str(), NULL, 16);
|
||||
uint32_t idcode = idCode();
|
||||
if (idcode != bit_idcode) {
|
||||
char mess[256];
|
||||
sprintf(mess, "mismatch between target's idcode and bitstream idcode\n"
|
||||
"\tbitstream has 0x%08X hardware requires 0x%08x", bit_idcode, idcode);
|
||||
printError(mess);
|
||||
delete _bit;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*IR = 0h3A, DR=0hFE,0h68. Enter RUNTESTIDLE.
|
||||
* thank @GregDavill
|
||||
* https://twitter.com/GregDavill/status/1251786406441086977
|
||||
|
|
@ -559,35 +525,31 @@ bool Lattice::program_extFlash(unsigned int offset)
|
|||
_jtag->shiftIR(0x3A, 8, Jtag::EXIT1_IR);
|
||||
uint8_t tmp[2] = {0xFE, 0x68};
|
||||
_jtag->shiftDR(tmp, NULL, 16);
|
||||
|
||||
uint8_t *data = _bit->getData();
|
||||
int length = _bit->getLength()/8;
|
||||
|
||||
/* test SPI */
|
||||
SPIFlash flash(this, _verbose);
|
||||
flash.reset();
|
||||
flash.read_id();
|
||||
flash.read_status_reg();
|
||||
flash.erase_and_prog(offset, data, length);
|
||||
|
||||
int ret = true;
|
||||
if (_verify)
|
||||
ret = flash.verify(offset, data, length);
|
||||
|
||||
delete _bit;
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::program_flash(unsigned int offset)
|
||||
bool Lattice::post_flash_access()
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
bool Lattice::clearSRAM()
|
||||
{
|
||||
uint32_t erase_op;
|
||||
|
||||
/* read ID Code 0xE0 */
|
||||
if (_verbose) {
|
||||
printf("IDCode : %x\n", idCode());
|
||||
displayReadReg(readStatusReg());
|
||||
}
|
||||
|
||||
/* preload 0x1C */
|
||||
uint8_t tx_buf[26];
|
||||
memset(tx_buf, 0xff, 26);
|
||||
|
|
@ -620,7 +582,69 @@ bool Lattice::program_flash(unsigned int offset)
|
|||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
DisableISC();
|
||||
return DisableISC();
|
||||
}
|
||||
|
||||
bool Lattice::program_extFlash(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
int ret;
|
||||
ConfigBitstreamParser *_bit;
|
||||
|
||||
printInfo("Open file ", false);
|
||||
try {
|
||||
if (_file_extension == "mcs")
|
||||
_bit = new McsParser(_filename, true, _verbose);
|
||||
else if (_file_extension == "bit")
|
||||
_bit = new LatticeBitParser(_filename, _verbose);
|
||||
else
|
||||
_bit = new RawParser(_filename, false);
|
||||
printSuccess("DONE");
|
||||
} catch (std::exception &e) {
|
||||
printError("FAIL");
|
||||
printError(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
printInfo("Parse file ", false);
|
||||
if (_bit->parse() == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
delete _bit;
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
if (_verbose)
|
||||
_bit->displayHeader();
|
||||
|
||||
if (_file_extension == "bit") {
|
||||
uint32_t bit_idcode = std::stoul(_bit->getHeaderVal("idcode").c_str(), NULL, 16);
|
||||
uint32_t idcode = idCode();
|
||||
if (idcode != bit_idcode) {
|
||||
char mess[256];
|
||||
sprintf(mess, "mismatch between target's idcode and bitstream idcode\n"
|
||||
"\tbitstream has 0x%08X hardware requires 0x%08x", bit_idcode, idcode);
|
||||
printError(mess);
|
||||
delete _bit;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SPIInterface::write(offset, _bit->getData(), _bit->getLength() / 8,
|
||||
unprotect_flash);
|
||||
|
||||
delete _bit;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Lattice::program_flash(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
/* read ID Code 0xE0 */
|
||||
if (_verbose) {
|
||||
printf("IDCode : %x\n", idCode());
|
||||
displayReadReg(readStatusReg());
|
||||
}
|
||||
|
||||
bool retval;
|
||||
if (_file_extension == "jed") {
|
||||
|
|
@ -641,113 +665,41 @@ bool Lattice::program_flash(unsigned int offset)
|
|||
if (_verbose)
|
||||
_jed.displayHeader();
|
||||
|
||||
/* clear current SRAM content */
|
||||
clearSRAM();
|
||||
|
||||
if (_fpga_family == MACHXO3D_FAMILY)
|
||||
retval = program_intFlash_MachXO3D(_jed);
|
||||
else
|
||||
retval = program_intFlash(_jed);
|
||||
return post_flash_access() && retval;
|
||||
} else if (_file_extension == "fea") {
|
||||
/* clear current SRAM content */
|
||||
clearSRAM();
|
||||
retval = program_fea_MachXO3D();
|
||||
return post_flash_access() && retval;
|
||||
} else if (_file_extension == "pub") {
|
||||
/* clear current SRAM content */
|
||||
clearSRAM();
|
||||
retval = program_pubkey_MachXO3D();
|
||||
} else {
|
||||
retval = program_extFlash(offset);
|
||||
return program_extFlash(offset, unprotect_flash);
|
||||
}
|
||||
|
||||
if (!retval)
|
||||
return false;
|
||||
|
||||
/* *************************** */
|
||||
/* reload bitstream from flash */
|
||||
/* *************************** */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void Lattice::program(unsigned int offset)
|
||||
void Lattice::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
bool retval = true;
|
||||
if (_mode == FLASH_MODE)
|
||||
retval = program_flash(offset);
|
||||
retval = program_flash(offset, unprotect_flash);
|
||||
else if (_mode == MEM_MODE)
|
||||
retval = program_mem();
|
||||
if (!retval)
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
/* 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.dump(filename, base_addr, len);
|
||||
|
||||
/* 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)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,27 @@ class Lattice: public Device, SPIInterface {
|
|||
int idCode() override;
|
||||
int userCode();
|
||||
void reset() override {}
|
||||
void program(unsigned int offset) override;
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
bool program_mem();
|
||||
bool program_flash(unsigned int offset);
|
||||
bool program_flash(unsigned int offset, bool unprotect_flash);
|
||||
bool Verify(std::vector<std::string> data, bool unlock = false,
|
||||
uint32_t flash_area = 0);
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len) override;
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len) override {
|
||||
return SPIInterface::dump(base_addr, len);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool protect_flash(uint32_t len) override {
|
||||
return SPIInterface::protect_flash(len);
|
||||
}
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool unprotect_flash() override {
|
||||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
|
||||
/* spi interface */
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
|
|
@ -54,9 +68,22 @@ class Lattice: public Device, SPIInterface {
|
|||
lattice_family_t _fpga_family;
|
||||
|
||||
bool program_intFlash(JedParser& _jed);
|
||||
bool program_extFlash(unsigned int offset);
|
||||
bool program_extFlash(unsigned int offset, bool unprotect_flash);
|
||||
bool wr_rd(uint8_t cmd, uint8_t *tx, int tx_len,
|
||||
uint8_t *rx, int rx_len, bool verbose = false);
|
||||
/*!
|
||||
* \brief move device to SPI access
|
||||
*/
|
||||
bool prepare_flash_access() override;
|
||||
/*!
|
||||
* \brief end of device to SPI access
|
||||
* reload btistream from flash
|
||||
*/
|
||||
bool post_flash_access() override;
|
||||
/*!
|
||||
* \brief erase SRAM
|
||||
*/
|
||||
bool clearSRAM();
|
||||
void unlock();
|
||||
bool EnableISC(uint8_t flash_mode);
|
||||
bool DisableISC();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
|||
Device::prog_type_t prg_type,
|
||||
const std::string &device_package, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 256, verify),
|
||||
_device_package(device_package)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
|
|
@ -160,7 +161,7 @@ int Xilinx::idCode()
|
|||
return id;
|
||||
}
|
||||
|
||||
void Xilinx::program(unsigned int offset)
|
||||
void Xilinx::program(unsigned int offset, bool unprotect_flash)
|
||||
{
|
||||
ConfigBitstreamParser *bit;
|
||||
bool reverse = false;
|
||||
|
|
@ -226,15 +227,14 @@ void Xilinx::program(unsigned int offset)
|
|||
|
||||
if (_fpga_family == XCF_FAMILY) {
|
||||
xcf_program(bit);
|
||||
delete bit;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mode == Device::SPI_MODE) {
|
||||
program_spi(bit, offset);
|
||||
reset();
|
||||
} else {
|
||||
if (_mode == Device::SPI_MODE)
|
||||
program_spi(bit, offset, unprotect_flash);
|
||||
else
|
||||
program_mem(bit);
|
||||
}
|
||||
|
||||
delete bit;
|
||||
}
|
||||
|
|
@ -264,29 +264,16 @@ bool Xilinx::load_bridge()
|
|||
return true;
|
||||
}
|
||||
|
||||
void Xilinx::program_spi(ConfigBitstreamParser * bit, unsigned int offset)
|
||||
void Xilinx::program_spi(ConfigBitstreamParser * bit, unsigned int offset,
|
||||
bool unprotect_flash)
|
||||
{
|
||||
/* first need to have bridge in RAM */
|
||||
if (load_bridge() == false)
|
||||
return;
|
||||
|
||||
uint8_t *data = bit->getData();
|
||||
int length = bit->getLength() / 8;
|
||||
|
||||
SPIFlash spiFlash(this, (_verbose ? 1 : (_quiet ? -1 : 0)));
|
||||
spiFlash.reset();
|
||||
spiFlash.read_id();
|
||||
spiFlash.display_status_reg(spiFlash.read_status_reg());
|
||||
spiFlash.erase_and_prog(offset, data, length);
|
||||
|
||||
/* verify write if required */
|
||||
if (_verify)
|
||||
spiFlash.verify(offset, data, length, 256);
|
||||
SPIInterface::write(offset, data, length, unprotect_flash);
|
||||
}
|
||||
|
||||
void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
|
||||
{
|
||||
if (_file_extension.empty()) return;
|
||||
std::cout << "load program" << std::endl;
|
||||
unsigned char tx_buf, rx_buf;
|
||||
/* comment TDI TMS TCK
|
||||
|
|
@ -393,8 +380,7 @@ void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
|
|||
_jtag->go_test_logic_reset();
|
||||
}
|
||||
|
||||
bool Xilinx::dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len)
|
||||
bool Xilinx::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||
{
|
||||
if (_fpga_family == XC95_FAMILY || _fpga_family == XCF_FAMILY) {
|
||||
std::string buffer;
|
||||
|
|
@ -412,7 +398,7 @@ bool Xilinx::dumpFlash(const std::string &filename,
|
|||
xcf_flow_disable();
|
||||
}
|
||||
printInfo("Open dump file ", false);
|
||||
FILE *fd = fopen(filename.c_str(), "wb");
|
||||
FILE *fd = fopen(_filename.c_str(), "wb");
|
||||
if (!fd) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
|
|
@ -429,26 +415,8 @@ bool Xilinx::dumpFlash(const std::string &filename,
|
|||
return true;
|
||||
}
|
||||
|
||||
int ret = true;
|
||||
/* first need to have bridge in RAM */
|
||||
if (load_bridge() == false)
|
||||
return false;
|
||||
|
||||
/* prepare SPI access */
|
||||
SPIFlash flash(this, _verbose);
|
||||
|
||||
try {
|
||||
flash.reset();
|
||||
ret = flash.dump(filename, base_addr, len, 256);
|
||||
} catch (std::exception &e) {
|
||||
printError(e.what());
|
||||
ret = false;
|
||||
}
|
||||
|
||||
/* reset device */
|
||||
reset();
|
||||
|
||||
return ret;
|
||||
/* dump SPI Flash */
|
||||
return SPIInterface::dump(base_addr, len);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
|
|
|||
|
|
@ -22,11 +22,25 @@ class Xilinx: public Device, SPIInterface {
|
|||
bool verify, int8_t verbose);
|
||||
~Xilinx();
|
||||
|
||||
void program(unsigned int offset = 0) override;
|
||||
void program_spi(ConfigBitstreamParser * bit, unsigned int offset = 0);
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
void program_spi(ConfigBitstreamParser * bit, unsigned int offset,
|
||||
bool unprotect_flash);
|
||||
void program_mem(ConfigBitstreamParser *bitfile);
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len) override;
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
|
||||
|
||||
/*!
|
||||
* \brief protect SPI flash blocks
|
||||
*/
|
||||
bool protect_flash(uint32_t len) override {
|
||||
return SPIInterface::protect_flash(len);
|
||||
}
|
||||
/*!
|
||||
* \brief unprotect SPI flash blocks
|
||||
*/
|
||||
bool unprotect_flash() override {
|
||||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
|
||||
int idCode() override;
|
||||
void reset() override;
|
||||
|
||||
|
|
@ -105,6 +119,16 @@ class Xilinx: public Device, SPIInterface {
|
|||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose = false) override;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief prepare SPI flash access (need to have bridge in RAM)
|
||||
*/
|
||||
virtual bool prepare_flash_access() override {return load_bridge();}
|
||||
/*!
|
||||
* \brief end of SPI flash access
|
||||
*/
|
||||
virtual bool post_flash_access() override {reset(); return true;}
|
||||
|
||||
private:
|
||||
/* list of xilinx family devices */
|
||||
enum xilinx_family_t {
|
||||
|
|
|
|||
Loading…
Reference in New Issue