Add support for flashing UFM on MachXO2 using JEDEC file. (#339)
* Add support for flashing UFM on MachXO2 using JEDEC file. * Use a better guard value for getUFMStartPageFromJEDEC. * Fix if-else style in getUFMStartPageFromJEDEC.
This commit is contained in:
parent
873de96a3b
commit
0db174ed7e
|
|
@ -32,7 +32,7 @@ using namespace std;
|
|||
#define ISC_DISABLE 0x26 /* ISC_DISABLE */
|
||||
#define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */
|
||||
#define FLASH_ERASE 0x0E /* ISC_ERASE */
|
||||
/* Flash areas as defined for Lattice MachXO3L/LF */
|
||||
/* Flash areas as defined for Lattice MachXO2,3L/LF */
|
||||
# define FLASH_ERASE_UFM (1<<3)
|
||||
# define FLASH_ERASE_CFG (1<<2)
|
||||
# define FLASH_ERASE_FEATURE (1<<1)
|
||||
|
|
@ -399,6 +399,7 @@ bool Lattice::program_mem()
|
|||
bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
||||
{
|
||||
uint64_t featuresRow;
|
||||
uint16_t ufm_start = 0;
|
||||
uint16_t feabits;
|
||||
uint8_t eraseMode = 0;
|
||||
vector<string> ufm_data, cfg_data, ebr_data;
|
||||
|
|
@ -425,6 +426,16 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
|||
if (note == "TAG DATA") {
|
||||
eraseMode |= FLASH_ERASE_UFM;
|
||||
ufm_data = _jed->data_for_section(i);
|
||||
ufm_start = getUFMStartPageFromJEDEC(_jed, i);
|
||||
|
||||
if (_verbose)
|
||||
printf("UFM init detected in JEDEC file");
|
||||
|
||||
if(ufm_start > 2045) {
|
||||
printError("UFM section detected in JEDEC file, but "
|
||||
"calculated flash start address was out of bounds");
|
||||
return false;
|
||||
}
|
||||
} else if (note == "END CONFIG DATA") {
|
||||
continue;
|
||||
} else if (note == "EBR_INIT DATA") {
|
||||
|
|
@ -444,7 +455,7 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
|||
feabits = 0x460;
|
||||
}
|
||||
|
||||
eraseMode = FLASH_ERASE_CFG;
|
||||
eraseMode |= FLASH_ERASE_CFG;
|
||||
if (featuresRow != readFeaturesRow() || feabits != readFeabits())
|
||||
eraseMode |= FLASH_ERASE_FEATURE;
|
||||
|
||||
|
|
@ -477,6 +488,24 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((eraseMode & FLASH_ERASE_UFM) != 0) {
|
||||
/* LSC_WRITE_ADDRESS */
|
||||
uint8_t tx[4] = {
|
||||
ufm_start & 0xff,
|
||||
(ufm_start >> 8) & 0xff,
|
||||
0,
|
||||
0x40
|
||||
};
|
||||
|
||||
wr_rd(LSC_WRITE_ADDRESS, tx, 4, NULL, 0);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
||||
/* Same command to program CFG flash works for UFM. */
|
||||
if (false == flashProg(0, "UFM", ufm_data))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* missing usercode update */
|
||||
|
||||
/* LSC_INIT_ADDRESS */
|
||||
|
|
@ -831,7 +860,7 @@ bool Lattice::checkID()
|
|||
{
|
||||
printf("\n");
|
||||
printf("check ID\n");
|
||||
uint8_t tx[4];
|
||||
uint8_t tx[4] = { 0 };
|
||||
wr_rd(0xE2, tx, 4, NULL, 0);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
|
@ -1253,6 +1282,38 @@ bool Lattice::loadConfiguration()
|
|||
return true;
|
||||
}
|
||||
|
||||
uint16_t Lattice::getUFMStartPageFromJEDEC(JedParser *_jed, int id)
|
||||
{
|
||||
/* In general, Lattice tools try to fill UFM from the highest
|
||||
page to lowest. JEDEC files will give a starting bit offset. */
|
||||
uint32_t bit_offset = _jed->offset_for_section(id);
|
||||
/* Convert to starting page, which seems to be one more than the number
|
||||
of Configuration Flash pages, based on looking at Diamond-generated
|
||||
JEDECs. */
|
||||
uint16_t raw_page_offset = bit_offset / 128;
|
||||
|
||||
/* Raw page offsets won't overlap- see Lattice TN-02155, page 49. So we
|
||||
can uniquely determine which part type we're targeting from the UFM start
|
||||
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) {
|
||||
return raw_page_offset - 5758 - 1; // 4000, 2000U
|
||||
} else if(raw_page_offset > 3198) {
|
||||
return raw_page_offset - 3198 - 1; // 2000, 1200U
|
||||
} else if(raw_page_offset > 2175) {
|
||||
return raw_page_offset - 2175 - 1; // 1200, 640U
|
||||
} else if(raw_page_offset > 1151) {
|
||||
return raw_page_offset - 1151 - 1; // 640
|
||||
} else {
|
||||
// 256- We should bail if we get here! No UFM!
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------ */
|
||||
/* SPI implementation */
|
||||
/* ------------------ */
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ class Lattice: public Device, SPIInterface {
|
|||
bool writeFeabits(uint16_t feabits, bool verify);
|
||||
bool writeProgramDone();
|
||||
bool loadConfiguration();
|
||||
uint16_t getUFMStartPageFromJEDEC(JedParser *_jed, int id);
|
||||
|
||||
/* test */
|
||||
bool checkID();
|
||||
|
|
|
|||
Loading…
Reference in New Issue