Merge pull request #390 from bg-gsl/lattice_fix_program

Lattice programming fix and boards added
This commit is contained in:
Gwenhael Goavec-Merou 2023-10-13 16:57:59 +02:00 committed by GitHub
commit 5a3ab610a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 19 deletions

View File

@ -126,7 +126,10 @@ static std::map <std::string, target_board_t> 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),

View File

@ -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 */
@ -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 */
@ -133,6 +134,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 +206,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();
@ -253,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;
}
@ -303,7 +307,40 @@ bool Lattice::program_mem()
memset(tx_buf, 0xff, 26);
wr_rd(0x1C, tx_buf, 26, NULL, 0);
wr_rd(0xFf, NULL, 0, NULL, 0);
/* 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);
@ -315,6 +352,29 @@ bool Lattice::program_mem()
printSuccess("DONE");
}
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;
}
printSuccess("DONE");
}
/* ISC ERASE */
printInfo("SRAM erase: ", false);
if (flashErase(FLASH_ERASE_SRAM) == false) {
@ -356,6 +416,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;
@ -888,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;
}
@ -940,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");
@ -1021,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;
@ -1089,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)
@ -1307,7 +1384,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) {

View File

@ -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<std::string> 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();

View File

@ -212,6 +212,9 @@ static std::map <uint32_t, fpga_model> fpga_list = {
{0x310F0043, {"lattice", "CertusNX", "LFD2NX-17", 8}},
{0x310F1043, {"lattice", "CertusNX", "LFD2NX-40", 8}},
/* Lattice CertusPro-NX */
{0x010F4043, {"lattice", "CertusProNX", "LFCPNX-100", 8}},
/**************************************************************************/
/* Gowin */
/**************************************************************************/