adding support for MachXO3D
This commit is contained in:
parent
3b15a633fa
commit
b6979f54f7
|
|
@ -72,6 +72,7 @@ set(OPENFPGALOADER_SOURCE
|
|||
src/epcq.cpp
|
||||
src/svf_jtag.cpp
|
||||
src/jedParser.cpp
|
||||
src/feaparser.cpp
|
||||
src/display.cpp
|
||||
src/jtag.cpp
|
||||
src/ftdiJtagBitbang.cpp
|
||||
|
|
@ -120,6 +121,7 @@ set(OPENFPGALOADER_HEADERS
|
|||
src/part.hpp
|
||||
src/board.hpp
|
||||
src/jedParser.hpp
|
||||
src/feaparser.hpp
|
||||
src/display.hpp
|
||||
src/mcsParser.hpp
|
||||
src/ftdipp_mpsse.hpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,225 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Martin Beynon <martin.beynon@abaco.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "display.hpp"
|
||||
#include "feaparser.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
FeaParser::FeaParser(string filename, bool verbose):
|
||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose),
|
||||
_feabits(0), _has_feabits(false)
|
||||
{
|
||||
for (int i=0; i < 3; i++)
|
||||
_featuresRow[i] = 0;
|
||||
}
|
||||
|
||||
/* fill a vector with consecutive lines, begining with 0 or 1, until EOF
|
||||
* \brief read a line with '\r''\n' or '\n' termination
|
||||
* check if last char is '\r'
|
||||
* \return a vector of lines without [\r]\n
|
||||
*/
|
||||
vector<string> FeaParser::readFeaFile()
|
||||
{
|
||||
vector<string> lines;
|
||||
|
||||
while (true) {
|
||||
string buffer;
|
||||
std::getline(_ss, buffer, '\n');
|
||||
if (buffer.empty())
|
||||
break;
|
||||
|
||||
/* if '\r' is present -> drop */
|
||||
if (buffer.back() == '\r')
|
||||
buffer.pop_back();
|
||||
|
||||
if (buffer.front() == '0' || buffer.front() == '1')
|
||||
lines.push_back(buffer);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
void FeaParser::displayHeader()
|
||||
{
|
||||
if (_has_feabits) {
|
||||
printf("\nFeature Row: [0x");
|
||||
for(int i = 2; i >= 0; i--) {
|
||||
printf("%08x", _featuresRow[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("\tCore Clock Select : 0x%x\n", (_featuresRow[2] >> 30) & 0x03);
|
||||
printf("\tCPU : %d\n",
|
||||
((_featuresRow[2] & FEATURE_CPU)? 1 : 0));
|
||||
printf("\tSSPI Auto : %s\n",
|
||||
((_featuresRow[2] & FEATURE_SSPI_AUTO)?"Enabled":"Disabled"));
|
||||
printf("\tReserved Zero (1) : 0x%x\n", (_featuresRow[2] >> 27) & 0x01);
|
||||
printf("\tEBR Enable : %s\n",
|
||||
((_featuresRow[2] & FEATURE_EBR_ENABLE)?"Yes":"No"));
|
||||
printf("\tHSE Clock Select : 0x%x\n", (_featuresRow[2] >> 24) & 0x03);
|
||||
printf("\tCPHA : %s\n",
|
||||
((_featuresRow[2] & FEATURE_CPHA)?"Enabled":"Disabled"));
|
||||
printf("\tCPOL : %s\n",
|
||||
((_featuresRow[2] & FEATURE_CPOL)?"Enabled":"Disabled"));
|
||||
printf("\tTx Edge : %s\n",
|
||||
((_featuresRow[2] & FEATURE_TX_EDGE)?"Enabled":"Disabled"));
|
||||
printf("\tRx Edge : %s\n",
|
||||
((_featuresRow[2] & FEATURE_RX_EDGE)?"Enabled":"Disabled"));
|
||||
printf("\tLSBF : %s\n",
|
||||
((_featuresRow[2] & FEATURE_LSBF)?"Enabled":"Disabled"));
|
||||
printf("\tMClock Bypass : %s\n",
|
||||
((_featuresRow[2] & FEATURE_MCLK_BYPASS)?"Enabled":"Disabled"));
|
||||
printf("\t32-bit SPIM : %s\n",
|
||||
((_featuresRow[2] & FEATURE_32BIT_SPIM)?"Enabled":"Disabled"));
|
||||
printf("\tBulk Erase Disable : %s\n",
|
||||
((_featuresRow[2] & FEATURE_BULK_ERASE_DISABLE)?"Yes":"No"));
|
||||
printf("\tSFDP Enable : %s\n",
|
||||
((_featuresRow[2] & FEATURE_SFDP_EN)?"Yes":"No"));
|
||||
printf("\tSFDP Continue on Fail : %s\n",
|
||||
((_featuresRow[2] & FEATURE_SFDP_CONT_FAIL)?"Yes":"No"));
|
||||
printf("\tReserved Zero (2) : 0x%x\n", (_featuresRow[2] >> 12) & 0x03);
|
||||
printf("\tSlave Idle Timer Count: %d\n", (_featuresRow[2] >> 8) & 0x0f);
|
||||
printf("\tMaster Timer Count : %d\n", (_featuresRow[2] >> 4) & 0x0f);
|
||||
printf("\tMaster Retry Count : %d\n", (_featuresRow[2] >> 2) & 0x03);
|
||||
printf("\tReserved Zero (2) : 0x%x\n", _featuresRow[2] & 0x03);
|
||||
|
||||
printf("\tDual Boot Address : 0x%x\n", (_featuresRow[1] >> 16) & 0xffff);
|
||||
printf("\tI2C Slave Address : 0x%x\n", (_featuresRow[1] >> 8) & 0xff);
|
||||
printf("\tCustom Trace ID : 0x%x\n", _featuresRow[1] & 0xff);
|
||||
printf("\tCustom ID Code : 0x%x\n", _featuresRow[0]);
|
||||
|
||||
|
||||
printf("\nFEAbits: [0x%08x]\n", _feabits);
|
||||
printf("\tReserved Zero (16) : 0x%x\n", (_feabits >> 17) & 0xffff);
|
||||
printf("\tRollback Protection : %s\n",
|
||||
((_feabits & FEA_VERSION_RB_PROT)?"Enabled":"Disabled"));
|
||||
printf("\tI2C Deglitch Range : %s\n",
|
||||
((_feabits & FEA_I2C_DG_RANGE_SEL)?"(1) 16 to 50 ns":"(0) 8 to 25 ns"));
|
||||
int boot_mode = (_feabits >> 12) & 0x07;
|
||||
printf("\tBoot Mode : ");
|
||||
if ((_feabits & FEA_MSPI_PERSIST) == 0) {
|
||||
if (boot_mode == 0)
|
||||
printf("Dual Boot, CFG0 - CFG1\n");
|
||||
else if (boot_mode == 1)
|
||||
printf("Dual Boot, CFG1 - CFG0\n");
|
||||
else if (boot_mode == 3)
|
||||
printf("Single Boot, CFG0\n");
|
||||
else if (boot_mode == 4)
|
||||
printf("Single Boot, CFG1\n");
|
||||
else if (boot_mode == 5)
|
||||
printf("Dual Boot, Boot from former bitstream first\n");
|
||||
else if (boot_mode == 7)
|
||||
printf("Dual Boot, Boot from latter bitstream first\n");
|
||||
else if ((boot_mode & 0x03) == 2)
|
||||
printf("Dual Boot, No Boot\n");
|
||||
else
|
||||
printf("Unknown boot sequence selection");
|
||||
}
|
||||
else {
|
||||
if (boot_mode == 0)
|
||||
printf("Dual Boot, CFG0 - Ext\n");
|
||||
else if ((boot_mode & 0x03) == 1)
|
||||
printf("Single Boot, Ext\n");
|
||||
else if (boot_mode == 2)
|
||||
printf("Dual Boot, Ext - CFG0\n");
|
||||
else if ((boot_mode & 0x03) == 3)
|
||||
printf("Dual Boot, Ext - Ext\n");
|
||||
else if (boot_mode == 4)
|
||||
printf("Dual Boot, CFG1 - Ext\n");
|
||||
else if (boot_mode == 6)
|
||||
printf("Dual Boot, Ext - CFG1\n");
|
||||
else
|
||||
printf("Unknown boot sequence selection");
|
||||
}
|
||||
printf("\tMSPI Enable : %s\n",
|
||||
((_feabits & FEA_MSPI_PERSIST)?"Yes":"No"));
|
||||
printf("\tI2C Disable : %s\n",
|
||||
((_feabits & FEA_I2C_PERSIST)?"Yes":"No"));
|
||||
printf("\tSSPI Disable : %s\n",
|
||||
((_feabits & FEA_SSPI_PERSIST)?"Yes":"No"));
|
||||
printf("\tJTAG Disable : %s\n",
|
||||
((_feabits & FEA_JTAG_PERSIST)?"Yes":"No"));
|
||||
printf("\tDONE Enable : %s\n",
|
||||
((_feabits & FEA_DONE_PERSIST)?"Yes":"No"));
|
||||
printf("\tINIT Enable : %s\n",
|
||||
((_feabits & FEA_INITN_PERSIST)?"Yes":"No"));
|
||||
printf("\tPROGRAM Disable : %s\n",
|
||||
((_feabits & FEA_PROG_PERSIST)?"Yes":"No"));
|
||||
printf("\tCustom ID Enable : %s\n",
|
||||
((_feabits & FEA_MY_ASSP_EN)?"Yes":"No"));
|
||||
|
||||
int flash_prot = (_feabits >> 1) & 0x07;
|
||||
printf("\tFlash Protection : ");
|
||||
if (flash_prot == 0) {
|
||||
printf("None\n");
|
||||
}
|
||||
else {
|
||||
if (flash_prot & 0x04)
|
||||
printf("CFG0 & CFG1 ");
|
||||
if (flash_prot & 0x02)
|
||||
printf("Feature, Security Keys ");
|
||||
if (flash_prot & 0x01)
|
||||
printf("All UFMs");
|
||||
printf("\n");
|
||||
}
|
||||
printf("\tI2C Deglitch Filter : %s\n",
|
||||
((_feabits & FEA_I2C_DG_FIL_EN)?"Enabled":"Disabled"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Features Row & Feabits - this data is in a separate .fea file (MachXO3D)
|
||||
* DATA:
|
||||
* 1: xxxx\n : feature Row (96 bits)
|
||||
* 2: yyyy*\n : feabits (32 bits)
|
||||
*/
|
||||
void FeaParser::parseFeatureRowAndFeabits(const vector<string> &content)
|
||||
{
|
||||
printf("Parsing Feature Row & FEAbits...\n");
|
||||
|
||||
string featuresRow = content[0];
|
||||
//printf("Features: [%s]\n", featuresRow.c_str());
|
||||
for (size_t i = 0; i < featuresRow.size(); i++)
|
||||
_featuresRow[3 - (i/32) - 1] |= ((featuresRow[i] - '0') << (32 - (i%32) - 1));
|
||||
|
||||
string feabits = content[1];
|
||||
//printf("Feabits: [%s]\n", feabits.c_str());
|
||||
_feabits = 0;
|
||||
for (size_t i = 0; i < feabits.size(); i++) {
|
||||
_feabits |= ((feabits[i] - '0') << (feabits.size() - i - 1));
|
||||
}
|
||||
}
|
||||
|
||||
int FeaParser::parse()
|
||||
{
|
||||
_ss.str(_raw_data);
|
||||
|
||||
std::vector<string>lines;
|
||||
int first_pos;
|
||||
char instr;
|
||||
|
||||
lines = readFeaFile();
|
||||
/* empty or end of file */
|
||||
if (lines.size() > 0) {
|
||||
parseFeatureRowAndFeabits(lines);
|
||||
_has_feabits = true;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Martin Beynon <martin.beynon@abaco.com>
|
||||
*/
|
||||
#ifndef FEAPARSER_HPP_
|
||||
#define FEAPARSER_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "configBitstreamParser.hpp"
|
||||
|
||||
/* FEAbits element defines */
|
||||
# define FEA_I2C_DG_FIL_EN (1 << 0) /* I2C deglitch filter enable for Primary I2C Port 0=Disabled (Default), 1=Enabled */
|
||||
# define FEA_FLASH_PROT_SEC_SEL (0x7 << 1) /* Flash Protection Sector Selection */
|
||||
# define FEA_MY_ASSP_EN (1 << 4) /* MY_ASSP Enabled 0=Disabled (Default), 1=Enabled */
|
||||
# define FEA_PROG_PERSIST (1 << 5) /* PROGRAMN Persistence 0=Enabled (Default), 1=Disabled */
|
||||
# define FEA_INITN_PERSIST (1 << 6) /* INITN Persistence 0=Disabled (Default), 1=Enabled */
|
||||
# define FEA_DONE_PERSIST (1 << 7) /* DONE Persistence 0=Disabled (Default), 1=Enabled */
|
||||
# define FEA_JTAG_PERSIST (1 << 8) /* JTAG Port Persistence 0=Enabled (Default), 1=Disabled */
|
||||
# define FEA_SSPI_PERSIST (1 << 9) /* Slave SPI Port Persistence 0=Enabled (Default), 1=Disabled */
|
||||
# define FEA_I2C_PERSIST (1 << 10) /* I²C Port Persistence 0=Enabled (Default), 1=Disabled */
|
||||
# define FEA_MSPI_PERSIST (1 << 11) /* Master SPI Port Persistence 0=Disabled (Default), 1=Enabled */
|
||||
# define FEA_BOOT_SEQ_SEL (0x07 << 12) /* Boot Sequence selection (used along with Master SPI Port Persistence bit) */
|
||||
# define FEA_I2C_DG_RANGE_SEL (1 << 15) /* I2C deglitch filter range selection on primary I2C port2 0= 8 to 25 ns range (Default) 1= 16 to 50 ns range */
|
||||
# define FEA_VERSION_RB_PROT (1 << 16) /* Version Rollback Protection1 0= Disabled (Default) 1= Enabled (Checks if current version of bitstream is similar to the one that is going to be downloaded) */
|
||||
# define FEA_RESERVED_ZERO (0xffff << 17)
|
||||
|
||||
/* Feature Row element defines */
|
||||
# define FEATURE_CUSTOM_ID (0xffffffff) /* 32 bits of Custom ID code */
|
||||
|
||||
# define FEATURE_TRACE_ID (0xff << 0) /* 8 bits for the user programmable TraceID */
|
||||
# define FEATURE_I2C_SLAVE_ADDR (0xff << 8) /* 8 bits for the user programmable I2C Slave Address */
|
||||
# define FEATURE_DUAL_BOOT_ADDR (0xffff << 16) /* 16 bits for Dual boot address (Most significant 16- bit of address for secondary boot from external flash) */
|
||||
|
||||
# define FEATURE_MASTER_RETRY_CNT (0x3 << 2) /* Master Retry Count */
|
||||
# define FEATURE_MASTER_TIMER_CNT (0x0f << 4) /* Master Timer Count */
|
||||
# define FEATURE_SLAVE_IDLE_TIMER_CNT (0x0f << 8) /* Slave Idle Timer Count */
|
||||
# define FEATURE_SFDP_CONT_FAIL (1 << 14) /* SFDP Continue on Fail */
|
||||
# define FEATURE_SFDP_EN (1 << 15) /* SFDP Enable */
|
||||
# define FEATURE_BULK_ERASE_DISABLE (1 << 16) /* No Bulk Erase */
|
||||
# define FEATURE_32BIT_SPIM (1 << 17) /* 32-bit SPIM */
|
||||
# define FEATURE_MCLK_BYPASS (1 << 18) /* MCLK Bypass */
|
||||
# define FEATURE_LSBF (1 << 19) /* LSBF */
|
||||
# define FEATURE_RX_EDGE (1 << 20)
|
||||
# define FEATURE_TX_EDGE (1 << 21)
|
||||
# define FEATURE_CPOL (1 << 22)
|
||||
# define FEATURE_CPHA (1 << 23)
|
||||
# define FEATURE_HSE_CLOCK_SEL (0x3 << 24)
|
||||
# define FEATURE_EBR_ENABLE (1 << 26)
|
||||
# define FEATURE_SSPI_AUTO (1 << 28) /* SSPI Auto */
|
||||
# define FEATURE_CPU (1 << 29) /* CPU */
|
||||
# define FEATURE_CORE_CLK_SEL (0x03 << 30) /* Core Clock Sel */
|
||||
|
||||
class FeaParser: public ConfigBitstreamParser {
|
||||
public:
|
||||
FeaParser(std::string filename, bool verbose = false);
|
||||
int parse() override;
|
||||
void displayHeader() override;
|
||||
|
||||
uint32_t* featuresRow() {return _featuresRow;}
|
||||
uint32_t feabits() {return _feabits;}
|
||||
|
||||
private:
|
||||
std::vector<std::string>readFeaFile();
|
||||
void parseFeatureRowAndFeabits(const std::vector<std::string> &content);
|
||||
|
||||
uint32_t _featuresRow[3];
|
||||
uint32_t _feabits;
|
||||
bool _has_feabits;
|
||||
|
||||
std::istringstream _ss;
|
||||
};
|
||||
|
||||
#endif // FEAPARSER_HPP_
|
||||
|
|
@ -33,6 +33,7 @@ class JedParser: public ConfigBitstreamParser {
|
|||
size_t offset_for_section(int id) {return _data_list[id].offset;}
|
||||
int len_for_section(int id) {return _data_list[id].len;}
|
||||
std::string get_fuselist() {return fuselist;}
|
||||
int get_fuse_count() {return _fuse_count;}
|
||||
std::vector<std::string> data_for_section(int id) {
|
||||
return _data_list[id].data;
|
||||
}
|
||||
|
|
|
|||
782
src/lattice.cpp
782
src/lattice.cpp
|
|
@ -25,46 +25,122 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define ISC_ENABLE 0xc6
|
||||
#define ISC_ENABLE 0xC6 /* ISC_ENABLE - Offline Mode */
|
||||
# define ISC_ENABLE_FLASH_MODE (1 << 3)
|
||||
# define ISC_ENABLE_SRAM_MODE (0 << 3)
|
||||
#define ISC_DISABLE 0x26
|
||||
#define READ_DEVICE_ID_CODE 0xE0
|
||||
#define FLASH_ERASE 0x0E
|
||||
#define ISC_ENABLE_TRANSPARANT 0x74 /* This command is used to put the device in transparent mode */
|
||||
#define ISC_DISABLE 0x26 /* ISC_DISABLE */
|
||||
#define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */
|
||||
#define FLASH_ERASE 0x0E /* ISC_ERASE */
|
||||
/* Flash areas as defined for Lattice MachXO3L/LF */
|
||||
# define FLASH_ERASE_UFM (1<<3)
|
||||
# define FLASH_ERASE_CFG (1<<2)
|
||||
# define FLASH_ERASE_FEATURE (1<<1)
|
||||
# define FLASH_ERASE_SRAM (1<<0)
|
||||
# define FLASH_ERASE_ALL 0x0F
|
||||
#define CHECK_BUSY_FLAG 0xF0
|
||||
# define CHECK_BUSY_FLAG_BUSY (1 << 7)
|
||||
#define RESET_CFG_ADDR 0x46
|
||||
#define PROG_CFG_FLASH 0x70
|
||||
#define REG_CFG_FLASH 0x73
|
||||
#define PROG_FEATURE_ROW 0xE4
|
||||
#define PROG_FEABITS 0xF8
|
||||
#define PROG_DONE 0x5E
|
||||
#define REFRESH 0x79
|
||||
|
||||
#define READ_FEATURE_ROW 0xE7
|
||||
#define READ_FEABITS 0xFB
|
||||
#define READ_STATUS_REGISTER 0x3C
|
||||
# define REG_STATUS_DONE (1 << 8)
|
||||
# define REG_STATUS_ISC_EN (1 << 9)
|
||||
# define REG_STATUS_BUSY (1 << 12)
|
||||
# define REG_STATUS_FAIL (1 << 13)
|
||||
# define REG_STATUS_CNF_CHK_MASK (0x7 << 23)
|
||||
# define REG_STATUS_EXEC_ERR (1 << 26)
|
||||
/* Flash areas as defined for Lattice MachXO3D, used with command: ISC_ERASE */
|
||||
# define FLASH_SEC_CFG0 (1<<8)
|
||||
# define FLASH_SEC_CFG1 (1<<9)
|
||||
# define FLASH_SEC_UFM0 (1<<10)
|
||||
# define FLASH_SEC_UFM1 (1<<11)
|
||||
# define FLASH_SEC_UFM2 (1<<12)
|
||||
# define FLASH_SEC_UFM3 (1<<13)
|
||||
// # define FLASH_SEC_CSEC (1<<14) /* not defined in later documentation */
|
||||
// # define FLASH_SEC_USEC (1<<15) /* not defined in later documentation */
|
||||
# define FLASH_SEC_PKEY (1<<16)
|
||||
# define FLASH_SEC_AKEY (1<<17)
|
||||
# define FLASH_SEC_FEA (1<<18)
|
||||
# define FLASH_SEC_ALL 0x7FF
|
||||
/* This uses the same defines as above (for ISC_ERASE)
|
||||
* The Lattice Standard Doc for MachXO3D has incorrect list of operands for this
|
||||
* command.
|
||||
* This is document is more correct:
|
||||
* fpga-tn-02119-1-1-using-hardened-control-functions-machxo3d-reference.pdf
|
||||
*/
|
||||
#define RESET_CFG_ADDR 0x46 /* LSC_INIT_ADDRESS */
|
||||
/* Set the Page Address pointer to the Flash page specified */
|
||||
#define LSC_WRITE_ADDRESS 0xB4
|
||||
# define FLASH_SET_ADDR_CFG0 0x00
|
||||
# define FLASH_SET_ADDR_UFM0 0x01
|
||||
# define FLASH_SET_ADDR_FEA 0x03
|
||||
# define FLASH_SET_ADDR_CFG1 0x04
|
||||
# define FLASH_SET_ADDR_UFM1 0x05
|
||||
# define FLASH_SET_ADDR_PKEY 0x06
|
||||
//# define FLASH_SET_ADDR_CSEC 0x07 /* not defined in later documentation */
|
||||
# define FLASH_SET_ADDR_UFM2 0x08
|
||||
# define FLASH_SET_ADDR_UFM3 0x09
|
||||
# define FLASH_SET_ADDR_AKEY 0x0A
|
||||
//# define FLASH_SET_ADDR_USEC 0x0B /* not defined in later documentation */
|
||||
/* Set the Page Address Pointer to the beginning of the UFM sectors.
|
||||
* It appears that this function is required when setting address to UFM sectors
|
||||
* The LSC_INIT_ADDRESS doesn't work when the sector is set to UFMx ... */
|
||||
#define LSC_INIT_ADDR_UFM 0x47
|
||||
# define FLASH_UFM_ADDR_UFM0 (1<<10)
|
||||
# define FLASH_UFM_ADDR_UFM1 (1<<11)
|
||||
# define FLASH_UFM_ADDR_UFM2 (1<<12)
|
||||
# define FLASH_UFM_ADDR_UFM3 (1<<13)
|
||||
#define PROG_CFG_FLASH 0x70 /* LSC_PROG_INCR_NV */
|
||||
#define READ_BUSY_FLAG 0xF0 /* LSC_CHECK_BUSY */
|
||||
/* The busy flag defines bit 7 as busy, but busy flags returns 1 for busy (bit 0). */
|
||||
#define REG_CFG_FLASH 0x73 /* LSC_READ_INCR_NV */
|
||||
#define PROG_FEATURE_ROW 0xE4 /* LSC_PROG_FEATURE */
|
||||
#define READ_FEATURE_ROW 0xE7 /* LSC_READ_FEATURE */
|
||||
/* See feaParser.hpp for FEATURE definitions */
|
||||
#define PROG_FEABITS 0xF8 /* LSC_PROG_FEABITS */
|
||||
#define READ_FEABITS 0xFB /* LSC_READ_FEABITS */
|
||||
/* See feaParser.hpp for FEAbit definitions */
|
||||
#define PROG_DONE 0x5E /* ISC_PROGRAM_DONE - This command is used to program the done bit */
|
||||
#define REFRESH 0x79 /* LSC_REFRESH */
|
||||
#define READ_STATUS_REGISTER 0x3C /* LSC_READ_STATUS */
|
||||
# define REG_STATUS_DONE (1 << 8) /* Flash or SRAM Done Flag (ISC_EN=0 -> 1 Successful Flash to SRAM transfer, ISC_EN=1 -> 1 Programmed) */
|
||||
# define REG_STATUS_ISC_EN (1 << 9) /* Enable Configuration Interface (1=Enable, 0=Disable) */
|
||||
# define REG_STATUS_BUSY (1 << 12) /* Busy Flag (1 = Busy) */
|
||||
# define REG_STATUS_FAIL (1 << 13) /* Fail Flag (1 = Operation failed) */
|
||||
# define REG_STATUS_PP_CFG (1 << 15) /* Password Protection All Enabled for CFG0 and CFG1 flash sectors 0=Disabled (Default), 1=Enabled */
|
||||
# define REG_STATUS_PP_FSK (1 << 16) /* Password Protection Enabled for Feature and Security Key flash sectors 0=Disabled (Default), 1=Enabled */
|
||||
# define REG_STATUS_PP_UFM (1 << 17) /* Password Protection enabled for all UFM flash sectors 0=Disabled (Default), 1=Enabled */
|
||||
# define REG_STATUS_AUTH_DONE (1 << 18) /* Authentication done */
|
||||
# define REG_STATUS_PRI_BOOT_FAIL (1 << 21) /* Primary boot failure (1= Fail) even though secondary boot successful */
|
||||
# define REG_STATUS_CNF_CHK_MASK (0x0f << 22)/* Configuration Status Check */
|
||||
# define REG_STATUS_EXEC_ERR (1 << 26) /*** NOT specified for MachXO3D ***/
|
||||
# define REG_STATUS_DEV_VERIFIED (1 << 27) /* I=0 Device verified correct, I=1 Device failed to verify */
|
||||
#define READ_STATUS_REGISTER_1 0x3D /* LSC_READ_STATUS_1 */
|
||||
# define REG_STATUS1_FLASH_SEL (0x0f << 0) /* Flash sector selection 1=CFG0, 2=CFG1, 4=FEATURE, 5=Pub Key, 6=AES Key, 8=UFM0, 10=UFM1, 11=UFM2, 12=UFM3 */
|
||||
# define REG_STATUS1_ERASE_DISABLE (1 << 4) /* Erase operation is prohibited (1 = Erase disable) */
|
||||
# define REG_STATUS1_PROG_DISABLE (1 << 5) /* Program operation is prohibited (1 = Programing disable) */
|
||||
# define REG_STATUS1_READ_DISABLE (1 << 6) /* Read operation is prohibited (1 = Read disable) */
|
||||
# define REG_STATUS1_HS_LOCK_SEL (1 << 7) /* Hard/Soft Lock Selection (1 = Hard Lock, 0 = Soft Lock) */
|
||||
# define REG_STATUS1_AUTH_MODE (0x03 << 8) /* Authentication mode: 0x: No Authentication, 10: HMAC Authentication, 11: ECDSA Signature Verification */
|
||||
# define REG_STATUS1_AUTH_DONE_CFG0 (1 << 10) /* Authentication done for CFG0 (1 = Authentication successful) */
|
||||
# define REG_STATUS1_AUTH_DONE_CFG1 (1 << 11) /* Authentication done for CFG1 (1 = Authentication successful) */
|
||||
# define REG_STATUS1_FLASH_DONE_CFG0 (1 << 12) /* Flash done bit is programmed of CFG0 (1= Programmed, 0=Unprogrammed) */
|
||||
# define REG_STATUS1_FLASH_DONE_CFG1 (1 << 13) /* Flash done bit is programmed of CFG1 (1= Programmed, 0=Unprogrammed) */
|
||||
# define REG_STATUS1_SEC_PLUS_EN_CFG0 (1 << 14) /* Security Plus enabled for CFG0 (1 = Enabled, 0 = Disabled) */
|
||||
# define REG_STATUS1_SEC_PLUS_EN_CFG1 (1 << 15) /* Security Plus enabled for CFG1 (1 = Enabled, 0 = Disabled) */
|
||||
# define REG_STATUS1_BITSTR_VERSION (1 << 16) /* Bitstream version: 1 = Bitstream in CFG0 is latter (newer) than CFG1, 0 = Bitstream in CFG1 is latter (newer) than CFG0 */
|
||||
# define REG_STATUS1_BOOT_SEQ_SEL (0x03 << 17)/* Boot Sequence selection (used along with Master SPI Port Persistence bit) */
|
||||
# define REG_STATUS1_MSPI_PERS (1 << 20) /* Master SPI Port Persistence 0=Disabled (Default), 1=Enabled */
|
||||
# define REG_STATUS1_I2C_DG_FILTER (1 << 21) /* I2C deglitch filter enable for Primary I2C Port 0=Disabled (Default), 1=Enabled */
|
||||
# define REG_STATUS1_I2C_DG_RANGE (1 << 22) /* I2C deglitch filter range selection on primary I2C port 0= 8 to 25 ns range (Default), 1= 16 to 50 ns range */
|
||||
#define PROG_ECDSA_PUBKEY0 0x59 /* This command is used to program the first 128 bits of the ECDSA Public Key. */
|
||||
#define READ_ECDSA_PUBKEY0 0x5A /* This command is used to read the first 128 bits of the ECDSA Public Key. */
|
||||
#define PROG_ECDSA_PUBKEY1 0x5B /* This command is used to program the second 128 bits of the ECDSA Public Key. */
|
||||
#define READ_ECDSA_PUBKEY1 0x5C /* This command is used to read the second 128 bits of the ECDSA Public Key. */
|
||||
#define PROG_ECDSA_PUBKEY2 0x61 /* This command is used to program the third 128 bits of the ECDSA Public Key. */
|
||||
#define READ_ECDSA_PUBKEY2 0x62 /* This command is used to read the third 128 bits of the ECDSA Public Key. */
|
||||
#define PROG_ECDSA_PUBKEY3 0x63 /* This command is used to program the fourth 128 bits of the ECDSA Public Key. */
|
||||
#define READ_ECDSA_PUBKEY3 0x64 /* This command is used to read the fourth 128 bits of the ECDSA Public Key. */
|
||||
#define ISC_NOOP 0xff /* This command is no operation command (NOOP) or null operation. */
|
||||
|
||||
Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
|
||||
Device::prog_type_t prg_type, bool verify, int8_t verbose):
|
||||
Device::prog_type_t prg_type, std::string flash_sector, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
_fpga_family(UNKNOWN_FAMILY)
|
||||
_fpga_family(UNKNOWN_FAMILY), _flash_sector(LATTICE_FLASH_UNDEFINED)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
_mode = READ_MODE;
|
||||
} else if (!_file_extension.empty()) {
|
||||
if (_file_extension == "jed" || _file_extension == "mcs") {
|
||||
if (_file_extension == "jed" || _file_extension == "mcs" || _file_extension == "fea" || _file_extension == "pub") {
|
||||
_mode = Device::FLASH_MODE;
|
||||
} else if (_file_extension == "bit" || _file_extension == "bin") {
|
||||
if (prg_type == Device::WR_FLASH)
|
||||
|
|
@ -94,6 +170,39 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type,
|
|||
printError("Unknown device family");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if (flash_sector == "CFG0") {
|
||||
_flash_sector = LATTICE_FLASH_CFG0;
|
||||
printInfo("Flash Sector: CFG0", true);
|
||||
}
|
||||
else if (flash_sector == "CFG1") {
|
||||
_flash_sector = LATTICE_FLASH_CFG1;
|
||||
printInfo("Flash Sector: CFG1", true);
|
||||
}
|
||||
else if (flash_sector == "UFM0") {
|
||||
_flash_sector = LATTICE_FLASH_UFM0;
|
||||
printInfo("Flash Sector: UFM0", true);
|
||||
}
|
||||
else if (flash_sector == "UFM1") {
|
||||
_flash_sector = LATTICE_FLASH_UFM1;
|
||||
printInfo("Flash Sector: UFM1", true);
|
||||
}
|
||||
else if (flash_sector == "UFM2") {
|
||||
_flash_sector = LATTICE_FLASH_UFM2;
|
||||
printInfo("Flash Sector: UFM2", true);
|
||||
}
|
||||
else if (flash_sector == "UFM3") {
|
||||
_flash_sector = LATTICE_FLASH_UFM3;
|
||||
printInfo("Flash Sector: UFM3", true);
|
||||
}
|
||||
else if (flash_sector == "FEA") {
|
||||
_flash_sector = LATTICE_FLASH_FEA;
|
||||
printInfo("Flash Sector: FEA", true);
|
||||
}
|
||||
else {
|
||||
printError("Unknown flash sector");
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
void displayFeabits(uint16_t _featbits)
|
||||
|
|
@ -151,12 +260,12 @@ bool Lattice::program_mem()
|
|||
bool err;
|
||||
LatticeBitParser _bit(_filename, _verbose);
|
||||
|
||||
printInfo("Open file ", false);
|
||||
printInfo("Open file: ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _bit.parse();
|
||||
|
||||
printInfo("Parse file ", false);
|
||||
printInfo("Parse file: ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
|
|
@ -173,6 +282,7 @@ bool Lattice::program_mem()
|
|||
displayReadReg(readStatusReg());
|
||||
}
|
||||
|
||||
/* The command code 0x1C is not listed in the manual? */
|
||||
/* preload 0x1C */
|
||||
uint8_t tx_buf[26];
|
||||
memset(tx_buf, 0xff, 26);
|
||||
|
|
@ -444,7 +554,7 @@ bool Lattice::program_extFlash(unsigned int offset)
|
|||
SPIFlash flash(this, _verbose);
|
||||
flash.reset();
|
||||
flash.read_id();
|
||||
flash.display_status_reg(flash.read_status_reg());
|
||||
flash.read_status_reg();
|
||||
flash.erase_and_prog(offset, data, length);
|
||||
|
||||
int ret = true;
|
||||
|
|
@ -457,6 +567,8 @@ bool Lattice::program_extFlash(unsigned int offset)
|
|||
|
||||
bool Lattice::program_flash(unsigned int offset)
|
||||
{
|
||||
uint32_t erase_op;
|
||||
|
||||
/* read ID Code 0xE0 */
|
||||
if (_verbose) {
|
||||
printf("IDCode : %x\n", idCode());
|
||||
|
|
@ -480,9 +592,14 @@ bool Lattice::program_flash(unsigned int offset)
|
|||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
if (_fpga_family == MACHXO3D_FAMILY)
|
||||
erase_op = 0x0;
|
||||
else
|
||||
erase_op = FLASH_ERASE_SRAM;
|
||||
|
||||
/* ISC ERASE */
|
||||
printInfo("SRAM erase: ", false);
|
||||
if (flashErase(FLASH_ERASE_SRAM) == false) {
|
||||
if (flashErase(erase_op) == false) {
|
||||
printError("FAIL");
|
||||
displayReadReg(readStatusReg());
|
||||
return false;
|
||||
|
|
@ -493,8 +610,18 @@ bool Lattice::program_flash(unsigned int offset)
|
|||
DisableISC();
|
||||
|
||||
bool retval;
|
||||
if (_file_extension == "jed")
|
||||
if (_file_extension == "jed") {
|
||||
if (_fpga_family == MACHXO3D_FAMILY)
|
||||
retval = program_intFlash_MachXO3D();
|
||||
else
|
||||
retval = program_intFlash();
|
||||
}
|
||||
else if (_file_extension == "fea") {
|
||||
retval = program_fea_MachXO3D();
|
||||
}
|
||||
else if (_file_extension == "pub") {
|
||||
retval = program_pubkey_MachXO3D();
|
||||
}
|
||||
else
|
||||
retval = program_extFlash(offset);
|
||||
|
||||
|
|
@ -694,7 +821,7 @@ uint32_t Lattice::readStatusReg()
|
|||
uint8_t rx[4], tx[4];
|
||||
/* valgrind warn */
|
||||
memset(tx, 0, 4);
|
||||
wr_rd(0x3C, tx, 4, rx, 4);
|
||||
wr_rd(READ_STATUS_REGISTER, tx, 4, rx, 4);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
reg = rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0];
|
||||
|
|
@ -893,7 +1020,7 @@ bool Lattice::pollBusyFlag(bool verbose)
|
|||
uint8_t rx;
|
||||
int timeout = 0;
|
||||
do {
|
||||
wr_rd(CHECK_BUSY_FLAG, NULL, 0, &rx, 1);
|
||||
wr_rd(READ_BUSY_FLAG, NULL, 0, &rx, 1);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
if (verbose)
|
||||
|
|
@ -914,16 +1041,28 @@ bool Lattice::flashEraseAll()
|
|||
return flashErase(0xf);
|
||||
}
|
||||
|
||||
bool Lattice::flashErase(uint8_t mask)
|
||||
bool Lattice::flashErase(uint32_t mask)
|
||||
{
|
||||
uint8_t tx[1] = {mask};
|
||||
if (_fpga_family == MACHXO3D_FAMILY) {
|
||||
uint8_t tx[2] = {
|
||||
(uint8_t)((mask >> 8) & 0xff),
|
||||
(uint8_t)((mask >> 16) & 0xff)
|
||||
};
|
||||
wr_rd(FLASH_ERASE, tx, 2, NULL, 0);
|
||||
}
|
||||
else {
|
||||
uint8_t tx[1] = {(uint8_t)(mask & 0xff)};
|
||||
wr_rd(FLASH_ERASE, tx, 1, NULL, 0);
|
||||
}
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
||||
if (!pollBusyFlag())
|
||||
return false;
|
||||
|
||||
if (!checkStatus(0, REG_STATUS_FAIL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -944,13 +1083,22 @@ bool Lattice::flashProg(uint32_t start_addr, const string &name, vector<string>
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::Verify(std::vector<std::string> data, bool unlock)
|
||||
bool Lattice::Verify(std::vector<std::string> data, bool unlock, uint32_t flash_area)
|
||||
{
|
||||
uint8_t tx_buf[16], rx_buf[16];
|
||||
if (unlock)
|
||||
EnableISC(0x08);
|
||||
|
||||
wr_rd(0x46, NULL, 0, NULL, 0);
|
||||
if (_fpga_family == MACHXO3D_FAMILY) {
|
||||
uint8_t tx[2] = { (
|
||||
uint8_t)((flash_area >> 8) & 0xff),
|
||||
(uint8_t)((flash_area >> 16) & 0xff)
|
||||
};
|
||||
wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0);
|
||||
} else {
|
||||
wr_rd(RESET_CFG_ADDR, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
||||
|
|
@ -1154,3 +1302,563 @@ int Lattice::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
|||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************** MODS FOR MacXO3D *********************************/
|
||||
|
||||
bool Lattice::programFeatureRow_MachXO3D(uint8_t* feature_row)
|
||||
{
|
||||
uint8_t tx[16] = { 0 };
|
||||
uint8_t rx[15] = { 0 };
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
tx[i] = feature_row[i];
|
||||
}
|
||||
|
||||
if (_verbose) {
|
||||
printf("\tProgramming feature row: [0x");
|
||||
for (int i = 11; i >= 0; i--) {
|
||||
printf("%02x", feature_row[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
wr_rd(PROG_FEATURE_ROW, tx, 16, NULL, 0);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||
if (!pollBusyFlag())
|
||||
return false;
|
||||
|
||||
wr_rd(READ_FEATURE_ROW, NULL, 0, rx, 15);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
if (_verbose) {
|
||||
printf("\tReadback Feature Row: [0x");
|
||||
for(int i = 11; i >= 0; i--) {
|
||||
printf("%02x", rx[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
if (_verify) {
|
||||
for(int i = 0; i < 15; i++) {
|
||||
if (feature_row[i] != rx[i]) {
|
||||
printf("\tVerify Failed...\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::programFeabits_MachXO3D(uint32_t feabits)
|
||||
{
|
||||
uint8_t tx[4] = { 0 };
|
||||
uint8_t rx[5] = { 0 };
|
||||
|
||||
memset(tx, 0, sizeof(tx));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tx[i] = (feabits >> (8*i)) & 0xff;
|
||||
}
|
||||
|
||||
if (_verbose) {
|
||||
printf("\tProgramming FEAbits: [0x");
|
||||
for (int i = 4; i >= 0; i--) {
|
||||
printf("%02x", tx[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
wr_rd(PROG_FEABITS, tx, 4, NULL, 0);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
wr_rd(0xff, NULL, 0, NULL, 0);
|
||||
if (!pollBusyFlag())
|
||||
return false;
|
||||
|
||||
wr_rd(READ_FEABITS, NULL, 0, rx, 5);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
if (_verbose) {
|
||||
printf("\tReadback Feabits: [0x");
|
||||
for(int i = 4; i >= 0; i--) {
|
||||
printf("%02x", rx[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
if (_verify) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if ((feabits >> (8*i)) & 0xff != rx[i]) {
|
||||
printf("\tVerify Failed...\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::program_fea_MachXO3D()
|
||||
{
|
||||
bool err;
|
||||
uint8_t rx[15] = { 0 };
|
||||
uint8_t tx[16] = { 0 };
|
||||
bool same = true;
|
||||
|
||||
FeaParser _fea(_filename, _verbose);
|
||||
printInfo("Open file: ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _fea.parse();
|
||||
printInfo("Parse file: ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
if (_verbose)
|
||||
_fea.displayHeader();
|
||||
|
||||
/* bypass */
|
||||
wr_rd(ISC_NOOP, NULL, 0, NULL, 0);
|
||||
/* ISC Enable 0xC6 with operand of 0x08 (Enable Offline mode) */
|
||||
printInfo("Enable configuration: ", false);
|
||||
if (!EnableISC(0x08)) {
|
||||
printError("FAIL");
|
||||
displayReadReg(readStatusReg());
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* read the current feature row */
|
||||
wr_rd(READ_FEATURE_ROW, NULL, 0, rx, 12);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
if (_verbose) {
|
||||
printf("Read Feature Row: [0x");
|
||||
for(int i = 11; i >= 0; i--) {
|
||||
printf("%02x", rx[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
uint8_t* feature_row = (uint8_t*)_fea.featuresRow();
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (feature_row[i] != rx[i])
|
||||
same = false;
|
||||
}
|
||||
|
||||
/* read the current FEAbits */
|
||||
uint32_t feabits = _fea.feabits();
|
||||
wr_rd(READ_FEABITS, NULL, 0, rx, 6);
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(2);
|
||||
|
||||
if (_verbose) {
|
||||
printf("Read Feabits: [0x");
|
||||
for(int i = 4; i >= 0; i--) {
|
||||
printf("%02x", rx[i]);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((feabits >> (i * 8) & 0xff) != rx[i])
|
||||
same = false;
|
||||
}
|
||||
|
||||
printf("Feature Row / Feabits Compare: %s\n", same ? "Same" : "Different");
|
||||
if (same == false) {
|
||||
/* LSC_INIT_ADDRESS */
|
||||
tx[0] = (uint8_t)((FLASH_SEC_FEA >> 8) & 0xff);
|
||||
tx[1] = (uint8_t)((FLASH_SEC_FEA >> 16) & 0xff);
|
||||
if (_verbose)
|
||||
printf("Selected address (I): 0x%x 0x%x\n", tx[0], tx[1]);
|
||||
wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0);
|
||||
|
||||
/* ISC ERASE */
|
||||
printInfo("Flash erase: ", false);
|
||||
if (flashErase(FLASH_SEC_FEA) == false) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* FEATURE Row */
|
||||
printInfo("Program Feature Row: ", true);
|
||||
if (!programFeatureRow_MachXO3D(feature_row)) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* FEAbits */
|
||||
printInfo("Program FEAbits: ", true);
|
||||
if (!programFeabits_MachXO3D(feabits)) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
}
|
||||
|
||||
/* ISC program done 0x5E */
|
||||
printInfo("Write program Done: ", false);
|
||||
if (writeProgramDone() == false) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* bypass */
|
||||
wr_rd(ISC_NOOP, NULL, 0, NULL, 0);
|
||||
|
||||
/* disable configuration mode */
|
||||
printInfo("Disable configuration: ", false);
|
||||
if (!DisableISC()) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lattice::program_pubkey_MachXO3D()
|
||||
{
|
||||
bool err;
|
||||
bool same = true;
|
||||
int len;
|
||||
|
||||
RawParser _pk(_filename, false);
|
||||
printInfo("Open file: ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _pk.parse();
|
||||
printInfo("Parse file: ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
uint8_t* data = _pk.getData();
|
||||
len = _pk.getLength()/8;
|
||||
|
||||
printf("Header: [");
|
||||
if (data[0] == 0x0f) {
|
||||
for (int i = 2; i < len; i++) {
|
||||
if (data[i] == 0xf0)
|
||||
break;
|
||||
printf("%c", data[i]);
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
printf("Data: [");
|
||||
for (int i = 0; i < len -3; i++) {
|
||||
printf("0x%02x ", data[i]);
|
||||
}
|
||||
printf("\b]\n");
|
||||
|
||||
printf("Trailing bytes: [");
|
||||
for (int i = len -3; i < len; i++) {
|
||||
printf("0x%02x ", data[i]);
|
||||
}
|
||||
printf("\b]\n");
|
||||
|
||||
}
|
||||
|
||||
bool Lattice::program_intFlash_MachXO3D()
|
||||
{
|
||||
bool err, ufm_flag;
|
||||
uint64_t featuresRow;
|
||||
uint16_t feabits;
|
||||
uint32_t erase_op = 0, prog_op = 0;
|
||||
vector<string> data;
|
||||
int offset, fuse_count;
|
||||
|
||||
JedParser _jed(_filename, _verbose);
|
||||
printInfo("Open file ", false);
|
||||
printSuccess("DONE");
|
||||
|
||||
err = _jed.parse();
|
||||
printInfo("Parse file ", false);
|
||||
if (err == EXIT_FAILURE) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
if (_verbose)
|
||||
_jed.displayHeader();
|
||||
|
||||
/* bypass */
|
||||
wr_rd(ISC_NOOP, NULL, 0, NULL, 0);
|
||||
/* ISC Enable 0xC6 with operand of 0x08 (Enable Offline mode) */
|
||||
printInfo("Enable configuration: ", false);
|
||||
if (!EnableISC(0x08)) {
|
||||
printError("FAIL");
|
||||
displayReadReg(readStatusReg());
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* this is the size of an CFGx+UFMx area in bits (hence the / 128) */
|
||||
fuse_count = _jed.get_fuse_count() / 128;
|
||||
|
||||
for (int i = 0; i < _jed.nb_section(); i++) {
|
||||
std::string area_name;
|
||||
|
||||
data = _jed.data_for_section(i);
|
||||
if (data.size() < 1) {
|
||||
/* if no data, nothing to do */
|
||||
continue;
|
||||
}
|
||||
string note = _jed.noteForSection(i);
|
||||
offset = _jed.offset_for_section(i) / 128;
|
||||
|
||||
erase_op = 0;
|
||||
prog_op = 0;
|
||||
ufm_flag = false;
|
||||
|
||||
/* if the offset > total fuse count, then this file must be configured
|
||||
* for the 2nd config sector (CFG1), so adjust offset */
|
||||
while (offset >= fuse_count) {
|
||||
offset -= fuse_count;
|
||||
}
|
||||
/* If the offset is greater than the size of the config area then we're
|
||||
* programming the UFM area (UFM 0/1) */
|
||||
if (offset >= 12542) {
|
||||
offset -= 12542;
|
||||
}
|
||||
|
||||
if (note == "END CONFIG DATA") {
|
||||
printf("Processing PADDING data (offset: %d (0x%x))\n", offset, offset);
|
||||
/* PADDING - this should be padding to CFGx area that we're currently
|
||||
* programming therefore the flash area will already have been erased...
|
||||
* NOTE: We have to write this data if we're using bitstream authentication
|
||||
* - even if it's all zeros.
|
||||
*/
|
||||
erase_op = 0;
|
||||
/* We need to use the 'LSC_WRITE_ADDRESS' command to set not only the
|
||||
* flash sector but also the page number. */
|
||||
if (_flash_sector == LATTICE_FLASH_CFG0) {
|
||||
prog_op = (FLASH_SET_ADDR_CFG0 << 14) | (offset);
|
||||
area_name = "Padding (CFG0)";
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_CFG1) {
|
||||
prog_op = (FLASH_SET_ADDR_CFG1 << 14) | (offset);
|
||||
area_name = "Padding (CFG1)";
|
||||
}
|
||||
|
||||
/* offset should not be zero */
|
||||
if (offset == 0) {
|
||||
printf("Warning: offset (%u) is for programming PADDING\n", offset);
|
||||
}
|
||||
}
|
||||
else if (note == "EBR_INIT DATA") {
|
||||
printf("Processing EBR_INIT data (offset: %d (0x%x))\n", offset, offset);
|
||||
/* EBR - Embedded Block RAM initialisation data */
|
||||
if (offset == 0) {
|
||||
if (_flash_sector == LATTICE_FLASH_CFG0) {
|
||||
erase_op = FLASH_SEC_UFM0;
|
||||
prog_op = FLASH_UFM_ADDR_UFM0;
|
||||
area_name = "EBR (UFM0)";
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_CFG1) {
|
||||
erase_op = FLASH_SEC_UFM1;
|
||||
prog_op = FLASH_UFM_ADDR_UFM1;
|
||||
area_name = "EBR (UFM1)";
|
||||
}
|
||||
ufm_flag = true;
|
||||
}
|
||||
else {
|
||||
/* NOT SUPPORTING NON-ZERO OFFSET WRITES...*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (note.compare(0, 16, "USER MEMORY DATA") == 0) {
|
||||
printf("Processing UFM data (offset: %d (0x%x))\n", offset, offset);
|
||||
if ((_flash_sector == LATTICE_FLASH_CFG0)||
|
||||
(_flash_sector == LATTICE_FLASH_UFM0)) {
|
||||
if (offset == 0) {
|
||||
erase_op = FLASH_SEC_UFM0;
|
||||
prog_op = FLASH_UFM_ADDR_UFM0;
|
||||
}
|
||||
else {
|
||||
erase_op = 0;
|
||||
/* We need to use the 'LSC_WRITE_ADDRESS' command to set the
|
||||
* flash sector and the page number. */
|
||||
prog_op = (FLASH_SET_ADDR_UFM0 << 14) | (offset);
|
||||
}
|
||||
area_name = "UFM0";
|
||||
}
|
||||
else if ((_flash_sector == LATTICE_FLASH_CFG1)||
|
||||
(_flash_sector == LATTICE_FLASH_UFM1)) {
|
||||
if (offset == 0) {
|
||||
erase_op = FLASH_SEC_UFM1;
|
||||
prog_op = FLASH_UFM_ADDR_UFM1;
|
||||
}
|
||||
else {
|
||||
erase_op = 0;
|
||||
/* We need to use the 'LSC_WRITE_ADDRESS' command to set the
|
||||
* flash sector and the page number. */
|
||||
prog_op = (FLASH_SET_ADDR_UFM1 << 14) | (offset);
|
||||
}
|
||||
area_name = "UFM1";
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_UFM2) {
|
||||
if (offset == 0) {
|
||||
erase_op = FLASH_SEC_UFM2;
|
||||
prog_op = FLASH_UFM_ADDR_UFM2;
|
||||
}
|
||||
else {
|
||||
erase_op = 0;
|
||||
/* We need to use the 'LSC_WRITE_ADDRESS' command to set the
|
||||
* flash sector and the page number. */
|
||||
prog_op = (FLASH_SET_ADDR_UFM2 << 14) | (offset);
|
||||
}
|
||||
area_name = "UFM2";
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_UFM3) {
|
||||
if (offset == 0) {
|
||||
erase_op = FLASH_SEC_UFM3;
|
||||
prog_op = FLASH_UFM_ADDR_UFM3;
|
||||
}
|
||||
else {
|
||||
erase_op = 0;
|
||||
/* We need to use the 'LSC_WRITE_ADDRESS' command to set the
|
||||
* flash sector and the page number. */
|
||||
prog_op = (FLASH_SET_ADDR_UFM3 << 14) | (offset);
|
||||
}
|
||||
area_name = "UFM3";
|
||||
}
|
||||
ufm_flag = true;
|
||||
}
|
||||
else {
|
||||
printf("Processing CFG data (offset: %d (0x%x))\n", offset, offset);
|
||||
if (_flash_sector == LATTICE_FLASH_CFG0) {
|
||||
erase_op = FLASH_SEC_CFG0;
|
||||
prog_op = FLASH_SEC_CFG0;
|
||||
area_name = "Data (CFG0)";
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_CFG1) {
|
||||
erase_op = FLASH_SEC_CFG1;
|
||||
prog_op = FLASH_SEC_CFG1;
|
||||
area_name = "Data (CFG1)";
|
||||
}
|
||||
|
||||
/* offset should be zero */
|
||||
if (offset != 0) {
|
||||
printf("Warning: offset (%u) is not 0 for programming CFG\n", offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (erase_op > 0) {
|
||||
/* ISC ERASE */
|
||||
printInfo("Flash erase: ", false);
|
||||
if (flashErase(erase_op) == false) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
/* LSC_INIT_ADDRESS */
|
||||
uint8_t tx[2] = {
|
||||
(uint8_t)((prog_op >> 8) & 0xff),
|
||||
(uint8_t)((prog_op >> 16) & 0xff)
|
||||
};
|
||||
printf("address (I): 0x%x 0x%x\n", tx[0], tx[1]);
|
||||
wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0);
|
||||
}
|
||||
else {
|
||||
/* LSC_WRITE_ADDRESS */
|
||||
uint8_t tx[3] = {
|
||||
(uint8_t)(prog_op & 0xff),
|
||||
(uint8_t)((prog_op >> 8) & 0xff),
|
||||
(uint8_t)((prog_op >> 16) & 0x03)
|
||||
};
|
||||
printf("address (W): 0x%x 0x%x 0x%x\n", tx[0], tx[1], tx[2]);
|
||||
wr_rd(LSC_WRITE_ADDRESS, tx, 3, NULL, 0);
|
||||
}
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
||||
/* flash CfgFlash */
|
||||
if (false == flashProg(0, area_name, data))
|
||||
return false;
|
||||
|
||||
/* verify write */
|
||||
if (_verify) {
|
||||
if (Verify(data, false, prog_op) == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* @TODO: missing usercode update */
|
||||
|
||||
/* LSC_INIT_ADDRESS */
|
||||
if (_flash_sector == LATTICE_FLASH_CFG0) {
|
||||
uint8_t tx[2] = {
|
||||
(uint8_t)((FLASH_SEC_CFG0 >> 8) & 0xff),
|
||||
(uint8_t)((FLASH_SEC_CFG0 >> 16) & 0xff)
|
||||
};
|
||||
wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0);
|
||||
}
|
||||
else if (_flash_sector == LATTICE_FLASH_CFG1) {
|
||||
uint8_t tx[2] = {
|
||||
(uint8_t)((FLASH_SEC_CFG1 >> 8) & 0xff),
|
||||
(uint8_t)((FLASH_SEC_CFG1 >> 16) & 0xff)
|
||||
};
|
||||
wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0);
|
||||
}
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
_jtag->toggleClk(1000);
|
||||
|
||||
/* ISC program done 0x5E */
|
||||
printInfo("Write program Done: ", false);
|
||||
if (writeProgramDone() == false) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
/* bypass */
|
||||
wr_rd(ISC_NOOP, NULL, 0, NULL, 0);
|
||||
|
||||
/* disable configuration mode */
|
||||
printInfo("Disable configuration: ", false);
|
||||
if (!DisableISC()) {
|
||||
printError("FAIL");
|
||||
return false;
|
||||
} else {
|
||||
printSuccess("DONE");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@
|
|||
#include "jtag.hpp"
|
||||
#include "device.hpp"
|
||||
#include "jedParser.hpp"
|
||||
#include "feaparser.hpp"
|
||||
#include "latticeBitParser.hpp"
|
||||
#include "spiInterface.hpp"
|
||||
|
||||
class Lattice: public Device, SPIInterface {
|
||||
public:
|
||||
Lattice(Jtag *jtag, std::string filename, const std::string &file_type,
|
||||
Device::prog_type_t prg_type, bool verify,
|
||||
Device::prog_type_t prg_type, std::string flash_sector, bool verify,
|
||||
int8_t verbose);
|
||||
int idCode() override;
|
||||
int userCode();
|
||||
|
|
@ -28,7 +29,7 @@ class Lattice: public Device, SPIInterface {
|
|||
void program(unsigned int offset) override;
|
||||
bool program_mem();
|
||||
bool program_flash(unsigned int offset);
|
||||
bool Verify(std::vector<std::string> data, bool unlock = false);
|
||||
bool Verify(std::vector<std::string> data, bool unlock = false, uint32_t flash_area = 0);
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len) override;
|
||||
|
||||
|
|
@ -62,7 +63,7 @@ class Lattice: public Device, SPIInterface {
|
|||
bool DisableCfg();
|
||||
bool pollBusyFlag(bool verbose = false);
|
||||
bool flashEraseAll();
|
||||
bool flashErase(uint8_t mask);
|
||||
bool flashErase(uint32_t mask);
|
||||
bool flashProg(uint32_t start_addr, const std::string &name,
|
||||
std::vector<std::string> data);
|
||||
bool checkStatus(uint32_t val, uint32_t mask);
|
||||
|
|
@ -77,5 +78,28 @@ class Lattice: public Device, SPIInterface {
|
|||
|
||||
/* test */
|
||||
bool checkID();
|
||||
|
||||
/*********************** MODS FOR MacXO3D *****************************/
|
||||
enum lattice_flash_sector_t {
|
||||
LATTICE_FLASH_UNDEFINED = 0,
|
||||
LATTICE_FLASH_CFG0,
|
||||
LATTICE_FLASH_CFG1,
|
||||
LATTICE_FLASH_UFM0,
|
||||
LATTICE_FLASH_UFM1,
|
||||
LATTICE_FLASH_UFM2,
|
||||
LATTICE_FLASH_UFM3,
|
||||
LATTICE_FLASH_FEA,
|
||||
LATTICE_FLASH_PKEY,
|
||||
LATTICE_FLASH_AKEY,
|
||||
LATTICE_FLASH_CSEC,
|
||||
LATTICE_FLASH_USEC
|
||||
};
|
||||
|
||||
lattice_flash_sector_t _flash_sector;
|
||||
bool program_intFlash_MachXO3D();
|
||||
bool program_fea_MachXO3D();
|
||||
bool program_pubkey_MachXO3D();
|
||||
bool programFeatureRow_MachXO3D(uint8_t* feature_row);
|
||||
bool programFeabits_MachXO3D(uint32_t feabits);
|
||||
};
|
||||
#endif // LATTICE_HPP_
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ struct arguments {
|
|||
int16_t altsetting;
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
string flash_sector;
|
||||
};
|
||||
|
||||
int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *pins_config);
|
||||
|
|
@ -77,7 +78,7 @@ int main(int argc, char **argv)
|
|||
/* command line args. */
|
||||
struct arguments args = {0, false, false, false, 0, "", "", "-", "", -1,
|
||||
0, "-", false, false, false, false, Device::WR_SRAM, false,
|
||||
false, false, "", "", "", -1, 0, false, -1, 0, 0};
|
||||
false, false, "", "", "", -1, 0, false, -1, 0, 0, ""};
|
||||
/* parse arguments */
|
||||
try {
|
||||
if (parse_opt(argc, argv, &args, &pins_config))
|
||||
|
|
@ -436,7 +437,7 @@ int main(int argc, char **argv)
|
|||
args.prg_type, args.external_flash, args.verify, args.verbose);
|
||||
} else if (fab == "lattice") {
|
||||
fpga = new Lattice(jtag, args.bit_file, args.file_type,
|
||||
args.prg_type, args.verify, args.verbose);
|
||||
args.prg_type, args.flash_sector, args.verify, args.verbose);
|
||||
} else {
|
||||
printError("Error: manufacturer " + fab + " not supported");
|
||||
delete(jtag);
|
||||
|
|
@ -548,6 +549,7 @@ int parse_opt(int argc, char **argv, struct arguments *args, jtag_pins_conf_t *p
|
|||
cxxopts::value<unsigned int>(args->file_size))
|
||||
("file-type", "provides file type instead of let's deduced by using extension",
|
||||
cxxopts::value<string>(args->file_type))
|
||||
("flash-sector","flash sector (Lattice parts only)", cxxopts::value<string>(args->flash_sector))
|
||||
("fpga-part", "fpga model flavor + package", cxxopts::value<string>(args->fpga_part))
|
||||
("freq", "jtag frequency (Hz)", cxxopts::value<string>(freqo))
|
||||
("f,write-flash",
|
||||
|
|
|
|||
Loading…
Reference in New Issue