all devices / spiInterface / main: added method / infra to detect flash chip with --detect -f

This commit is contained in:
Gwenhael Goavec-Merou 2024-06-09 09:28:52 +02:00
parent d0dd71a28a
commit c468a69fc9
11 changed files with 126 additions and 2 deletions

View File

@ -46,6 +46,12 @@ class Altera: public Device, SPIInterface {
/* spi interface */ /* spi interface */
/*************************/ /*************************/
/*!
* \brief display SPI flash ID and status register
*/
bool detect_flash() override {
return SPIInterface::detect_flash();
}
/*! /*!
* \brief protect SPI flash blocks * \brief protect SPI flash blocks
*/ */

View File

@ -123,6 +123,46 @@ void CologneChip::waitCfgDone()
} }
} }
/**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/
bool CologneChip::detect_flash()
{
if (_spi) {
/* enable output and hold reset */
_spi->gpio_clear(_rstn_pin | _oen_pin);
} else if (_ftdi_jtag) {
/* enable output and disable reset */
_ftdi_jtag->gpio_clear(_oen_pin);
_ftdi_jtag->gpio_set(_rstn_pin);
}
/* prepare SPI access */
printInfo("Read Flash ", false);
try {
std::unique_ptr<SPIFlash> flash(_spi ?
new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose):
new SPIFlash(this, false, _verbose));
flash->read_id();
flash->display_status_reg();
} catch (std::exception &e) {
printError("Fail");
printError(std::string(e.what()));
return false;
}
if (_spi) {
/* disable output and release reset */
_spi->gpio_set(_rstn_pin | _oen_pin);
} else if (_ftdi_jtag) {
/* disable output */
_ftdi_jtag->gpio_set(_oen_pin);
}
usleep(SLEEP_US);
return true;
}
/** /**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode. * Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/ */

View File

@ -34,6 +34,7 @@ class CologneChip: public Device, SPIInterface {
bool cfgDone(); bool cfgDone();
void waitCfgDone(); void waitCfgDone();
bool detect_flash() override;
bool dumpFlash(uint32_t base_addr, uint32_t len) override; bool dumpFlash(uint32_t base_addr, uint32_t len) override;
virtual bool protect_flash(uint32_t len) override { virtual bool protect_flash(uint32_t len) override {
(void) len; (void) len;

View File

@ -46,6 +46,8 @@ class Device {
/**********************/ /**********************/
/* flash access */ /* flash access */
/**********************/ /**********************/
virtual bool detect_flash() {
printError("detect flash not supported"); return false;}
virtual bool dumpFlash(uint32_t base_addr, uint32_t len) { virtual bool dumpFlash(uint32_t base_addr, uint32_t len) {
(void) base_addr; (void) len; (void) base_addr; (void) len;
printError("dump flash not supported"); return false;} printError("dump flash not supported"); return false;}

View File

@ -29,6 +29,10 @@ class Gowin: public Device, SPIInterface {
bool connectJtagToMCU() override; bool connectJtagToMCU() override;
/* spi interface */ /* spi interface */
bool detect_flash() override {
if (is_gw5a)
return SPIInterface::detect_flash();
printError("protect flash not supported"); return false;}
bool protect_flash(uint32_t len) override { bool protect_flash(uint32_t len) override {
(void) len; (void) len;
printError("protect flash not supported"); return false;} printError("protect flash not supported"); return false;}

View File

@ -35,6 +35,12 @@ class Lattice: public Device, SPIInterface {
return SPIInterface::dump(base_addr, len); return SPIInterface::dump(base_addr, len);
} }
/*!
* \brief display SPI flash ID and status register
*/
bool detect_flash() override {
return SPIInterface::detect_flash();
}
/*! /*!
* \brief protect SPI flash blocks * \brief protect SPI flash blocks
*/ */

View File

@ -44,7 +44,7 @@ using namespace std;
struct arguments { struct arguments {
int8_t verbose; int8_t verbose;
bool reset, detect, verify, scan_usb; bool reset, detect, detect_flash, verify, scan_usb;
unsigned int offset; unsigned int offset;
string bit_file; string bit_file;
string secondary_bit_file; string secondary_bit_file;
@ -112,7 +112,10 @@ 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,
//reset, detect, detect_flash, verify, scan_usb
false, false, false, false, false,
0, "", "", "", "-", "", -1,
-1, 0, false, "-", false, false, false, false, Device::PRG_NONE, false, -1, 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, "", "", "", "",
@ -633,6 +636,11 @@ int main(int argc, char **argv)
fpga->protect_flash(args.protect_flash); fpga->protect_flash(args.protect_flash);
} }
/* detect/display flash */
if (args.detect_flash != 0) {
fpga->detect_flash();
}
if (args.prg_type == Device::RD_FLASH) { if (args.prg_type == Device::RD_FLASH) {
if (args.file_size == 0) { if (args.file_size == 0) {
printError("Error: 0 size for dump"); printError("Error: 0 size for dump");
@ -1050,6 +1058,14 @@ int parse_opt(int argc, char **argv, struct arguments *args,
cout << options.help() << endl; cout << options.help() << endl;
throw std::exception(); throw std::exception();
} }
// user ask detect with flash set
// detect/display flash CHIP informations instead
// of FPGA details
if (args->detect && args->prg_type == Device::WR_FLASH) {
args->detect = false;
args->detect_flash = true;
}
} catch (const cxxopts::OptionException& e) { } catch (const cxxopts::OptionException& e) {
cerr << "Error parsing options: " << e.what() << endl; cerr << "Error parsing options: " << e.what() << endl;
throw std::exception(); throw std::exception();

View File

@ -23,6 +23,35 @@ SPIInterface::SPIInterface(const std::string &filename, int8_t verbose,
{} {}
/* spiFlash generic acces */ /* spiFlash generic acces */
bool SPIInterface::detect_flash()
{
bool ret = true;
printInfo("protect_flash: ", false);
/* move device to spi access */
if (!prepare_flash_access()) {
printError("Fail");
return false;
}
/* spi flash access */
try {
// instanciate call (display flash ID is automatic)
SPIFlash flash(this, false, _spif_verbose);
// display status register
flash.display_status_reg();
printSuccess("Done");
} catch (std::exception &e) {
printError("Fail");
printError(e.what());
ret = false;
}
/* reload bitstream */
return post_flash_access() && ret;
}
bool SPIInterface::protect_flash(uint32_t len) bool SPIInterface::protect_flash(uint32_t len)
{ {
bool ret = true; bool ret = true;

View File

@ -26,6 +26,7 @@ class SPIInterface {
bool skip_reset = false); bool skip_reset = false);
virtual ~SPIInterface() {} virtual ~SPIInterface() {}
bool detect_flash();
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();

View File

@ -1152,6 +1152,21 @@ bool Xilinx::dumpFlash(uint32_t base_addr, uint32_t len)
return true; return true;
} }
bool Xilinx::detect_flash()
{
if (_flash_chips & PRIMARY_FLASH) {
select_flash_chip(PRIMARY_FLASH);
if (!SPIInterface::detect_flash())
return false;
}
if (_flash_chips & SECONDARY_FLASH) {
select_flash_chip(SECONDARY_FLASH);
if (!SPIInterface::detect_flash())
return false;
}
return true;
}
bool Xilinx::protect_flash(uint32_t len) bool Xilinx::protect_flash(uint32_t len)
{ {
if (_flash_chips & PRIMARY_FLASH) { if (_flash_chips & PRIMARY_FLASH) {

View File

@ -53,6 +53,10 @@ class Xilinx: public Device, SPIInterface {
*/ */
uint32_t dumpRegister(const std::string reg_name); uint32_t dumpRegister(const std::string reg_name);
/*!
* \brief display SPI flash ID and status register
*/
bool detect_flash() override;
/*! /*!
* \brief protect SPI flash blocks * \brief protect SPI flash blocks
*/ */