Skip to content

Commit e1d0749

Browse files
committed
lattice: fixed ECP3 support: now working
1 parent fb55a2d commit e1d0749

File tree

2 files changed

+151
-48
lines changed

2 files changed

+151
-48
lines changed

src/lattice.cpp

Lines changed: 148 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#include <string.h>
1313
#include <unistd.h>
1414

15+
#include <iomanip>
1516
#include <iostream>
17+
#include <list>
1618
#include <stdexcept>
1719

1820
#include "jtag.hpp"
@@ -280,9 +282,17 @@ bool Lattice::checkStatus(uint64_t val, uint64_t mask)
280282
return ((reg & mask) == val) ? true : false;
281283
}
282284

285+
void Lattice::usleep_ecp3(uint64_t us_time)
286+
{
287+
const uint32_t clk_period = 1e9/static_cast<float>(_jtag->getClkFreq());
288+
const uint32_t clk_len = (us_time * 1000) / clk_period;
289+
_jtag->toggleClk((us_time * 1000) / clk_period, 0); // 0.5s
290+
}
291+
283292
bool Lattice::program_mem()
284293
{
285294
bool err;
295+
286296
LatticeBitParser _bit(_filename, false, _verbose);
287297

288298
printInfo("Open file: ", false);
@@ -376,8 +386,8 @@ bool Lattice::program_mem()
376386
case ECP3_FAMILY:
377387
wr_rd(ECP3_LSCC_REFRESH, NULL, 0, NULL, 0);
378388
_jtag->set_state(Jtag::RUN_TEST_IDLE);
379-
_jtag->toggleClk(5e8 / clk_period); // 0.5s
380-
displayReadReg(readStatusReg());
389+
_jtag->toggleClk(5, 1);
390+
usleep_ecp3(500000); // 0.5s
381391
was_refreshed = false;
382392
break;
383393
default:
@@ -431,7 +441,9 @@ bool Lattice::program_mem()
431441
uint32_t dummy = 0xffffffff;
432442
wr_rd(ECP3_ISC_PROGRAM_USERCODE, (uint8_t *)&dummy, 4, NULL, 0);
433443
_jtag->set_state(Jtag::RUN_TEST_IDLE);
434-
_jtag->toggleClk(2e6 / clk_period); // 2ms
444+
_jtag->toggleClk(5, 1);
445+
usleep_ecp3(2000); // 2ms
446+
435447
uint32_t rx = 0;
436448
wr_rd(ECP3_READ_USERCODE, (uint8_t *)&dummy, 4, (uint8_t *)&rx, 4);
437449
if (rx != 0xffffffff) {
@@ -462,8 +474,10 @@ bool Lattice::program_mem()
462474
if (_fpga_family == ECP3_FAMILY) {
463475
wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
464476
_jtag->set_state(Jtag::RUN_TEST_IDLE);
465-
_jtag->toggleClk(2e6 / clk_period); // 2ms
466-
/* read user code */
477+
_jtag->toggleClk(5);
478+
usleep_ecp3(2000); // 2ms
479+
480+
/* read user code (User Code register must have all bit set cleared) */
467481
const uint32_t dummy = 0xffffffff;
468482
uint32_t rx = 0;
469483
wr_rd(ECP3_READ_USERCODE, (uint8_t *)&dummy, 4, (uint8_t *)&rx, 4);
@@ -482,6 +496,12 @@ bool Lattice::program_mem()
482496
const uint8_t *data = _bit.getData();
483497
int length = _bit.getLength()/8;
484498
if (_fpga_family == ECP3_FAMILY) {
499+
/* Reset Address */
500+
wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
501+
_jtag->set_state(Jtag::RUN_TEST_IDLE);
502+
_jtag->toggleClk(5, 1);
503+
usleep_ecp3(2000); // 2ms
504+
485505
wr_rd(ECP3_LSCC_BITSTREAM_BURST, NULL, 0, NULL, 0);
486506
} else {
487507
wr_rd(0x7A, NULL, 0, NULL, 0);
@@ -510,51 +530,47 @@ bool Lattice::program_mem()
510530
}
511531

512532
_jtag->set_state(Jtag::RUN_TEST_IDLE);
533+
513534
if (_fpga_family == ECP3_FAMILY) {
514-
_jtag->toggleClk(200e6 / clk_period); // 200ms
515-
/* Verify USERCODE */
516-
uint8_t r[] = {0xff, 0xff, 0xff, 0xff};
517-
uint8_t t[4];
518-
wr_rd(0x17, r, 4, t, 4);
519-
printf("%02x %02x %02x %02x\n", t[0], t[1], t[2], t[3]);
520-
// isc disable
521-
wr_rd(0x1e, NULL, 0, NULL, 0);
522-
_jtag->set_state(Jtag::RUN_TEST_IDLE);
523-
_jtag->toggleClk(5);
524-
// bypass
525-
wr_rd(0xff, NULL, 0, NULL, 0);
526-
_jtag->set_state(Jtag::RUN_TEST_IDLE);
527-
_jtag->toggleClk(100);
528-
// Verify STATUS Register
529-
uint64_t status = readStatusReg();
530-
printf("status %08x %08x\n", status, status & 0x60007);
531-
displayReadReg(status);
532-
return true;
535+
_jtag->toggleClk(256, 1);
536+
usleep_ecp3(2000);
537+
538+
/* Verifiy User Code register */
539+
uint32_t rx = 0;
540+
uint8_t dummy[] = {0xff, 0xff, 0xff, 0xff};
541+
wr_rd(ECP3_READ_USERCODE, dummy, 4, (uint8_t *)&rx, 4);
542+
if (rx != 0x00000000) {
543+
char message[256];
544+
snprintf(message, 256, "failed: 0x%08x instead of 0x00000000", rx);
545+
printError(message);
546+
return false;
547+
}
533548
} else {
534549
_jtag->toggleClk(1000);
535550
}
536551

537-
uint32_t status_mask;
538-
if (_fpga_family == MACHXO3D_FAMILY)
539-
status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK;
540-
else
541-
status_mask = REG_STATUS_CNF_CHK_MASK;
552+
if (_fpga_family != ECP3_FAMILY) {
553+
uint32_t status_mask;
554+
if (_fpga_family == MACHXO3D_FAMILY)
555+
status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK;
556+
else
557+
status_mask = REG_STATUS_CNF_CHK_MASK;
542558

543-
if (checkStatus(0, status_mask)) {
544-
progress.done();
545-
} else {
546-
progress.fail();
547-
displayReadReg(readStatusReg());
548-
return false;
549-
}
559+
if (checkStatus(0, status_mask)) {
560+
progress.done();
561+
} else {
562+
progress.fail();
563+
displayReadReg(readStatusReg());
564+
return false;
565+
}
550566

551-
wr_rd(0xff, NULL, 0, NULL, 0);
567+
/* bypass */
568+
wr_rd(0xff, NULL, 0, NULL, 0);
569+
}
552570

553-
if (_verbose)
571+
if (_verbose && _fpga_family != ECP3_FAMILY)
554572
printf("userCode: %08x\n", userCode());
555573

556-
/* bypass */
557-
wr_rd(0xff, NULL, 0, NULL, 0);
558574
/* disable configuration mode */
559575
printInfo("Disable configuration: ", false);
560576
if (!DisableISC()) {
@@ -565,11 +581,23 @@ bool Lattice::program_mem()
565581
printSuccess("DONE");
566582
}
567583

584+
if (_fpga_family == ECP3_FAMILY) {
585+
/* Bypass */
586+
wr_rd(0xff, NULL, 0, NULL, 0);
587+
_jtag->set_state(Jtag::RUN_TEST_IDLE);
588+
_jtag->toggleClk(100, 1);
589+
usleep_ecp3(1000);
590+
591+
// Verify STATUS Register
592+
uint64_t status = readStatusReg();
593+
printf("status %08x %08x\n", status, status & 0x60007);
594+
displayReadReg(status);
595+
_jtag->toggleClk(5, 1);
596+
}
597+
568598
if (_verbose)
569599
displayReadReg(readStatusReg());
570600

571-
/* bypass */
572-
wr_rd(0xff, NULL, 0, NULL, 0);
573601
_jtag->go_test_logic_reset();
574602
return true;
575603
}
@@ -989,11 +1017,10 @@ void Lattice::program(unsigned int offset, bool unprotect_flash)
9891017
bool Lattice::EnableISC(uint8_t flash_mode)
9901018
{
9911019
if (_fpga_family == ECP3_FAMILY) {
992-
const uint32_t clk_period = 1e9/static_cast<float>(_jtag->getClkFreq());
993-
const uint32_t clk_len = 2e7 / clk_period;
9941020
wr_rd(ECP3_ISC_ENABLE, NULL, 0, NULL, 0);
9951021
_jtag->set_state(Jtag::RUN_TEST_IDLE);
996-
_jtag->toggleClk(clk_len);
1022+
_jtag->toggleClk(5, 1); // 0.5s
1023+
usleep_ecp3(20000); // 0.20s
9971024
return true;
9981025
}
9991026

@@ -1010,6 +1037,13 @@ bool Lattice::EnableISC(uint8_t flash_mode)
10101037

10111038
bool Lattice::DisableISC()
10121039
{
1040+
if (_fpga_family == ECP3_FAMILY) {
1041+
/** Shift in ISC DISABLE instruction */
1042+
_jtag->shiftIR(0x1E, 8, Jtag::RUN_TEST_IDLE);
1043+
_jtag->toggleClk(5, 1);
1044+
usleep_ecp3(200000);
1045+
return true;
1046+
}
10131047
wr_rd(ISC_DISABLE, NULL, 0, NULL, 0);
10141048
_jtag->set_state(Jtag::RUN_TEST_IDLE);
10151049
_jtag->toggleClk(1000);
@@ -1153,8 +1187,75 @@ bool Lattice::wr_rd(uint8_t cmd,
11531187
return true;
11541188
}
11551189

1190+
typedef struct {
1191+
std::string description;
1192+
uint8_t offset;
1193+
uint8_t size;
1194+
std::map<int, std::string> reg_cnt;
1195+
} reg_struct_t;
1196+
1197+
#define REG_ENTRY(_description, _offset, _size, ...) \
1198+
{_description, _offset, _size, {__VA_ARGS__}}
1199+
1200+
static const std::map<std::string, std::list<reg_struct_t>> reg_content = {
1201+
{"StatusRegister", std::list<reg_struct_t>{
1202+
REG_ENTRY("CRC Error", 0, 1, {0, "OK"}, {1, "KO"}),
1203+
REG_ENTRY("ID Verify failed", 1, 1, {0, "No"}, {1, "Yes"}),
1204+
REG_ENTRY("Invalid Command", 2, 1, {0, "No"}, {1, "Yes"}),
1205+
REG_ENTRY("SPIm Mode Error", 3, 1, {0, "No"}, {1, "Yes"}),
1206+
REG_ENTRY("Device locked", 4, 1, {0, "No"}, {1, "Yes"}),
1207+
REG_ENTRY("Key Fire", 5, 1, {0, "No"}, {1, "Yes"}),
1208+
REG_ENTRY("Alignement Preamble", 6, 1, {0, "No"}, {1, "Yes"}),
1209+
REG_ENTRY("Encryption Preamble", 7, 1, {0, "No"}, {1, "Yes"}),
1210+
REG_ENTRY("Std Preamble", 8, 1, {0, "No"}, {1, "Yes"}),
1211+
REG_ENTRY("HFC", 9, 1, {0, "No"}, {1, "Yes"}),
1212+
REG_ENTRY("Memory Cleared", 15, 1, {0, "No"}, {1, "Yes"}),
1213+
REG_ENTRY("Device Secured", 16, 1, {0, "No"}, {1, "Yes"}),
1214+
REG_ENTRY("Device Configured", 17, 1, {0, "No"}, {1, "Yes"}),
1215+
REG_ENTRY("Non-JTAG Mode", 18, 1, {0, "No"}, {1, "Yes"}),
1216+
REG_ENTRY("ReadBack Mode", 19, 1, {0, "No"}, {1, "Yes"}),
1217+
REG_ENTRY("Bypass Mode", 20, 1, {0, "No"}, {1, "Yes"}),
1218+
REG_ENTRY("Flow Trough", 21, 1, {0, "No"}, {1, "Yes"}),
1219+
REG_ENTRY("Configuration Mode", 22, 1, {0, "No"}, {1, "Yes"}),
1220+
REG_ENTRY("Transparent Mode", 23, 1, {0, "No"}, {1, "Yes"}),
1221+
}},
1222+
};
1223+
11561224
void Lattice::displayReadReg(uint64_t dev)
11571225
{
1226+
if (_fpga_family == ECP3_FAMILY) {
1227+
auto reg = reg_content.find("StatusRegister");
1228+
if (reg == reg_content.end()) {
1229+
printError("Unknown register StatusRegister");
1230+
return;
1231+
}
1232+
1233+
std::stringstream raw_val;
1234+
raw_val << "0x" << std::hex << dev;
1235+
printSuccess("Register raw value: " + raw_val.str());
1236+
1237+
const std::list<reg_struct_t> regs = reg->second;
1238+
for (reg_struct_t r: regs) {
1239+
uint8_t offset = r.offset;
1240+
uint8_t size = r.size;
1241+
uint32_t mask = (1 << size) - 1;
1242+
uint32_t val = (dev >> offset) & mask;
1243+
std::stringstream ss, desc;
1244+
desc << r.description;
1245+
ss << std::setw(20) << std::left << r.description;
1246+
if (r.reg_cnt.size() != 0) {
1247+
ss << r.reg_cnt[val];
1248+
} else {
1249+
std::stringstream hex_val;
1250+
hex_val << "0x" << std::hex << val;
1251+
ss << hex_val.str();
1252+
}
1253+
1254+
printInfo(ss.str());
1255+
}
1256+
return;
1257+
}
1258+
11581259
uint8_t err;
11591260
printf("displayReadReg\n");
11601261
if (dev & 1<<0) printf("\tTRAN Mode\n");
@@ -1349,11 +1450,10 @@ bool Lattice::flashErase(uint32_t mask)
13491450
};
13501451
wr_rd(FLASH_ERASE, tx, 2, NULL, 0);
13511452
} else if (_fpga_family == ECP3_FAMILY) {
1352-
const uint32_t clk_period = 1e9/static_cast<float>(_jtag->getClkFreq());
1353-
const uint32_t clk_len = 2e7 / clk_period;
13541453
wr_rd(ECP3_ISC_ERASE, NULL, 0, NULL, 0);
13551454
_jtag->set_state(Jtag::RUN_TEST_IDLE);
1356-
_jtag->toggleClk(clk_len);
1455+
_jtag->toggleClk(5, 1);
1456+
usleep_ecp3(2000000); // 2s
13571457
return true;
13581458
} else {
13591459
uint8_t tx[1] = {(uint8_t)(mask & 0xff)};

src/lattice.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ class Lattice: public Device, SPIInterface {
123123
/* test */
124124
bool checkID();
125125

126+
/************************* MODS for ECP3 ******************************/
127+
void usleep_ecp3(uint64_t us_time);
128+
126129
/*********************** MODS FOR MacXO3D *****************************/
127130
enum lattice_flash_sector_t {
128131
LATTICE_FLASH_UNDEFINED = 0,

0 commit comments

Comments
 (0)