Compare commits
No commits in common. "a1ba0457e04585179de52f8555ae93a82cbe5adc" and "4a5a912b9d5f5de3f2acc284b06621ec1f351a9f" have entirely different histories.
a1ba0457e0
...
4a5a912b9d
|
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||||
# set the project name
|
# set the project name
|
||||||
project(openFPGALoader VERSION "0.13.1" LANGUAGES CXX)
|
project(openFPGALoader VERSION "0.13.1" LANGUAGES CXX)
|
||||||
add_definitions(-DVERSION=\"v${PROJECT_VERSION}\")
|
add_definitions(-DVERSION=\"v${PROJECT_VERSION}\")
|
||||||
|
|
||||||
option(ENABLE_OPTIM "Enable build with -O3 optimization level" ON)
|
option(ENABLE_OPTIM "Enable build with -O3 optimization level" ON)
|
||||||
option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
|
option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||||
|
|
@ -28,7 +29,7 @@ set(ISE_PATH "/opt/Xilinx/14.7" CACHE STRING "ise root directory (default: /opt/
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
if(ENABLE_OPTIM AND NOT(CMAKE_BUILD_TYPE STREQUAL "Debug"))
|
if (ENABLE_OPTIM)
|
||||||
set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ openFPGALoader -- a program to flash FPGA
|
||||||
with dump-flash
|
with dump-flash
|
||||||
--file-type arg provides file type instead of let's deduced
|
--file-type arg provides file type instead of let's deduced
|
||||||
by using extension
|
by using extension
|
||||||
--flash-sector arg flash sector (Lattice and Altera MAX10 parts only)
|
--flash-sector arg flash sector (Lattice parts only)
|
||||||
--fpga-part arg fpga model flavor + package
|
--fpga-part arg fpga model flavor + package
|
||||||
--freq arg jtag frequency (Hz)
|
--freq arg jtag frequency (Hz)
|
||||||
-f, --write-flash write bitstream in flash (default: false)
|
-f, --write-flash write bitstream in flash (default: false)
|
||||||
|
|
|
||||||
|
|
@ -494,7 +494,7 @@
|
||||||
URL: https://www.xilinx.com/products/boards-and-kits/kcu105.html
|
URL: https://www.xilinx.com/products/boards-and-kits/kcu105.html
|
||||||
FPGA: Kintex UltraScale xcku040-ffva1156
|
FPGA: Kintex UltraScale xcku040-ffva1156
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK (primary and secondary)
|
Flash: OK
|
||||||
|
|
||||||
- ID: kcu116
|
- ID: kcu116
|
||||||
Description: Xilinx KCU116
|
Description: Xilinx KCU116
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Reading the bitstream from STDIN
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# FPGA side
|
# FPGA side
|
||||||
nc -lp port | openFPGALoader --file-type xxx [option]
|
nc -lp port | openFPGALoader --file-type xxx [option
|
||||||
|
|
||||||
# Bitstream side
|
# Bitstream side
|
||||||
nc -q 0 host port < /path/to/bitstream.ext
|
nc -q 0 host port < /path/to/bitstream.ext
|
||||||
|
|
@ -83,35 +83,6 @@ Writing to an arbitrary address in flash memory
|
||||||
With FPGA using an external SPI flash (*xilinx*, *lattice ECP5/nexus/ice40*, *anlogic*, *efinix*) option ``-o`` allows
|
With FPGA using an external SPI flash (*xilinx*, *lattice ECP5/nexus/ice40*, *anlogic*, *efinix*) option ``-o`` allows
|
||||||
one to write raw binary file to an arbitrary adress in FLASH.
|
one to write raw binary file to an arbitrary adress in FLASH.
|
||||||
|
|
||||||
Detect/read/write on primary/secondary flash memories
|
|
||||||
=====================================================
|
|
||||||
|
|
||||||
With FPGA using two external SPI flash (some *xilinx* boards) option ``--target-flash`` allows to select the QSPI chip.
|
|
||||||
|
|
||||||
To detect:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
openFPGALoader -b kcu105 -f --target-flash {primary,secondary} --detect
|
|
||||||
|
|
||||||
To read the primary flash memory:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
openFPGALoader -b kcu105 -f --target-flash primary --dump-flash --file-size N_BYTES mydump.bin
|
|
||||||
|
|
||||||
and the second flash memory:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
openFPGALoader -b kcu105 -f --target-flash secondary --dump-flash --file-size N_BYTES --secondary-bitstream mydump.bin
|
|
||||||
|
|
||||||
To write on secondary flash memory:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
openFPGALoader -b kcu105 -f --target-flash secondary --secondary-bitstream mySecondaryBitstream.bin
|
|
||||||
|
|
||||||
Using an alternative directory for *spiOverJtag*
|
Using an alternative directory for *spiOverJtag*
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ if tool in ["ise", "vivado"]:
|
||||||
"xc7s25csga225" : "xc7s_csga225",
|
"xc7s25csga225" : "xc7s_csga225",
|
||||||
"xc7s25csga324" : "xc7s_csga324",
|
"xc7s25csga324" : "xc7s_csga324",
|
||||||
"xc7s50csga324" : "xc7s_csga324",
|
"xc7s50csga324" : "xc7s_csga324",
|
||||||
"xc7s75fgga676" : "xc7s_fgga676",
|
|
||||||
"xcku040-ffva1156" : "xcku040_ffva1156",
|
"xcku040-ffva1156" : "xcku040_ffva1156",
|
||||||
"xcku060-ffva1156" : "xcku060_ffva1156",
|
"xcku060-ffva1156" : "xcku060_ffva1156",
|
||||||
"xcvu9p-flga2104" : "xcvu9p_flga2104",
|
"xcvu9p-flga2104" : "xcvu9p_flga2104",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
set_property CFGBVS VCCO [current_design]
|
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
||||||
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH {4} [current_design]
|
|
||||||
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
|
||||||
|
|
||||||
set_property -dict {PACKAGE_PIN R20 IOSTANDARD LVCMOS33} [get_ports {csn}];
|
|
||||||
set_property -dict {PACKAGE_PIN N23 IOSTANDARD LVCMOS33} [get_ports {sdi_dq0}];
|
|
||||||
set_property -dict {PACKAGE_PIN N24 IOSTANDARD LVCMOS33} [get_ports {sdo_dq1}];
|
|
||||||
set_property -dict {PACKAGE_PIN P23 IOSTANDARD LVCMOS33} [get_ports {wpn_dq2}];
|
|
||||||
set_property -dict {PACKAGE_PIN R23 IOSTANDARD LVCMOS33} [get_ports {hldn_dq3}];
|
|
||||||
Binary file not shown.
|
|
@ -31,14 +31,12 @@ Altera::Altera(Jtag *jtag, const std::string &filename,
|
||||||
const std::string &file_type, Device::prog_type_t prg_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
const std::string &device_package,
|
const std::string &device_package,
|
||||||
const std::string &spiOverJtagPath, bool verify, int8_t verbose,
|
const std::string &spiOverJtagPath, bool verify, int8_t verbose,
|
||||||
const std::string &flash_sectors,
|
|
||||||
bool skip_load_bridge, bool skip_reset):
|
bool skip_load_bridge, bool skip_reset):
|
||||||
Device(jtag, filename, file_type, verify, verbose),
|
Device(jtag, filename, file_type, verify, verbose),
|
||||||
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
|
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
|
||||||
skip_reset),
|
skip_reset),
|
||||||
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
||||||
_vir_addr(0x1000), _vir_length(14), _clk_period(1),
|
_vir_addr(0x1000), _vir_length(14), _clk_period(1)
|
||||||
_flash_sectors(flash_sectors)
|
|
||||||
{
|
{
|
||||||
/* check device family */
|
/* check device family */
|
||||||
_idcode = _jtag->get_target_device_id();
|
_idcode = _jtag->get_target_device_id();
|
||||||
|
|
@ -405,7 +403,6 @@ bool Altera::max10_program_ufm(const Altera::max10_mem_t *mem, unsigned int offs
|
||||||
void Altera::max10_program(unsigned int offset)
|
void Altera::max10_program(unsigned int offset)
|
||||||
{
|
{
|
||||||
uint32_t base_addr;
|
uint32_t base_addr;
|
||||||
uint8_t update_sectors;
|
|
||||||
|
|
||||||
/* Needs to have some specifics informations about internal flash size/organisation
|
/* Needs to have some specifics informations about internal flash size/organisation
|
||||||
* and some magics.
|
* and some magics.
|
||||||
|
|
@ -482,54 +479,27 @@ void Altera::max10_program(unsigned int offset)
|
||||||
const uint8_t *dsm_data = _bit.getData("ICB");
|
const uint8_t *dsm_data = _bit.getData("ICB");
|
||||||
const int dsm_len = _bit.getLength("ICB") / 32; // getLength (bits) dsm_len in 32bits word
|
const int dsm_len = _bit.getLength("ICB") / 32; // getLength (bits) dsm_len in 32bits word
|
||||||
|
|
||||||
/* Check for a full update or only for a subset */
|
|
||||||
if (_flash_sectors.size() > 0) {
|
|
||||||
const std::vector<std::string> sectors = splitString(_flash_sectors, ',');
|
|
||||||
update_sectors = 0;
|
|
||||||
for (const auto §or: sectors) {
|
|
||||||
if (sector == "UFM1")
|
|
||||||
update_sectors |= (1 << 0);
|
|
||||||
else if (sector == "UFM0")
|
|
||||||
update_sectors |= (1 << 1);
|
|
||||||
else if (sector == "CFM2")
|
|
||||||
update_sectors |= (1 << 2);
|
|
||||||
else if (sector == "CFM1")
|
|
||||||
update_sectors |= (1 << 3);
|
|
||||||
else if (sector == "CFM0")
|
|
||||||
update_sectors |= (1 << 4);
|
|
||||||
else
|
|
||||||
throw std::runtime_error("Unknown sector " + sector);
|
|
||||||
}
|
|
||||||
} else { // full update
|
|
||||||
update_sectors = 0x1F;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start!
|
// Start!
|
||||||
max10_flow_enable();
|
max10_flow_enable();
|
||||||
|
|
||||||
max10_flow_erase(&mem, update_sectors);
|
max10_flow_erase(&mem, 0x1F);
|
||||||
if (update_sectors == 0x1f)
|
max10_dsm_verify();
|
||||||
max10_dsm_verify();
|
|
||||||
|
|
||||||
/* Write */
|
/* Write */
|
||||||
|
|
||||||
// UFM 1 -> 0
|
// UFM 1 -> 0
|
||||||
base_addr = mem.ufm_addr;
|
base_addr = mem.ufm_addr;
|
||||||
for (int i = 1; i >= 0; i--) {
|
for (int i = 1; i >= 0; i--) {
|
||||||
if (update_sectors & (1 << i)) {
|
printInfo("Write UFM" + std::to_string(i));
|
||||||
printInfo("Write UFM" + std::to_string(i));
|
writeXFM(ufm_data[i], base_addr, 0, mem.ufm_len[i]);
|
||||||
writeXFM(ufm_data[i], base_addr, 0, mem.ufm_len[i]);
|
|
||||||
}
|
|
||||||
base_addr += mem.ufm_len[i];
|
base_addr += mem.ufm_len[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// CFM2 -> 0
|
// CFM2 -> 0
|
||||||
base_addr = mem.cfm_addr;
|
base_addr = mem.cfm_addr;
|
||||||
for (int i = 2; i >= 0; i--) {
|
for (int i = 2; i >= 0; i--) {
|
||||||
if (update_sectors & (1 << ((2 - i) + 2))) {
|
printInfo("Write CFM" + std::to_string(i));
|
||||||
printInfo("Write CFM" + std::to_string(i));
|
writeXFM(cfm_data[i], base_addr, 0, mem.cfm_len[i]);
|
||||||
writeXFM(cfm_data[i], base_addr, 0, mem.cfm_len[i]);
|
|
||||||
}
|
|
||||||
base_addr += mem.cfm_len[i];
|
base_addr += mem.cfm_len[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,35 +508,29 @@ void Altera::max10_program(unsigned int offset)
|
||||||
// UFM 1 -> 0
|
// UFM 1 -> 0
|
||||||
base_addr = mem.ufm_addr;
|
base_addr = mem.ufm_addr;
|
||||||
for (int i = 1; i >= 0; i--) {
|
for (int i = 1; i >= 0; i--) {
|
||||||
if (update_sectors & (1 << i)) {
|
printInfo("Verify UFM" + std::to_string(i));
|
||||||
printInfo("Verify UFM" + std::to_string(i));
|
verifyxFM(ufm_data[i], base_addr, 0, mem.ufm_len[i]);
|
||||||
verifyxFM(ufm_data[i], base_addr, 0, mem.ufm_len[i]);
|
|
||||||
}
|
|
||||||
base_addr += mem.ufm_len[i];
|
base_addr += mem.ufm_len[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// CFM2->0
|
// CFM2->0
|
||||||
base_addr = mem.cfm_addr;
|
base_addr = mem.cfm_addr;
|
||||||
for (int i = 2; i >= 0; i--) {
|
for (int i = 2; i >= 0; i--) {
|
||||||
if (update_sectors & (1 << ((2 - i) + 2))) {
|
printInfo("Verify CFM" + std::to_string(i));
|
||||||
printInfo("Verify CFM" + std::to_string(i));
|
verifyxFM(cfm_data[i], base_addr, 0, mem.cfm_len[i]);
|
||||||
verifyxFM(cfm_data[i], base_addr, 0, mem.cfm_len[i]);
|
|
||||||
}
|
|
||||||
base_addr += mem.cfm_len[i];
|
base_addr += mem.cfm_len[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DSM
|
// DSM
|
||||||
|
|
||||||
if (update_sectors == 0x1F) {
|
max10_dsm_program(dsm_data, dsm_len);
|
||||||
max10_dsm_program(dsm_data, dsm_len);
|
max10_dsm_verify();
|
||||||
max10_dsm_verify();
|
|
||||||
|
|
||||||
max10_flow_program_donebit(mem.done_bit_addr);
|
max10_flow_program_donebit(mem.done_bit_addr);
|
||||||
max10_dsm_verify();
|
max10_dsm_verify();
|
||||||
max10_dsm_program_success(mem.pgm_success_addr);
|
max10_dsm_program_success(mem.pgm_success_addr);
|
||||||
max10_dsm_verify();
|
max10_dsm_verify();
|
||||||
}
|
|
||||||
|
|
||||||
/* disable ISC flow */
|
/* disable ISC flow */
|
||||||
max10_flow_disable();
|
max10_flow_disable();
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ class Altera: public Device, SPIInterface {
|
||||||
const std::string &device_package,
|
const std::string &device_package,
|
||||||
const std::string &spiOverJtagPath,
|
const std::string &spiOverJtagPath,
|
||||||
bool verify, int8_t verbose,
|
bool verify, int8_t verbose,
|
||||||
const std::string &flash_sectors,
|
|
||||||
bool skip_load_bridge, bool skip_reset);
|
bool skip_load_bridge, bool skip_reset);
|
||||||
~Altera();
|
~Altera();
|
||||||
|
|
||||||
|
|
@ -153,7 +152,6 @@ class Altera: public Device, SPIInterface {
|
||||||
|
|
||||||
altera_family_t _fpga_family;
|
altera_family_t _fpga_family;
|
||||||
uint32_t _idcode;
|
uint32_t _idcode;
|
||||||
std::string _flash_sectors; /**< MAX10 Only: list of sectors to erase/write */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_ALTERA_HPP_
|
#endif // SRC_ALTERA_HPP_
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ static std::map <std::string, target_board_t> board_list = {
|
||||||
0, 0, CABLE_DEFAULT),
|
0, 0, CABLE_DEFAULT),
|
||||||
DFU_BOARD("icebreaker-bitsy", "", "dfu", 0x1d50, 0x6146, 0),
|
DFU_BOARD("icebreaker-bitsy", "", "dfu", 0x1d50, 0x6146, 0),
|
||||||
JTAG_BOARD("kc705", "", "digilent", 0, 0, CABLE_DEFAULT),
|
JTAG_BOARD("kc705", "", "digilent", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("kcu105", "xcku040-ffva1156", "jtag-smt2-nc", 0, 0, CABLE_DEFAULT),
|
JTAG_BOARD("kcu105", "", "jtag-smt2-nc", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("kcu116", "xcku5p-ffvb676", "jtag-smt2-nc", 0, 0, CABLE_DEFAULT),
|
JTAG_BOARD("kcu116", "xcku5p-ffvb676", "jtag-smt2-nc", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("LD-SCHOKO", "LFE5U-45F-6CABGA256", "", 0, 0, CABLE_MHZ(6)),
|
JTAG_BOARD("LD-SCHOKO", "LFE5U-45F-6CABGA256", "", 0, 0, CABLE_MHZ(6)),
|
||||||
DFU_BOARD("LD-SCHOKO-DFU", "", "dfu", 0x16d0, 0x116d, 0),
|
DFU_BOARD("LD-SCHOKO-DFU", "", "dfu", 0x16d0, 0x116d, 0),
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <cstdlib>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief return shell environment variable value
|
* \brief return shell environment variable value
|
||||||
|
|
@ -20,23 +19,3 @@ const std::string get_shell_env_var(const char* key,
|
||||||
const char* ret = std::getenv(key);
|
const char* ret = std::getenv(key);
|
||||||
return std::string(ret ? ret : def_val);
|
return std::string(ret ? ret : def_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief convert a string, separate by delim to a vector
|
|
||||||
* \param[in] in: string to split
|
|
||||||
* \param[in] delim: split caracter
|
|
||||||
* \return vector a substring
|
|
||||||
*/
|
|
||||||
const std::vector<std::string> splitString(const std::string& in,
|
|
||||||
const char delim) noexcept {
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
size_t start = 0, end = 0;
|
|
||||||
|
|
||||||
while ((end = in.find(delim, start)) != std::string::npos) {
|
|
||||||
tokens.push_back(in.substr(start, end - start));
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens.push_back(in.substr(start)); // Add the last token
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
#define SRC_COMMON_HPP_
|
#define SRC_COMMON_HPP_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief return shell environment variable value
|
* \brief return shell environment variable value
|
||||||
|
|
@ -18,13 +17,4 @@
|
||||||
const std::string get_shell_env_var(const char* key,
|
const std::string get_shell_env_var(const char* key,
|
||||||
const char *def_val="") noexcept;
|
const char *def_val="") noexcept;
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief convert a string, separate by delim to a vector
|
|
||||||
* \param[in] in: string to split
|
|
||||||
* \param[in] delim: split caracter
|
|
||||||
* \return vector a substring
|
|
||||||
*/
|
|
||||||
const std::vector<std::string> splitString(const std::string& in,
|
|
||||||
const char delim) noexcept;
|
|
||||||
|
|
||||||
#endif // SRC_COMMON_HPP_
|
#endif // SRC_COMMON_HPP_
|
||||||
|
|
|
||||||
|
|
@ -911,10 +911,7 @@ bool Gowin::eraseSRAM()
|
||||||
// is set
|
// is set
|
||||||
bool auto_boot_2nd_fail = (status & (1 << 4)) == (1 << 4);
|
bool auto_boot_2nd_fail = (status & (1 << 4)) == (1 << 4);
|
||||||
bool is_timeout = (status & (1 << 3)) == (1 << 3);
|
bool is_timeout = (status & (1 << 3)) == (1 << 3);
|
||||||
bool bad_cmd = (status & STATUS_BAD_COMMAND) == STATUS_BAD_COMMAND;
|
if (is_gw5a && (is_timeout || auto_boot_2nd_fail)) {
|
||||||
uint8_t loop = 0;
|
|
||||||
bool must_loop = is_gw5a;
|
|
||||||
if (is_gw5a && (is_timeout || auto_boot_2nd_fail || bad_cmd)) {
|
|
||||||
send_command(CONFIG_ENABLE);
|
send_command(CONFIG_ENABLE);
|
||||||
send_command(0x3F);
|
send_command(0x3F);
|
||||||
send_command(CONFIG_DISABLE);
|
send_command(CONFIG_DISABLE);
|
||||||
|
|
@ -923,44 +920,36 @@ bool Gowin::eraseSRAM()
|
||||||
send_command(NOOP);
|
send_command(NOOP);
|
||||||
_jtag->toggleClk(125 * 8);
|
_jtag->toggleClk(125 * 8);
|
||||||
}
|
}
|
||||||
do {
|
|
||||||
|
|
||||||
if (!enableCfg()) {
|
if (!enableCfg()) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
send_command(ERASE_SRAM);
|
send_command(ERASE_SRAM);
|
||||||
send_command(NOOP);
|
send_command(NOOP);
|
||||||
|
|
||||||
/* TN653 specifies to wait for 4ms with
|
/* TN653 specifies to wait for 4ms with
|
||||||
* clock generated but
|
* clock generated but
|
||||||
* status register bit MEMORY_ERASE goes low when ERASE_SRAM
|
* status register bit MEMORY_ERASE goes low when ERASE_SRAM
|
||||||
* is send and goes high after erase
|
* is send and goes high after erase
|
||||||
* this check seems enough
|
* this check seems enough
|
||||||
*/
|
*/
|
||||||
if (_idcode == 0x0001081b) // seems required for GW5AST...
|
if (_idcode == 0x0001081b) // seems required for GW5AST...
|
||||||
sendClkUs(10000);
|
sendClkUs(10000);
|
||||||
if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) {
|
if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) {
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
displayReadReg("after erase sram", readStatusReg());
|
displayReadReg("after erase sram", readStatusReg());
|
||||||
} else {
|
} else {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_command(XFER_DONE);
|
send_command(XFER_DONE);
|
||||||
send_command(NOOP);
|
send_command(NOOP);
|
||||||
if (!disableCfg()) {
|
if (!disableCfg()) {
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_gw5a) {
|
|
||||||
uint32_t status_reg = readStatusReg();
|
|
||||||
if ((loop >= 1) && ((status_reg & (1 << 13)) == 0))
|
|
||||||
must_loop = false;
|
|
||||||
loop++;
|
|
||||||
}
|
|
||||||
} while(must_loop);
|
|
||||||
|
|
||||||
if (_mode == Device::FLASH_MODE) {
|
if (_mode == Device::FLASH_MODE) {
|
||||||
uint32_t status_reg = readStatusReg();
|
uint32_t status_reg = readStatusReg();
|
||||||
|
|
@ -1190,18 +1179,16 @@ bool Gowin::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||||
|
|
||||||
bool Gowin::prepare_flash_access()
|
bool Gowin::prepare_flash_access()
|
||||||
{
|
{
|
||||||
/* Work around FPGA stuck in Bad Command status */
|
|
||||||
if (is_gw5a) {
|
|
||||||
reset();
|
|
||||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
|
||||||
_jtag->toggleClk(1000000);
|
|
||||||
}
|
|
||||||
if (!eraseSRAM()) {
|
if (!eraseSRAM()) {
|
||||||
printError("Error: fail to erase SRAM");
|
printError("Error: fail to erase SRAM");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_gw5a) {
|
if (is_gw5a) {
|
||||||
|
if (!eraseSRAM()) {
|
||||||
|
printError("Error: fail to erase SRAM");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
if (!gw5a_enable_spi()) {
|
if (!gw5a_enable_spi()) {
|
||||||
printError("Error: fail to switch GW5A to SPI mode");
|
printError("Error: fail to switch GW5A to SPI mode");
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
#include "board.hpp"
|
#include "board.hpp"
|
||||||
#include "cable.hpp"
|
#include "cable.hpp"
|
||||||
#include "colognechip.hpp"
|
#include "colognechip.hpp"
|
||||||
#include "common.hpp"
|
|
||||||
#include "cxxopts.hpp"
|
#include "cxxopts.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "dfu.hpp"
|
#include "dfu.hpp"
|
||||||
|
|
@ -575,7 +574,7 @@ int main(int argc, char **argv)
|
||||||
} else if (fab == "altera") {
|
} else if (fab == "altera") {
|
||||||
fpga = new Altera(jtag, args.bit_file, args.file_type,
|
fpga = new Altera(jtag, args.bit_file, args.file_type,
|
||||||
args.prg_type, args.fpga_part, args.bridge_path, args.verify,
|
args.prg_type, args.fpga_part, args.bridge_path, args.verify,
|
||||||
args.verbose, args.flash_sector, args.skip_load_bridge, args.skip_reset);
|
args.verbose, args.skip_load_bridge, args.skip_reset);
|
||||||
} else if (fab == "anlogic") {
|
} else if (fab == "anlogic") {
|
||||||
fpga = new Anlogic(jtag, args.bit_file, args.file_type,
|
fpga = new Anlogic(jtag, args.bit_file, args.file_type,
|
||||||
args.prg_type, args.verify, args.verbose);
|
args.prg_type, args.verify, args.verbose);
|
||||||
|
|
@ -809,7 +808,7 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
("file-type",
|
("file-type",
|
||||||
"provides file type instead of let's deduced by using extension",
|
"provides file type instead of let's deduced by using extension",
|
||||||
cxxopts::value<string>(args->file_type))
|
cxxopts::value<string>(args->file_type))
|
||||||
("flash-sector", "flash sector (Lattice and Altera MAX10 parts only)",
|
("flash-sector", "flash sector (Lattice parts only)",
|
||||||
cxxopts::value<string>(args->flash_sector))
|
cxxopts::value<string>(args->flash_sector))
|
||||||
("fpga-part", "fpga model flavor + package",
|
("fpga-part", "fpga model flavor + package",
|
||||||
cxxopts::value<string>(args->fpga_part))
|
cxxopts::value<string>(args->fpga_part))
|
||||||
|
|
@ -1044,8 +1043,7 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
||||||
args->secondary_bit_file.empty() &&
|
args->secondary_bit_file.empty() &&
|
||||||
!args->protect_flash &&
|
!args->protect_flash &&
|
||||||
!args->unprotect_flash &&
|
!args->unprotect_flash &&
|
||||||
!args->bulk_erase_flash &&
|
!args->bulk_erase_flash
|
||||||
!args->detect
|
|
||||||
) {
|
) {
|
||||||
printError("Error: secondary bitfile not specified");
|
printError("Error: secondary bitfile not specified");
|
||||||
cout << options.help() << endl;
|
cout << options.help() << endl;
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,10 @@ int McsParser::parse()
|
||||||
case 4:
|
case 4:
|
||||||
sscanf((char*)&str[DATA_BASE], "%4x", &loc_addr);
|
sscanf((char*)&str[DATA_BASE], "%4x", &loc_addr);
|
||||||
_base_addr = (loc_addr << 16);
|
_base_addr = (loc_addr << 16);
|
||||||
|
if ((size_t)_base_addr > _bit_data.size())
|
||||||
|
_bit_data.resize(_base_addr);
|
||||||
if (_base_addr * 8 > _bit_length)
|
if (_base_addr * 8 > _bit_length)
|
||||||
_bit_length = _base_addr * 8;
|
_bit_length = _base_addr * 8;
|
||||||
if (_bit_length > _bit_data.size() * 8)
|
|
||||||
_bit_data.resize(_bit_length / 8);
|
|
||||||
sum += (loc_addr & 0xff) + ((loc_addr >> 8) & 0xff);
|
sum += (loc_addr & 0xff) + ((loc_addr >> 8) & 0xff);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,6 @@ static std::map <uint32_t, fpga_model> fpga_list = {
|
||||||
{0x03620093, {"xilinx", "spartan7", "xc7s15ftgb196-1", 6}},
|
{0x03620093, {"xilinx", "spartan7", "xc7s15ftgb196-1", 6}},
|
||||||
{0x037c4093, {"xilinx", "spartan7", "xc7s25", 6}},
|
{0x037c4093, {"xilinx", "spartan7", "xc7s25", 6}},
|
||||||
{0x0362f093, {"xilinx", "spartan7", "xc7s50", 6}},
|
{0x0362f093, {"xilinx", "spartan7", "xc7s50", 6}},
|
||||||
{0x037c8093, {"xilinx", "spartan7", "xc7s75", 6}},
|
|
||||||
|
|
||||||
/* Xilinx Virtex6 */
|
/* Xilinx Virtex6 */
|
||||||
{0x8424a093, {"xilinx", "virtex6", "xc6vlx130t", 10}},
|
{0x8424a093, {"xilinx", "virtex6", "xc6vlx130t", 10}},
|
||||||
|
|
|
||||||
|
|
@ -456,22 +456,6 @@ static std::map <uint32_t, flash_t> flash_list = {
|
||||||
.quad_register = STATR,
|
.quad_register = STATR,
|
||||||
.quad_mask = (1 << 6),
|
.quad_mask = (1 << 6),
|
||||||
}},
|
}},
|
||||||
{0xc22019, {
|
|
||||||
/* https://www.mxic.com.tw/Lists/Datasheet/Attachments/8906/MX25L25645G,%203V,%20256Mb,%20v2.0.pdf */
|
|
||||||
.manufacturer = "Macronix",
|
|
||||||
.model = "MX25L25645G",
|
|
||||||
.nr_sector = 512,
|
|
||||||
.sector_erase = true,
|
|
||||||
.subsector_erase = true,
|
|
||||||
.has_extended = false,
|
|
||||||
.tb_otp = true,
|
|
||||||
.tb_offset = (1 << 3),
|
|
||||||
.tb_register = CONFR,
|
|
||||||
.bp_len = 5,
|
|
||||||
.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
|
|
||||||
.quad_register = STATR,
|
|
||||||
.quad_mask = (1 << 6),
|
|
||||||
}},
|
|
||||||
{0xc2201a, {
|
{0xc2201a, {
|
||||||
/* https://www.macronix.com/Lists/Datasheet/Attachments/8745/MX25L51245G,%203V,%20512Mb,%20v1.7.pdf */
|
/* https://www.macronix.com/Lists/Datasheet/Attachments/8745/MX25L51245G,%203V,%20512Mb,%20v1.7.pdf */
|
||||||
.manufacturer = "Macronix",
|
.manufacturer = "Macronix",
|
||||||
|
|
@ -596,66 +580,6 @@ static std::map <uint32_t, flash_t> flash_list = {
|
||||||
.quad_register = NONER,
|
.quad_register = NONER,
|
||||||
.quad_mask = 0,
|
.quad_mask = 0,
|
||||||
}},
|
}},
|
||||||
{0x6bbb14, {
|
|
||||||
.manufacturer = "Everspin",
|
|
||||||
.model = "EM008LX",
|
|
||||||
.nr_sector = 16,
|
|
||||||
.sector_erase = true,
|
|
||||||
.subsector_erase = true,
|
|
||||||
.has_extended = true,
|
|
||||||
.tb_otp = false,
|
|
||||||
.tb_offset = (1 << 5),
|
|
||||||
.tb_register = STATR,
|
|
||||||
.bp_len = 4,
|
|
||||||
.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
|
|
||||||
.quad_register = NONER,
|
|
||||||
.quad_mask = 0,
|
|
||||||
}},
|
|
||||||
{0x6bbb15, {
|
|
||||||
.manufacturer = "Everspin",
|
|
||||||
.model = "EM016LX",
|
|
||||||
.nr_sector = 32,
|
|
||||||
.sector_erase = true,
|
|
||||||
.subsector_erase = true,
|
|
||||||
.has_extended = true,
|
|
||||||
.tb_otp = false,
|
|
||||||
.tb_offset = (1 << 5),
|
|
||||||
.tb_register = STATR,
|
|
||||||
.bp_len = 4,
|
|
||||||
.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
|
|
||||||
.quad_register = NONER,
|
|
||||||
.quad_mask = 0,
|
|
||||||
}},
|
|
||||||
{0x6bbb16, {
|
|
||||||
.manufacturer = "Everspin",
|
|
||||||
.model = "EM032LX",
|
|
||||||
.nr_sector = 64,
|
|
||||||
.sector_erase = true,
|
|
||||||
.subsector_erase = true,
|
|
||||||
.has_extended = true,
|
|
||||||
.tb_otp = false,
|
|
||||||
.tb_offset = (1 << 5),
|
|
||||||
.tb_register = STATR,
|
|
||||||
.bp_len = 4,
|
|
||||||
.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
|
|
||||||
.quad_register = NONER,
|
|
||||||
.quad_mask = 0,
|
|
||||||
}},
|
|
||||||
{0x6bbb17, {
|
|
||||||
.manufacturer = "Everspin",
|
|
||||||
.model = "EM064LX",
|
|
||||||
.nr_sector = 128,
|
|
||||||
.sector_erase = true,
|
|
||||||
.subsector_erase = true,
|
|
||||||
.has_extended = true,
|
|
||||||
.tb_otp = false,
|
|
||||||
.tb_offset = (1 << 5),
|
|
||||||
.tb_register = STATR,
|
|
||||||
.bp_len = 4,
|
|
||||||
.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
|
|
||||||
.quad_register = NONER,
|
|
||||||
.quad_mask = 0,
|
|
||||||
}},
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,9 +230,7 @@ void SVF_jtag::parse_runtest(vector<string> const &vstr)
|
||||||
}
|
}
|
||||||
_jtag->set_state(_run_state);
|
_jtag->set_state(_run_state);
|
||||||
_jtag->toggleClk(nb_iter);
|
_jtag->toggleClk(nb_iter);
|
||||||
_jtag->flush();
|
if (min_duration > 0) {
|
||||||
if (min_duration > 0)
|
|
||||||
{
|
|
||||||
usleep((useconds_t)(min_duration * 1.0E6));
|
usleep((useconds_t)(min_duration * 1.0E6));
|
||||||
}
|
}
|
||||||
_jtag->set_state(_end_state);
|
_jtag->set_state(_end_state);
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
|
||||||
_secondary_file_extension = secondary_filename.substr(
|
_secondary_file_extension = secondary_filename.substr(
|
||||||
secondary_filename.find_last_of(".") + 1);
|
secondary_filename.find_last_of(".") + 1);
|
||||||
_mode = Device::SPI_MODE;
|
_mode = Device::SPI_MODE;
|
||||||
if (!(_device_package == "xcvu9p-flga2104" || _device_package == "xcku5p-ffvb676" || _device_package == "xcku040-ffva1156")) {
|
if (!(_device_package == "xcvu9p-flga2104" || _device_package == "xcku5p-ffvb676")) {
|
||||||
throw std::runtime_error("Error: secondary flash unavailable");
|
throw std::runtime_error("Error: secondary flash unavailable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue