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+
283292bool 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)
9891017bool 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
10111038bool 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+
11561224void 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 (" \t TRAN 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 )};
0 commit comments