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 ISC_DISABLE 0x26 /* ISC_DISABLE */
|
||||||
#define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */
|
#define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */
|
||||||
#define FLASH_ERASE 0x0E /* ISC_ERASE */
|
#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_UFM (1<<3)
|
||||||
# define FLASH_ERASE_CFG (1<<2)
|
# define FLASH_ERASE_CFG (1<<2)
|
||||||
# define FLASH_ERASE_FEATURE (1<<1)
|
# define FLASH_ERASE_FEATURE (1<<1)
|
||||||
|
|
@ -399,6 +399,7 @@ bool Lattice::program_mem()
|
||||||
bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
||||||
{
|
{
|
||||||
uint64_t featuresRow;
|
uint64_t featuresRow;
|
||||||
|
uint16_t ufm_start = 0;
|
||||||
uint16_t feabits;
|
uint16_t feabits;
|
||||||
uint8_t eraseMode = 0;
|
uint8_t eraseMode = 0;
|
||||||
vector<string> ufm_data, cfg_data, ebr_data;
|
vector<string> ufm_data, cfg_data, ebr_data;
|
||||||
|
|
@ -425,6 +426,16 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
||||||
if (note == "TAG DATA") {
|
if (note == "TAG DATA") {
|
||||||
eraseMode |= FLASH_ERASE_UFM;
|
eraseMode |= FLASH_ERASE_UFM;
|
||||||
ufm_data = _jed->data_for_section(i);
|
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") {
|
} else if (note == "END CONFIG DATA") {
|
||||||
continue;
|
continue;
|
||||||
} else if (note == "EBR_INIT DATA") {
|
} else if (note == "EBR_INIT DATA") {
|
||||||
|
|
@ -444,7 +455,7 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
||||||
feabits = 0x460;
|
feabits = 0x460;
|
||||||
}
|
}
|
||||||
|
|
||||||
eraseMode = FLASH_ERASE_CFG;
|
eraseMode |= FLASH_ERASE_CFG;
|
||||||
if (featuresRow != readFeaturesRow() || feabits != readFeabits())
|
if (featuresRow != readFeaturesRow() || feabits != readFeabits())
|
||||||
eraseMode |= FLASH_ERASE_FEATURE;
|
eraseMode |= FLASH_ERASE_FEATURE;
|
||||||
|
|
||||||
|
|
@ -477,6 +488,24 @@ bool Lattice::program_intFlash(ConfigBitstreamParser *_cbp)
|
||||||
return false;
|
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 */
|
/* missing usercode update */
|
||||||
|
|
||||||
/* LSC_INIT_ADDRESS */
|
/* LSC_INIT_ADDRESS */
|
||||||
|
|
@ -831,7 +860,7 @@ bool Lattice::checkID()
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("check ID\n");
|
printf("check ID\n");
|
||||||
uint8_t tx[4];
|
uint8_t tx[4] = { 0 };
|
||||||
wr_rd(0xE2, tx, 4, NULL, 0);
|
wr_rd(0xE2, tx, 4, NULL, 0);
|
||||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
_jtag->toggleClk(1000);
|
_jtag->toggleClk(1000);
|
||||||
|
|
@ -1253,6 +1282,38 @@ bool Lattice::loadConfiguration()
|
||||||
return true;
|
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 */
|
/* SPI implementation */
|
||||||
/* ------------------ */
|
/* ------------------ */
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ class Lattice: public Device, SPIInterface {
|
||||||
bool writeFeabits(uint16_t feabits, bool verify);
|
bool writeFeabits(uint16_t feabits, bool verify);
|
||||||
bool writeProgramDone();
|
bool writeProgramDone();
|
||||||
bool loadConfiguration();
|
bool loadConfiguration();
|
||||||
|
uint16_t getUFMStartPageFromJEDEC(JedParser *_jed, int id);
|
||||||
|
|
||||||
/* test */
|
/* test */
|
||||||
bool checkID();
|
bool checkID();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue