From 5733ca29c3a56c4cecfc98a020a194b388760d62 Mon Sep 17 00:00:00 2001 From: Giovanni Bruni Date: Wed, 11 Oct 2023 09:52:45 +0200 Subject: [PATCH 1/2] fix lattice programming and add nexus boards Fix to lattice programming: we considered a svf file generated by Lattice Radiant-Programmer and compared it with the current way lattice devices were programmed. There were few differences dealing with configuration reset and REFRESH. These fixes allow us to program an fpga when it is in a state of error (e.g. there's no bitstream in the SPI Flash). Lattice parts added: - CertusPro FPGA Nexus boards added: - Certus Versa Evaluation board - CertusPro Evaluation board - CertusPro Versa Evaluation board --- src/board.hpp | 5 ++++- src/lattice.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- src/part.hpp | 3 +++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/board.hpp b/src/board.hpp index 6a1e4d4..33de882 100644 --- a/src/board.hpp +++ b/src/board.hpp @@ -126,7 +126,10 @@ static std::map board_list = { JTAG_BOARD("colorlight-i5", "", "cmsisdap", 0, 0, CABLE_DEFAULT), JTAG_BOARD("colorlight-i9", "", "cmsisdap", 0, 0, CABLE_DEFAULT), JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "", 0, 0, CABLE_DEFAULT), - JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certusnx_versa_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certuspronx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certuspronx_versa_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("c10lp-refkit", "10cl055484", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("de0", "", "usb-blaster",0, 0, CABLE_DEFAULT), diff --git a/src/lattice.cpp b/src/lattice.cpp index c4a5570..ac86553 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -28,7 +28,7 @@ using namespace std; #define ISC_ENABLE 0xC6 /* ISC_ENABLE - Offline Mode */ # define ISC_ENABLE_FLASH_MODE (1 << 3) # define ISC_ENABLE_SRAM_MODE (0 << 3) -#define ISC_ENABLE_TRANSPARANT 0x74 /* This command is used to put the device in transparent mode */ +#define ISC_ENABLE_TRANSPARENT 0x74 /* ISC_ENABLE_X This command is used to put the device in transparent mode */ #define ISC_DISABLE 0x26 /* ISC_DISABLE */ #define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */ #define FLASH_ERASE 0x0E /* ISC_ERASE */ @@ -133,6 +133,7 @@ using namespace std; #define PROG_ECDSA_PUBKEY3 0x63 /* This command is used to program the fourth 128 bits of the ECDSA Public Key. */ #define READ_ECDSA_PUBKEY3 0x64 /* This command is used to read the fourth 128 bits of the ECDSA Public Key. */ #define ISC_NOOP 0xff /* This command is no operation command (NOOP) or null operation. */ +#define LSC_DEVICE_CONTROL 0x7D /* Multiple commands. Bit 3: configuration reset */ #define PUBKEY_LENGTH_BYTES 64 /* length of the public key (MachXO3D) in bytes */ @@ -204,6 +205,8 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type, _fpga_family = NEXUS_FAMILY; } else if (family == "CertusNX") { _fpga_family = NEXUS_FAMILY; + } else if (family == "CertusProNX") { + _fpga_family = NEXUS_FAMILY; } else { printError("Unknown device family"); throw std::exception(); @@ -303,7 +306,17 @@ bool Lattice::program_mem() memset(tx_buf, 0xff, 26); wr_rd(0x1C, tx_buf, 26, NULL, 0); - wr_rd(0xFf, NULL, 0, NULL, 0); + /* SRAM TRANSPARENT mode ISC_ENABLE_X 0x74 */ + uint8_t tx_tmp[1] = {0x00}; + // wr_rd(ISC_ENABLE_TRANSPARENT, tx_tmp, 1, NULL, 0); + // _jtag->set_state(Jtag::RUN_TEST_IDLE); + // _jtag->toggleClk(1000); + + /* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin" */ + wr_rd(REFRESH, NULL, 0, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + sleep(5); /* ISC Enable 0xC6 */ printInfo("Enable configuration: ", false); @@ -315,6 +328,25 @@ bool Lattice::program_mem() printSuccess("DONE"); } + /* LSC_DEVICE_CONTROL 0x7D -- configuration reset */ + tx_tmp[0] = 0x08; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } + + tx_tmp[0] = 0x00; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } + /* ISC ERASE */ printInfo("SRAM erase: ", false); if (flashErase(FLASH_ERASE_SRAM) == false) { @@ -356,6 +388,9 @@ bool Lattice::program_mem() _jtag->shiftDR(tmp, NULL, size*8, next_state); } + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + uint32_t status_mask; if (_fpga_family == MACHXO3D_FAMILY) status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK; @@ -1307,7 +1342,7 @@ uint16_t Lattice::getUFMStartPageFromJEDEC(JedParser *_jed, int id) addres. TODO: In any case, JEDEC files don't carry part information. Verify against IDCODE read previously? */ - + if(raw_page_offset > 9211) { return raw_page_offset - 9211 - 1; // 7000 } else if(raw_page_offset > 5758) { diff --git a/src/part.hpp b/src/part.hpp index 0c45448..34e20c7 100644 --- a/src/part.hpp +++ b/src/part.hpp @@ -212,6 +212,9 @@ static std::map fpga_list = { {0x310F0043, {"lattice", "CertusNX", "LFD2NX-17", 8}}, {0x310F1043, {"lattice", "CertusNX", "LFD2NX-40", 8}}, + /* Lattice CertusPro-NX */ + {0x010F4043, {"lattice", "CertusProNX", "LFCPNX-100", 8}}, + /**************************************************************************/ /* Gowin */ /**************************************************************************/ From dafe350fbefc40b5798dcff17a4effa69cb4be9a Mon Sep 17 00:00:00 2001 From: Giovanni Bruni Date: Wed, 11 Oct 2023 16:49:55 +0200 Subject: [PATCH 2/2] lattice nexus family: REFRESH (plus config logic reset) in case of fpga in error state and add capabilities to handle the whole 64-bits status register --- src/lattice.cpp | 120 ++++++++++++++++++++++++++++++++---------------- src/lattice.hpp | 8 ++-- 2 files changed, 86 insertions(+), 42 deletions(-) diff --git a/src/lattice.cpp b/src/lattice.cpp index ac86553..8b23a1a 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -91,7 +91,7 @@ using namespace std; #define READ_FEABITS 0xFB /* LSC_READ_FEABITS */ /* See feaParser.hpp for FEAbit definitions */ #define PROG_DONE 0x5E /* ISC_PROGRAM_DONE - This command is used to program the done bit */ -#define REFRESH 0x79 /* LSC_REFRESH */ +#define REFRESH 0x79 /* LSC_REFRESH - Equivalent to toggle PROGRAMN pin */ #define READ_STATUS_REGISTER 0x3C /* LSC_READ_STATUS */ # define REG_STATUS_DONE (1 << 8) /* Flash or SRAM Done Flag (ISC_EN=0 -> 1 Successful Flash to SRAM transfer, ISC_EN=1 -> 1 Programmed) */ # define REG_STATUS_ISC_EN (1 << 9) /* Enable Configuration Interface (1=Enable, 0=Disable) */ @@ -103,6 +103,7 @@ using namespace std; # define REG_STATUS_AUTH_DONE (1 << 18) /* Authentication done */ # define REG_STATUS_PRI_BOOT_FAIL (1 << 21) /* Primary boot failure (1= Fail) even though secondary boot successful */ # define REG_STATUS_CNF_CHK_MASK (0x0f << 23) /* Configuration Status Check */ +#define REG_STATUS_PRV_CNF_CHK_MASK (0x0fUL << 33) /* NEXUS_FAMILY: Configuration Status Check of previous bitstrem */ # define REG_STATUS_MACHXO3D_CNF_CHK_MASK (0x0f << 22) /* Configuration Status Check */ # define REG_STATUS_EXEC_ERR (1 << 26) /*** NOT specified for MachXO3D ***/ # define REG_STATUS_DEV_VERIFIED (1 << 27) /* I=0 Device verified correct, I=1 Device failed to verify */ @@ -256,9 +257,9 @@ void displayFeabits(uint16_t _featbits) (((_featbits>>2)&0x01)?"Enabled" : "Disabled")); } -bool Lattice::checkStatus(uint32_t val, uint32_t mask) +bool Lattice::checkStatus(uint64_t val, uint64_t mask) { - uint32_t reg = readStatusReg(); + uint64_t reg = readStatusReg(); return ((reg & mask) == val) ? true : false; } @@ -306,17 +307,40 @@ bool Lattice::program_mem() memset(tx_buf, 0xff, 26); wr_rd(0x1C, tx_buf, 26, NULL, 0); - /* SRAM TRANSPARENT mode ISC_ENABLE_X 0x74 */ - uint8_t tx_tmp[1] = {0x00}; - // wr_rd(ISC_ENABLE_TRANSPARENT, tx_tmp, 1, NULL, 0); - // _jtag->set_state(Jtag::RUN_TEST_IDLE); - // _jtag->toggleClk(1000); - - /* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin" */ - wr_rd(REFRESH, NULL, 0, NULL, 0); - _jtag->set_state(Jtag::RUN_TEST_IDLE); - _jtag->toggleClk(1000); - sleep(5); + /* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin" + * We REFRESH only if the fpga is in a status of error due to + * the previous bitstream. For example, this happens if + * no bitstream is present on the SPI FLASH + */ + /*flag to understand if we refreshed or not*/ + bool was_refreshed; + if (_fpga_family == NEXUS_FAMILY) { + if (!checkStatus(0, REG_STATUS_PRV_CNF_CHK_MASK)) { + printInfo("Error in previous bitstream execution. REFRESH: ", false); + wr_rd(REFRESH, NULL, 0, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + /* In Lattice FPGA-TN-02099 document in a note it's reported that there + is a delay time after LSC_REFRESH where "Duration could be in + seconds". Without whis waiting time, busy flag can't be cleared.*/ + sleep(5); + was_refreshed = true; + if (!checkStatus(0, REG_STATUS_PRV_CNF_CHK_MASK)) { + printError("FAIL"); + displayReadReg(readStatusReg()); + return false; + } else { + printSuccess("DONE"); + } + } else { + was_refreshed = false; + if (_verbose){ + printInfo("No error in previous bitstream execution.", true); + } + } + } else { + was_refreshed = false; + } /* ISC Enable 0xC6 */ printInfo("Enable configuration: ", false); @@ -328,23 +352,27 @@ bool Lattice::program_mem() printSuccess("DONE"); } - /* LSC_DEVICE_CONTROL 0x7D -- configuration reset */ - tx_tmp[0] = 0x08; - wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); - _jtag->set_state(Jtag::RUN_TEST_IDLE); - _jtag->toggleClk(1000); - if(!pollBusyFlag()) { - printError("FAIL"); - return false; - } + if (was_refreshed) { + /* LSC_DEVICE_CONTROL 0x7D -- configuration reset */ + printInfo("Configuration Logic Reset: ", false); + uint8_t tx_tmp[1] = {0x08}; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } - tx_tmp[0] = 0x00; - wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); - _jtag->set_state(Jtag::RUN_TEST_IDLE); - _jtag->toggleClk(1000); - if(!pollBusyFlag()) { - printError("FAIL"); - return false; + tx_tmp[0] = 0x00; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } + printSuccess("DONE"); } /* ISC ERASE */ @@ -923,20 +951,35 @@ bool Lattice::checkID() return true; } +/* returns the number of bits of the Device Status Register + * accordingly to _fpga_family + */ +int Lattice::get_statusreg_size(){ + if (_fpga_family == NEXUS_FAMILY) { + return 64; + } else{ + return 32; + } +} + /* feabits is MSB first * maybe this register too * or not */ -uint32_t Lattice::readStatusReg() +uint64_t Lattice::readStatusReg() { - uint32_t reg; - uint8_t rx[4], tx[4]; + uint64_t reg; + uint8_t rx[8], tx[8]; + + int reg_len = get_statusreg_size() / 8; + /* valgrind warn */ - memset(tx, 0, 4); - wr_rd(READ_STATUS_REGISTER, tx, 4, rx, 4); + memset(tx, 0, 8); + memset(rx, 0, 8); + wr_rd(READ_STATUS_REGISTER, tx, reg_len, rx, reg_len); _jtag->set_state(Jtag::RUN_TEST_IDLE); _jtag->toggleClk(1000); - reg = rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]; + reg = (uint64_t) rx[7] << 56 | (uint64_t) rx[6] << 48 | (uint64_t) rx[5] << 40 | (uint64_t) rx[4] << 32 | rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]; return reg; } @@ -975,7 +1018,7 @@ bool Lattice::wr_rd(uint8_t cmd, return true; } -void Lattice::displayReadReg(uint32_t dev) +void Lattice::displayReadReg(uint64_t dev) { uint8_t err; printf("displayReadReg\n"); @@ -1056,7 +1099,6 @@ void Lattice::displayReadReg(uint32_t dev) if ((dev >> 31) & 0x01) printf("\tFT Mode\n"); } -#if 0 if (_fpga_family == NEXUS_FAMILY) { if ((dev >> 33) & 0x01) printf("\tDry Run Done\n"); err = (dev >> 34)&0x0f; @@ -1124,7 +1166,7 @@ void Lattice::displayReadReg(uint32_t dev) } if ((dev >> 50) & 0x01) printf("\tAuthentication Done\n"); if ((dev >> 51) & 0x01) printf("\tDry Run Authentication Done\n"); -#endif + } } bool Lattice::pollBusyFlag(bool verbose) diff --git a/src/lattice.hpp b/src/lattice.hpp index cf694ed..1a74861 100644 --- a/src/lattice.hpp +++ b/src/lattice.hpp @@ -73,6 +73,8 @@ class Lattice: public Device, SPIInterface { lattice_family_t _fpga_family; + int get_statusreg_size(); + bool program_intFlash(ConfigBitstreamParser *_cbp); bool program_extFlash(unsigned int offset, bool unprotect_flash); bool wr_rd(uint8_t cmd, uint8_t *tx, int tx_len, @@ -100,9 +102,9 @@ class Lattice: public Device, SPIInterface { bool flashErase(uint32_t mask); bool flashProg(uint32_t start_addr, const std::string &name, std::vector data); - bool checkStatus(uint32_t val, uint32_t mask); - void displayReadReg(uint32_t dev); - uint32_t readStatusReg(); + bool checkStatus(uint64_t val, uint64_t mask); + void displayReadReg(uint64_t dev); + uint64_t readStatusReg(); uint64_t readFeaturesRow(); bool writeFeaturesRow(uint64_t features, bool verify); uint16_t readFeabits();