Загрузка данных
#include <fstream> // Обязательно добавьте этот инклуд в начало файла, если его там нет
bool Lattice::program_mem()
{
bool err;
LatticeBitParser _bit(_filename, false, false, _verbose);
printInfo("Open file: ", false);
printSuccess("DONE");
err = _bit.parse();
printInfo("Parse file: ", false);
if (err == EXIT_FAILURE) {
printError("FAIL");
return false;
} else {
printSuccess("DONE");
}
if (_verbose)
_bit.displayHeader();
#ifndef MY_CODE
readStatusReg();
#endif
/* read ID Code 0xE0 and compare to bitstream */
uint32_t bit_idcode = std::stoul(_bit.getHeaderVal("idcode").c_str(), NULL, 16);
uint32_t idcode = idCode();
#if 1//def MY_CODE
if (idcode != bit_idcode) {
char mess[256];
snprintf(mess, 256, "mismatch between target's idcode and bitstream idcode\n"
"\tbitstream has 0x%08X hardware requires 0x%08x", bit_idcode, idcode);
printError(mess);
return false;
}
#endif
if (_verbose) {
printf("IDCode : %x\n", idcode);
displayReadReg(readStatusReg());
}
/* The command code 0x1C is not listed in the manual?
* PRELOAD/SAMPLE 0x1C
* For NEXUS family fpgas, the Bscan register is 362 bits long or
* 45.25 bytes => 46 bytes
* For ECP3 family fpgas, the Bscan register is 1077 bits long or
* 134.62 bytes => 135 bytes
*/
preload();
/* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin"
* We REFRESH only if the fpga is in a status of error due to
* the previous bitstream. For example, this happens if
* no bitstream is present on the SPI FLASH
*/
/*flag to understand if we refreshed or not*/
bool was_refreshed;
switch (_fpga_family) {
case NEXUS_FAMILY:
break;
case ECP3_FAMILY:
wr_rd(ECP3_LSCC_REFRESH, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(5, 1);
usleep_ecp3(500000); // 0.5s
was_refreshed = false;
break;
default:
was_refreshed = false;
}
/* ISC Enable 0xC6 */
printInfo("Enable configuration: ", false);
if (!EnableISC(0x00)) {
printError("FAIL");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
if (_fpga_family == NEXUS_FAMILY) {
wr_rd(REFRESH, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2);
/* LSC_DEVICE_CONTROL 0x7D -- configuration reset */
printInfo("Configuration Logic Reset: ", false);
uint8_t tx_tmp[1] = {0x08};
wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000);
if(!pollBusyFlag()) {
printError("FAIL");
return false;
}
tx_tmp[0] = 0x00;
wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000);
if(!pollBusyFlag()) {
printError("FAIL");
return false;
}
printSuccess("DONE");
}
if (_fpga_family == ECP3_FAMILY) {
if (!write_userCode(0xffffffff))
return false;
}
/* ISC ERASE
* For Nexus family (from svf file): 1 byte to tx 0x00
*/
printInfo("SRAM erase: ", false);
uint32_t mask_erase[1] = {FLASH_ERASE_SRAM};
if (_fpga_family == NEXUS_FAMILY){
mask_erase[0] = 0x00;
}
if (flashErase(mask_erase[0]) == false) {
printError("FAIL");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
if (_fpga_family == NEXUS_FAMILY) {
printInfo("SRAM erase check: ", false);
uint64_t status = readStatusReg();
if ((status & 0x000000000002100) != 0) {
printError("FAIL");
return false;
} else {
printSuccess("DONE");
}
}
/* LSC_INIT_ADDRESS */
if (_fpga_family == ECP3_FAMILY) {
wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(5);
usleep_ecp3(2000); // 2ms
/* read user code (User Code register must have all bit set cleared) */
const uint32_t dummy = 0xffffffff;
uint32_t rx = 0;
wr_rd(ECP3_READ_USERCODE, (uint8_t *)&dummy, 4, (uint8_t *)&rx, 4);
if (rx != 0x00000000) {
char message[256];
snprintf(message, 256, "failed: 0x%08x instead of 0xffffffff", rx);
printError(message);
return false;
}
} else {
wr_rd(RESET_CFG_ADDR, NULL, 0, NULL, 0); // LSC_INIT_ADDRESS
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000);
}
const uint8_t *data = _bit.getData();
int length = _bit.getLength()/8;
printf("%s(%d) length=%u\n",__FUNCTION__,__LINE__,length);
if (_fpga_family == ECP3_FAMILY) {
/* Reset Address */
wr_rd(ECP3_RESET_ADDRESS, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(5, 1);
usleep_ecp3(2000); // 2ms
wr_rd(ECP3_LSCC_BITSTREAM_BURST, NULL, 0, NULL, 0);
} else {
wr_rd(LSC_BITSTREAM_BURST, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(2);
}
uint8_t tmp[1024];
int size = 1024;
Jtag::tapState_t next_state = Jtag::SHIFT_DR;
ProgressBar progress("Loading", length, 50, _quiet);
// ==================== НАЧАЛО ИЗМЕНЕНИЙ СТРИМ-ДАМПА ====================
std::ofstream dump_file("jtag_stream_dump.bin", std::ios::out | std::ios::binary);
if (!dump_file.is_open()) {
printError("Failed to open jtag_stream_dump.bin for writing!");
}
// ======================================================================
for (int i = 0; i < length; i += size) {
progress.display(i);
if (length < i + size) {
size = length-i;
next_state = Jtag::RUN_TEST_IDLE;
}
printf("%d)\n",i);
for (int ii = 0; ii < size; ii++) {
tmp[ii] = ConfigBitstreamParser::reverseByte(data[i+ii]);
#ifndef MY_CODE
printf("0x%X ",tmp[ii]);
#endif
}
// ==================== ЗАПИСЬ ДАННЫХ В ФАЙЛ ====================
if (dump_file.is_open()) {
dump_file.write(reinterpret_cast<const char*>(tmp), size);
}
// ==============================================================
_jtag->shiftDR(tmp, NULL, size * 8, next_state);
}
// ==================== КОРРЕКТНОЕ ЗАКРЫТИЕ ФАЙЛА ====================
if (dump_file.is_open()) {
dump_file.close();
printInfo("JTAG stream dump saved to jtag_stream_dump.bin successfully.", true);
}
// ===================================================================
_jtag->set_state(Jtag::RUN_TEST_IDLE);
if (_fpga_family == ECP3_FAMILY) {
_jtag->toggleClk(256, 1);
usleep_ecp3(2000);
/* Verifiy User Code register */
uint32_t rx = userCode();
if (rx != 0x00000000) {
progress.fail();
char message[256];
snprintf(message, 256, "failed: 0x%08x instead of 0x00000000", rx);
printError(message);
return false;
}
progress.done();
} else {
_jtag->toggleClk(1000);
uint32_t status_mask;
uint32_t status_val = 0;
if (_fpga_family == MACHXO3D_FAMILY)
status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK;
else if (_fpga_family == NEXUS_FAMILY) {
status_val = REG_STATUS_DONE;
status_mask = REG_STATUS_DONE | REG_STATUS_BUSY | REG_STATUS_FAIL
| REG_NEXUS_STATUS_BSE_ERR_MASK;
}
else
status_mask = REG_STATUS_CNF_CHK_MASK;
if (checkStatus(status_val, status_mask)) {
progress.done();
} else {
progress.fail();
displayReadReg(readStatusReg());
return false;
}
/* bypass */
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");
displayReadReg(readStatusReg());
return false;
} else {
printSuccess("DONE");
}
if (_fpga_family == ECP3_FAMILY) {
/* Bypass */
wr_rd(0xff, NULL, 0, NULL, 0);
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(100, 1);
usleep_ecp3(1000);
// Verify STATUS Register
uint64_t status = readStatusReg();
_jtag->toggleClk(5, 1);
if ((status & 0x60007) != 0x20000) {
char message[256];
snprintf(message, 256, "Programming failed: status 0x%" PRIx64 "instead of 0x20000", status);
printError(message);
displayReadReg(status);
return false;
}
}
if (_verbose)
displayReadReg(readStatusReg());
/* bypass */
wr_rd(0xff, NULL, 0, NULL, 0);
if (_fpga_family == NEXUS_FAMILY) {
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(100);
usleep_ecp3(1000000);
}
_jtag->go_test_logic_reset();
return true;
}