lattice: add flash SRAM with .bit file support. Split program in two distinct methods
This commit is contained in:
parent
1cbd3aa89b
commit
c394c69a10
211
lattice.cpp
211
lattice.cpp
|
|
@ -58,14 +58,21 @@ using namespace std;
|
||||||
# define REG_STATUS_ISC_EN (1 << 9)
|
# define REG_STATUS_ISC_EN (1 << 9)
|
||||||
# define REG_STATUS_BUSY (1 << 12)
|
# define REG_STATUS_BUSY (1 << 12)
|
||||||
# define REG_STATUS_FAIL (1 << 13)
|
# define REG_STATUS_FAIL (1 << 13)
|
||||||
|
# define REG_STATUS_CNF_CHK_MASK (0x7 << 23)
|
||||||
# define REG_STATUS_EXEC_ERR (1 << 26)
|
# define REG_STATUS_EXEC_ERR (1 << 26)
|
||||||
|
|
||||||
Lattice::Lattice(FtdiJtag *jtag, const string filename, bool verbose):
|
Lattice::Lattice(FtdiJtag *jtag, const string filename, bool verbose):
|
||||||
Device(jtag, filename, verbose)
|
Device(jtag, filename, verbose)
|
||||||
{
|
{
|
||||||
if (_filename != "")
|
if (_filename != "") {
|
||||||
if (_file_extension == "jed")
|
if (_file_extension == "jed") {
|
||||||
_mode = Device::FLASH_MODE;
|
_mode = Device::FLASH_MODE;
|
||||||
|
} else if (_file_extension == "bit") {
|
||||||
|
_mode = Device::MEM_MODE;
|
||||||
|
} else {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -119,46 +126,165 @@ bool Lattice::checkStatus(uint32_t val, uint32_t mask)
|
||||||
return ((reg & mask) == val) ? true : false;
|
return ((reg & mask) == val) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lattice::program(unsigned int offset)
|
bool Lattice::program_mem()
|
||||||
{
|
{
|
||||||
(void) offset;
|
bool err;
|
||||||
uint64_t featuresRow;
|
LatticeBitParser _bit(_filename, _verbose);
|
||||||
uint16_t feabits;
|
|
||||||
uint8_t eraseMode;
|
|
||||||
vector<string> ufm_data, cfg_data;
|
|
||||||
|
|
||||||
if (_mode != FLASH_MODE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JedParser _jed(_filename, _verbose);
|
|
||||||
|
|
||||||
printInfo("Open file " + _filename + " ", false);
|
printInfo("Open file " + _filename + " ", false);
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
|
|
||||||
if (_jed.parse() == EXIT_FAILURE) {
|
err = _bit.parse();
|
||||||
printInfo("Parse file ", false);
|
|
||||||
|
printInfo("Parse file ", false);
|
||||||
|
if (err == EXIT_FAILURE) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printInfo("Parse file ", false);
|
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read ID Code 0xE0 */
|
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
|
_bit.displayHeader();
|
||||||
|
|
||||||
|
/* read ID Code 0xE0 */
|
||||||
|
if (_verbose) {
|
||||||
printf("IDCode : %x\n", idCode());
|
printf("IDCode : %x\n", idCode());
|
||||||
|
displayReadReg(readStatusReg());
|
||||||
|
}
|
||||||
|
|
||||||
/* preload 0x1C */
|
/* preload 0x1C */
|
||||||
uint8_t tx_buf[26];
|
uint8_t tx_buf[26];
|
||||||
memset(tx_buf, 0xff, 26);
|
memset(tx_buf, 0xff, 26);
|
||||||
wr_rd(0x1C, tx_buf, 26, NULL, 0);
|
wr_rd(0x1C, tx_buf, 26, NULL, 0);
|
||||||
|
|
||||||
|
wr_rd(0xFf, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
/* ISC Enable 0xC6 */
|
/* ISC Enable 0xC6 */
|
||||||
printInfo("Enable configuration: ", false);
|
printInfo("Enable configuration: ", false);
|
||||||
if (!EnableISC(0x00)) {
|
if (!EnableISC(0x00)) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
displayReadReg(readStatusReg());
|
displayReadReg(readStatusReg());
|
||||||
return;
|
return false;
|
||||||
|
} else {
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ISC ERASE */
|
||||||
|
printInfo("SRAM erase: ", false);
|
||||||
|
if (flashErase(FLASH_ERASE_SRAM) == false) {
|
||||||
|
printError("FAIL");
|
||||||
|
displayReadReg(readStatusReg());
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LSC_INIT_ADDRESS */
|
||||||
|
wr_rd(0x46, NULL, 0, NULL, 0);
|
||||||
|
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE);
|
||||||
|
_jtag->toggleClk(1000);
|
||||||
|
|
||||||
|
uint8_t *data = _bit.getData();
|
||||||
|
int length = _bit.getLength()/8;
|
||||||
|
wr_rd(0x7A, NULL, 0, NULL, 0);
|
||||||
|
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE);
|
||||||
|
_jtag->toggleClk(2);
|
||||||
|
|
||||||
|
uint8_t tmp[1024];
|
||||||
|
int size = 1024;
|
||||||
|
|
||||||
|
ProgressBar progress("Loading", length, 50);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i += size) {
|
||||||
|
progress.display(i);
|
||||||
|
|
||||||
|
if (length < i + size)
|
||||||
|
size = length-i;
|
||||||
|
|
||||||
|
for (int ii = 0; ii < size; ii++)
|
||||||
|
tmp[ii] = ConfigBitstreamParser::reverseByte(data[i+ii]);
|
||||||
|
|
||||||
|
_jtag->shiftDR(tmp, NULL, size*8, FtdiJtag::SHIFT_DR);
|
||||||
|
}
|
||||||
|
|
||||||
|
_jtag->set_state(FtdiJtag::RUN_TEST_IDLE);
|
||||||
|
|
||||||
|
if (checkStatus(0, REG_STATUS_CNF_CHK_MASK))
|
||||||
|
progress.done();
|
||||||
|
else {
|
||||||
|
progress.fail();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
|
if (_verbose)
|
||||||
|
printf("userCode: %08x\n", userCode());
|
||||||
|
|
||||||
|
/* bypass */
|
||||||
|
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||||
|
/* disable configuration mode */
|
||||||
|
printInfo("Disable configuration: ", false);
|
||||||
|
if (!DisableISC()) {
|
||||||
|
printError("FAIL");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_verbose)
|
||||||
|
displayReadReg(readStatusReg());
|
||||||
|
|
||||||
|
/* bypass */
|
||||||
|
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||||
|
_jtag->go_test_logic_reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lattice::program_flash(unsigned int offset)
|
||||||
|
{
|
||||||
|
(void) offset;
|
||||||
|
bool err;
|
||||||
|
uint64_t featuresRow;
|
||||||
|
uint16_t feabits;
|
||||||
|
uint8_t eraseMode;
|
||||||
|
vector<string> ufm_data, cfg_data;
|
||||||
|
|
||||||
|
JedParser _jed(_filename, _verbose);
|
||||||
|
|
||||||
|
printInfo("Open file " + _filename + " ", false);
|
||||||
|
printSuccess("DONE");
|
||||||
|
|
||||||
|
err = _jed.parse();
|
||||||
|
|
||||||
|
printInfo("Parse file ", false);
|
||||||
|
if (err == EXIT_FAILURE) {
|
||||||
|
printError("FAIL");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
printSuccess("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read ID Code 0xE0 */
|
||||||
|
if (_verbose) {
|
||||||
|
printf("IDCode : %x\n", idCode());
|
||||||
|
displayReadReg(readStatusReg());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preload 0x1C */
|
||||||
|
uint8_t tx_buf[26];
|
||||||
|
memset(tx_buf, 0xff, 26);
|
||||||
|
wr_rd(0x1C, tx_buf, 26, NULL, 0);
|
||||||
|
|
||||||
|
wr_rd(0xFf, NULL, 0, NULL, 0);
|
||||||
|
|
||||||
|
/* ISC Enable 0xC6 */
|
||||||
|
printInfo("Enable configuration: ", false);
|
||||||
|
if (!EnableISC(0x00)) {
|
||||||
|
printError("FAIL");
|
||||||
|
displayReadReg(readStatusReg());
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +293,7 @@ void Lattice::program(unsigned int offset)
|
||||||
if (flashErase(FLASH_ERASE_SRAM) == false) {
|
if (flashErase(FLASH_ERASE_SRAM) == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
displayReadReg(readStatusReg());
|
displayReadReg(readStatusReg());
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
@ -179,12 +305,11 @@ void Lattice::program(unsigned int offset)
|
||||||
if (!EnableISC(0x08)) {
|
if (!EnableISC(0x08)) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
displayReadReg(readStatusReg());
|
displayReadReg(readStatusReg());
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < _jed.nb_section(); i++) {
|
for (size_t i = 0; i < _jed.nb_section(); i++) {
|
||||||
string note = _jed.noteForSection(i);
|
string note = _jed.noteForSection(i);
|
||||||
if (note == "TAG DATA") {
|
if (note == "TAG DATA") {
|
||||||
|
|
@ -208,7 +333,7 @@ void Lattice::program(unsigned int offset)
|
||||||
printInfo("Flash erase: ", false);
|
printInfo("Flash erase: ", false);
|
||||||
if (flashErase(eraseMode) == false) {
|
if (flashErase(eraseMode) == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
@ -220,9 +345,9 @@ void Lattice::program(unsigned int offset)
|
||||||
|
|
||||||
/* flash UFM */
|
/* flash UFM */
|
||||||
if (false == flashProg(0, cfg_data))
|
if (false == flashProg(0, cfg_data))
|
||||||
return;
|
return false;
|
||||||
if (Verify(_jed) == false)
|
if (Verify(_jed) == false)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
/* missing usercode update */
|
/* missing usercode update */
|
||||||
|
|
||||||
|
|
@ -236,7 +361,7 @@ void Lattice::program(unsigned int offset)
|
||||||
printInfo("Program features Row: ", false);
|
printInfo("Program features Row: ", false);
|
||||||
if (writeFeaturesRow(_jed.featuresRow(), true) == false) {
|
if (writeFeaturesRow(_jed.featuresRow(), true) == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +369,7 @@ void Lattice::program(unsigned int offset)
|
||||||
printInfo("Program feabits: ", false);
|
printInfo("Program feabits: ", false);
|
||||||
if (writeFeabits(_jed.feabits(), true) == false) {
|
if (writeFeabits(_jed.feabits(), true) == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
@ -254,32 +379,44 @@ void Lattice::program(unsigned int offset)
|
||||||
printInfo("Write program Done: ", false);
|
printInfo("Write program Done: ", false);
|
||||||
if (writeProgramDone() == false) {
|
if (writeProgramDone() == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bypass */
|
/* bypass */
|
||||||
wr_rd(0xff, NULL, 0, NULL, 0);
|
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||||
/* disable configuration mode */
|
/* disable configuration mode */
|
||||||
printInfo("Disable configuration: ", false);
|
printInfo("Disable configuration: ", false);
|
||||||
if (!DisableISC()) {
|
if (!DisableISC()) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
/* ISC REFRESH 0x26 */
|
|
||||||
|
/* ISC REFRESH 0x79 */
|
||||||
printInfo("Refresh: ", false);
|
printInfo("Refresh: ", false);
|
||||||
if (loadConfiguration() == false) {
|
if (loadConfiguration() == false) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bypass */
|
/* bypass */
|
||||||
wr_rd(0xff, NULL, 0, NULL, 0);
|
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||||
_jtag->go_test_logic_reset();
|
_jtag->go_test_logic_reset();
|
||||||
return;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lattice::program(unsigned int offset)
|
||||||
|
{
|
||||||
|
if (_mode == FLASH_MODE)
|
||||||
|
program_flash(offset);
|
||||||
|
else if (_mode == MEM_MODE)
|
||||||
|
program_mem();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lattice::EnableISC(uint8_t flash_mode)
|
bool Lattice::EnableISC(uint8_t flash_mode)
|
||||||
|
|
@ -335,6 +472,16 @@ int Lattice::idCode()
|
||||||
device_id[0];
|
device_id[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Lattice::userCode()
|
||||||
|
{
|
||||||
|
uint8_t usercode[4];
|
||||||
|
wr_rd(0xC0, NULL, 0, usercode, 4);
|
||||||
|
return usercode[3] << 24 |
|
||||||
|
usercode[2] << 16 |
|
||||||
|
usercode[1] << 8 |
|
||||||
|
usercode[0];
|
||||||
|
}
|
||||||
|
|
||||||
bool Lattice::checkID()
|
bool Lattice::checkID()
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,17 @@
|
||||||
#include "ftdijtag.hpp"
|
#include "ftdijtag.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "jedParser.hpp"
|
#include "jedParser.hpp"
|
||||||
|
#include "latticeBitParser.hpp"
|
||||||
|
|
||||||
class Lattice: public Device {
|
class Lattice: public Device {
|
||||||
public:
|
public:
|
||||||
Lattice(FtdiJtag *jtag, std::string filename, bool verbose);
|
Lattice(FtdiJtag *jtag, std::string filename, bool verbose);
|
||||||
int idCode() override;
|
int idCode() override;
|
||||||
|
int userCode();
|
||||||
void reset() override {}
|
void reset() override {}
|
||||||
void program(unsigned int offset) override;
|
void program(unsigned int offset) override;
|
||||||
|
bool program_mem();
|
||||||
|
bool program_flash(unsigned int offset);
|
||||||
bool Verify(JedParser &_jed, bool unlock = false);
|
bool Verify(JedParser &_jed, bool unlock = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue