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 */
/*************************/
/*!
* \brief display SPI flash ID and status register
*/
bool detect_flash() override {
return SPIInterface::detect_flash();
}
/*!
* \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.
*/

View File

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

View File

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

View File

@ -29,6 +29,10 @@ class Gowin: public Device, SPIInterface {
bool connectJtagToMCU() override;
/* 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 {
(void) len;
printError("protect flash not supported"); return false;}

View File

@ -35,6 +35,12 @@ class Lattice: public Device, SPIInterface {
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
*/

View File

@ -44,7 +44,7 @@ using namespace std;
struct arguments {
int8_t verbose;
bool reset, detect, verify, scan_usb;
bool reset, detect, detect_flash, verify, scan_usb;
unsigned int offset;
string 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};
/* 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,
/* spi dfu file_type fpga_part bridge_path probe_firmware */
false, false, "", "", "", "",
@ -633,6 +636,11 @@ int main(int argc, char **argv)
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.file_size == 0) {
printError("Error: 0 size for dump");
@ -1050,6 +1058,14 @@ int parse_opt(int argc, char **argv, struct arguments *args,
cout << options.help() << endl;
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) {
cerr << "Error parsing options: " << e.what() << endl;
throw std::exception();

View File

@ -23,6 +23,35 @@ SPIInterface::SPIInterface(const std::string &filename, int8_t verbose,
{}
/* 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 ret = true;

View File

@ -26,6 +26,7 @@ class SPIInterface {
bool skip_reset = false);
virtual ~SPIInterface() {}
bool detect_flash();
bool protect_flash(uint32_t len);
bool unprotect_flash();
bool bulk_erase_flash();

View File

@ -1152,6 +1152,21 @@ bool Xilinx::dumpFlash(uint32_t base_addr, uint32_t len)
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)
{
if (_flash_chips & PRIMARY_FLASH) {

View File

@ -53,6 +53,10 @@ class Xilinx: public Device, SPIInterface {
*/
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
*/