Update to latest openFPGALoader files
This commit is contained in:
commit
f817819b3e
|
|
@ -38,8 +38,8 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- 18
|
||||
- 20
|
||||
- 22
|
||||
name: '🚧🐧 Ubuntu ${{ matrix.os }} | build'
|
||||
runs-on: ubuntu-${{ matrix.os }}.04
|
||||
steps:
|
||||
|
|
@ -52,6 +52,7 @@ jobs:
|
|||
sudo apt update -qq
|
||||
sudo apt install -y \
|
||||
cmake \
|
||||
gzip \
|
||||
libftdi1-2 \
|
||||
libftdi1-dev \
|
||||
libhidapi-hidraw0 \
|
||||
|
|
@ -121,8 +122,8 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- 18
|
||||
- 20
|
||||
- 22
|
||||
name: '🚦🐧 Ubuntu ${{ matrix.os }} | test'
|
||||
runs-on: ubuntu-${{ matrix.os }}.04
|
||||
steps:
|
||||
|
|
|
|||
|
|
@ -45,3 +45,6 @@ build/
|
|||
/doc/compatibility/boards.inc
|
||||
/doc/compatibility/cable.inc
|
||||
/doc/compatibility/fpga.inc
|
||||
|
||||
# VSCode local settings directory
|
||||
/.vscode/
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
# Copy this file to /etc/udev/rules.d/
|
||||
|
||||
ACTION!="add|change", GOTO="openfpgaloader_rules_end"
|
||||
|
||||
# gpiochip subsystem
|
||||
SUBSYSTEM=="gpio", MODE="0664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
SUBSYSTEM!="usb|tty|hidraw", GOTO="openfpgaloader_rules_end"
|
||||
|
||||
# Original FT232/FT245 VID:PID
|
||||
|
|
@ -23,6 +27,8 @@ ATTRS{idVendor}=="0547", ATTRS{idProduct}=="1002", MODE="664", GROUP="plugdev",
|
|||
|
||||
# altera usb-blaster
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6002", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6003", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# altera usb-blasterII - uninitialized
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6810", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
|
@ -32,10 +38,19 @@ ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev",
|
|||
# dirtyJTAG
|
||||
ATTRS{idVendor}=="1209", ATTRS{idProduct}=="c0ca", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Jlink
|
||||
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# NXP LPC-Link2
|
||||
ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="0090", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# NXP ARM mbed
|
||||
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# icebreaker bitsy
|
||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6146", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# orbtrace-mini dfu
|
||||
ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3442", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
LABEL="openfpgaloader_rules_end"
|
||||
|
|
|
|||
186
CMakeLists.txt
186
CMakeLists.txt
|
|
@ -1,25 +1,36 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
# set the project name
|
||||
project(openFPGALoader VERSION "0.7.0" LANGUAGES CXX)
|
||||
project(openFPGALoader VERSION "0.10.0" LANGUAGES CXX)
|
||||
add_definitions(-DVERSION=\"v${PROJECT_VERSION}\")
|
||||
|
||||
option(ENABLE_OPTIM "Enable build with -O3 optimization level" ON)
|
||||
option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(ENABLE_UDEV OFF)
|
||||
set(ENABLE_UDEV OFF)
|
||||
else()
|
||||
option(ENABLE_UDEV "use udev to search JTAG adapter from /dev/xx" ON)
|
||||
option(ENABLE_UDEV "use udev to search JTAG adapter from /dev/xx" ON)
|
||||
endif()
|
||||
option(ENABLE_CMSISDAP "enable cmsis DAP interface (requires hidapi)" ON)
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
option(ENABLE_LIBGPIOD "enable libgpiod bitbang driver (requires libgpiod)" ON)
|
||||
option(ENABLE_REMOTEBITBANG "enable remote bitbang driver" ON)
|
||||
else()
|
||||
set(ENABLE_LIBGPIOD OFF)
|
||||
set(ENABLE_REMOTEBITBANG OFF)
|
||||
endif()
|
||||
option(USE_PKGCONFIG "Use pkgconfig to find libraries" ON)
|
||||
option(LINK_CMAKE_THREADS "Use CMake find_package to link the threading library" OFF)
|
||||
set(BLASTERII_PATH "" CACHE STRING "usbBlasterII firmware directory")
|
||||
set(ISE_PATH "/opt/Xilinx/14.7" CACHE STRING "ise root directory (default: /opt/Xilinx/14.7)")
|
||||
|
||||
## specify the C++ standard
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
if (ENABLE_OPTIM)
|
||||
set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if (BUILD_STATIC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
|
@ -31,16 +42,20 @@ include(GNUInstallDirs)
|
|||
add_definitions(-DDATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}\")
|
||||
|
||||
add_definitions(-DISE_DIR=\"${ISE_PATH}\")
|
||||
add_definitions(-DBLASTERII_DIR=\"${BLASTERII_PATH}\")
|
||||
|
||||
if(USE_PKGCONFIG)
|
||||
if (USE_PKGCONFIG)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
|
||||
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
|
||||
pkg_check_modules(HIDAPI hidapi-hidraw)
|
||||
# if hidraw not found try with libusb
|
||||
if(NOT HIDAPI_FOUND)
|
||||
if (NOT HIDAPI_FOUND)
|
||||
pkg_check_modules(HIDAPI hidapi-libusb)
|
||||
endif()
|
||||
if (NOT HIDAPI_FOUND)
|
||||
pkg_check_modules(HIDAPI hidapi)
|
||||
endif()
|
||||
# zlib support (gzip)
|
||||
pkg_check_modules(ZLIB zlib)
|
||||
if (NOT ZLIB_FOUND)
|
||||
|
|
@ -53,7 +68,7 @@ if(USE_PKGCONFIG)
|
|||
endif()
|
||||
endif(NOT ZLIB_FOUND)
|
||||
|
||||
if(ENABLE_UDEV)
|
||||
if (ENABLE_UDEV)
|
||||
pkg_check_modules(LIBUDEV libudev)
|
||||
if (LIBUDEV_FOUND)
|
||||
add_definitions(-DUSE_UDEV)
|
||||
|
|
@ -62,6 +77,14 @@ if(USE_PKGCONFIG)
|
|||
set(ENABLE_UDEV OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ENABLE_LIBGPIOD)
|
||||
pkg_check_modules(LIBGPIOD libgpiod)
|
||||
if (NOT LIBGPIOD_FOUND)
|
||||
message("libgpiod not found, disabling gpiod support")
|
||||
set(ENABLE_LIBGPIOD OFF)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(OPENFPGALOADER_SOURCE
|
||||
|
|
@ -69,6 +92,7 @@ set(OPENFPGALOADER_SOURCE
|
|||
src/anlogicBitParser.cpp
|
||||
src/anlogicCable.cpp
|
||||
src/ch552_jtag.cpp
|
||||
src/common.cpp
|
||||
src/dfu.cpp
|
||||
src/dfuFileParser.cpp
|
||||
src/dirtyJtag.cpp
|
||||
|
|
@ -77,9 +101,10 @@ set(OPENFPGALOADER_SOURCE
|
|||
src/fx2_ll.cpp
|
||||
src/ice40.cpp
|
||||
src/ihexParser.cpp
|
||||
src/pofParser.cpp
|
||||
src/rawParser.cpp
|
||||
src/spiFlash.cpp
|
||||
src/spiInterface.cpp
|
||||
src/rawParser.cpp
|
||||
src/usbBlaster.cpp
|
||||
src/epcq.cpp
|
||||
src/svf_jtag.cpp
|
||||
|
|
@ -93,8 +118,10 @@ set(OPENFPGALOADER_SOURCE
|
|||
src/ftdipp_mpsse.cpp
|
||||
src/main.cpp
|
||||
src/latticeBitParser.cpp
|
||||
src/libusb_ll.cpp
|
||||
src/gowin.cpp
|
||||
src/device.cpp
|
||||
src/jlink.cpp
|
||||
src/lattice.cpp
|
||||
src/progressBar.cpp
|
||||
src/fsparser.cpp
|
||||
|
|
@ -114,6 +141,7 @@ set(OPENFPGALOADER_HEADERS
|
|||
src/anlogicBitParser.hpp
|
||||
src/anlogicCable.hpp
|
||||
src/ch552_jtag.hpp
|
||||
src/common.hpp
|
||||
src/cxxopts.hpp
|
||||
src/dfu.hpp
|
||||
src/dfuFileParser.hpp
|
||||
|
|
@ -123,14 +151,17 @@ set(OPENFPGALOADER_HEADERS
|
|||
src/fx2_ll.hpp
|
||||
src/ice40.hpp
|
||||
src/ihexParser.hpp
|
||||
src/pofParser.hpp
|
||||
src/progressBar.hpp
|
||||
src/rawParser.hpp
|
||||
src/usbBlaster.hpp
|
||||
src/bitparser.hpp
|
||||
src/ftdiJtagBitbang.hpp
|
||||
src/ftdiJtagMPSSE.hpp
|
||||
src/jlink.hpp
|
||||
src/jtag.hpp
|
||||
src/jtagInterface.hpp
|
||||
src/libusb_ll.hpp
|
||||
src/fsparser.hpp
|
||||
src/part.hpp
|
||||
src/board.hpp
|
||||
|
|
@ -157,6 +188,19 @@ set(OPENFPGALOADER_HEADERS
|
|||
src/colognechipCfgParser.hpp
|
||||
)
|
||||
|
||||
link_directories(
|
||||
${LIBUSB_LIBRARY_DIRS}
|
||||
${LIBFTDI_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if (ENABLE_LIBGPIOD)
|
||||
link_directories(${LIBGPIOD_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
if (ENABLE_CMSISDAP AND HIDAPI_FOUND)
|
||||
link_directories(${HIDAPI_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
add_executable(openFPGALoader
|
||||
${OPENFPGALOADER_SOURCE}
|
||||
${OPENFPGALOADER_HEADERS}
|
||||
|
|
@ -167,16 +211,6 @@ include_directories(
|
|||
${LIBFTDI_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
find_library(LIBFTDI1STATIC libftdi1.a REQUIRED)
|
||||
find_library(LIBUSB1STATIC libusb-1.0.a REQUIRED)
|
||||
target_link_libraries(openFPGALoader ${LIBFTDI1STATIC} ${LIBUSB1STATIC})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation -framework IOKit -framework Security")
|
||||
link_directories(/usr/local/lib)
|
||||
target_include_directories(openFPGALoader PRIVATE /usr/local/include)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
|
||||
else()
|
||||
target_link_libraries(openFPGALoader
|
||||
${LIBUSB_LIBRARIES}
|
||||
${LIBFTDI_LIBRARIES}
|
||||
|
|
@ -185,6 +219,9 @@ target_link_libraries(openFPGALoader
|
|||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# winsock provides ntohs
|
||||
target_link_libraries(openFPGALoader ws2_32)
|
||||
|
||||
target_sources(openFPGALoader PRIVATE src/pathHelper.cpp)
|
||||
list(APPEND OPENFPGALOADER_HEADERS src/pathHelper.hpp)
|
||||
endif()
|
||||
|
||||
# libusb_attach_kernel_driver is only available on Linux.
|
||||
|
|
@ -192,28 +229,72 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
add_definitions(-DATTACH_KERNEL)
|
||||
endif()
|
||||
|
||||
if(ENABLE_UDEV)
|
||||
include_directories(${LIBUDEV_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
|
||||
if (ENABLE_UDEV)
|
||||
include_directories(${LIBUDEV_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (ENABLE_LIBGPIOD)
|
||||
include_directories(${LIBGPIOD_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${LIBGPIOD_LIBRARIES})
|
||||
add_definitions(-DENABLE_LIBGPIOD=1)
|
||||
target_sources(openFPGALoader PRIVATE src/libgpiodJtagBitbang.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/libgpiodJtagBitbang.hpp)
|
||||
if (LIBGPIOD_VERSION VERSION_GREATER_EQUAL 2)
|
||||
message("libgpiod v2 support enabled")
|
||||
add_definitions(-DGPIOD_APIV2)
|
||||
else()
|
||||
message("libgpiod v1 support enabled")
|
||||
endif()
|
||||
endif(ENABLE_LIBGPIOD)
|
||||
|
||||
if (ENABLE_JETSONNANOGPIO)
|
||||
add_definitions(-DENABLE_JETSONNANOGPIO=1)
|
||||
target_sources(openFPGALoader PRIVATE src/jetsonNanoJtagBitbang.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/jetsonNanoJtagBitbang.hpp)
|
||||
message("Jetson Nano GPIO support enabled")
|
||||
endif(ENABLE_JETSONNANOGPIO)
|
||||
|
||||
if (ENABLE_UDEV OR ENABLE_LIBGPIOD OR ENABLE_JETSONNANOGPIO)
|
||||
add_definitions(-DUSE_DEVICE_ARG)
|
||||
endif(ENABLE_UDEV OR ENABLE_LIBGPIOD OR ENABLE_JETSONNANOGPIO)
|
||||
|
||||
if (BUILD_STATIC)
|
||||
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CMSISDAP)
|
||||
if (HIDAPI_FOUND)
|
||||
include_directories(${HIDAPI_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
|
||||
add_definitions(-DENABLE_CMSISDAP=1)
|
||||
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
|
||||
message("cmsis_dap support enabled")
|
||||
else()
|
||||
message("hidapi-libusb not found: cmsis_dap support disabled")
|
||||
endif()
|
||||
if (HIDAPI_FOUND)
|
||||
include_directories(${HIDAPI_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
|
||||
add_definitions(-DENABLE_CMSISDAP=1)
|
||||
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
|
||||
message("cmsis_dap support enabled")
|
||||
else()
|
||||
message("hidapi-libusb not found: cmsis_dap support disabled")
|
||||
endif()
|
||||
endif(ENABLE_CMSISDAP)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_definitions(-DENABLE_XVC=1)
|
||||
target_sources(openFPGALoader PRIVATE src/xvc_client.cpp src/xvc_server.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/xvc_client.hpp src/xvc_server.hpp)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-pthread ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
message("Xilinx Virtual Server support enabled")
|
||||
else()
|
||||
message("Xilinx Virtual Server support disabled")
|
||||
endif()
|
||||
|
||||
if (ENABLE_REMOTEBITBANG)
|
||||
add_definitions(-DENABLE_REMOTEBITBANG=1)
|
||||
target_sources(openFPGALoader PRIVATE src/remoteBitbang_client.cpp)
|
||||
list (APPEND OPENFPGALOADER_HEADERS src/remoteBitbang_client.hpp)
|
||||
message("Remote bitbang client support enabled")
|
||||
else()
|
||||
message("Remote bitbang client support disabled")
|
||||
endif()
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(openFPGALoader ${ZLIB_LIBRARIES})
|
||||
|
|
@ -221,7 +302,6 @@ if (ZLIB_FOUND)
|
|||
else()
|
||||
message("zlib library not found: can't flash intel/altera devices")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LINK_CMAKE_THREADS)
|
||||
find_package(Threads REQUIRED)
|
||||
|
|
@ -238,13 +318,43 @@ math(EXPR FTDI_VAL "${LIBFTDI_VERSION_MAJOR} * 100 + ${LIBFTDI_VERSION_MINOR}")
|
|||
add_definitions(-DFTDI_VERSION=${FTDI_VAL})
|
||||
|
||||
install(TARGETS openFPGALoader DESTINATION bin)
|
||||
file(GLOB BITS_FILES spiOverJtag/spiOverJtag_*.bit)
|
||||
file(GLOB RBF_FILES spiOverJtag/spiOverJtag_*.rbf)
|
||||
|
||||
file(GLOB GZ_FILES spiOverJtag/spiOverJtag_*.*.gz)
|
||||
install(FILES
|
||||
test_sfl.svf
|
||||
${BITS_FILES}
|
||||
${RBF_FILES}
|
||||
|
||||
# Compress rbf and bit files present into repository
|
||||
# TODO: test compat with Windows and MacOS
|
||||
list(INSERT CMAKE_MODULE_PATH 0 ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
||||
include(FindGZIP)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND GZIP_PRG)
|
||||
set(SPIOVERJTAG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spiOverJtag")
|
||||
file(GLOB BITS_FILES RELATIVE ${SPIOVERJTAG_DIR} spiOverJtag/spiOverJtag_*.bit)
|
||||
file(GLOB RBF_FILES RELATIVE ${SPIOVERJTAG_DIR} spiOverJtag/spiOverJtag_*.rbf)
|
||||
|
||||
STRING(REGEX REPLACE ".bit" ".bit.gz" BIT_GZ_FILES "${BITS_FILES}")
|
||||
STRING(REGEX REPLACE ".rbf" ".rbf.gz" RBF_GZ_FILES "${RBF_FILES}")
|
||||
|
||||
FOREACH(bit ${BITS_FILES} ${RBF_FILES})
|
||||
ADD_CUSTOM_COMMAND(OUTPUT ${bit}.gz
|
||||
COMMAND ${GZIP_PRG} -9 -c ${bit} > ${CMAKE_CURRENT_BINARY_DIR}/${bit}.gz
|
||||
DEPENDS ${SPIOVERJTAG_DIR}/${bit}
|
||||
WORKING_DIRECTORY ${SPIOVERJTAG_DIR}
|
||||
COMMENT "Building ${bit}.gz")
|
||||
list(APPEND GZ_FILES ${CMAKE_CURRENT_BINARY_DIR}/${bit}.gz)
|
||||
ENDFOREACH(bit)
|
||||
|
||||
ADD_CUSTOM_TARGET(bit ALL DEPENDS ${BIT_GZ_FILES} ${RBF_GZ_FILES})
|
||||
else()
|
||||
file(GLOB BITS_FILES spiOverJtag/spiOverJtag_*.bit)
|
||||
file(GLOB RBF_FILES spiOverJtag/spiOverJtag_*.rbf)
|
||||
install(FILES
|
||||
${BITS_FILES}
|
||||
${RBF_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
|
||||
)
|
||||
endif()
|
||||
|
||||
install(FILES
|
||||
${GZ_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
|
||||
)
|
||||
|
|
|
|||
134
README.md
134
README.md
|
|
@ -3,7 +3,7 @@
|
|||
<p align="right">
|
||||
<a title="Documentation" href="https://trabucayre.github.io/openFPGALoader"><img src="https://img.shields.io/website.svg?label=trabucayre.github.io%2FopenFPGALoader&longCache=true&style=flat-square&url=http%3A%2F%2Ftrabucayre.github.io%2FopenFPGALoader%2Findex.html&logo=GitHub"></a><!--
|
||||
-->
|
||||
<a title="'Test' workflow Status" href="https://github.com/trabucayre/openFPGALoader/actions?query=workflow%3ATest"><img alt="'Test' workflow Status" src="https://img.shields.io/github/workflow/status/trabucayre/openFPGALoader/Test?longCache=true&style=flat-square&label=Test&logo=github%20actions&logoColor=fff"></a><!--
|
||||
<a title="'Test' workflow Status" href="https://github.com/trabucayre/openFPGALoader/actions/workflows/Test.yml"><img alt="'Test' workflow Status" src="https://img.shields.io/github/actions/workflow/status/trabucayre/openFPGALoader/Test.yml?branch=master&longCache=true&style=flat-square&label=Test&logo=github%20actions&logoColor=fff"></a><!--
|
||||
-->
|
||||
<a title="Releases" href="https://github.com/trabucayre/openFPGALoader/releases"><img src="https://img.shields.io/github/commits-since/trabucayre/openFPGALoader/latest.svg?longCache=true&style=flat-square&logo=git&logoColor=fff"></a>
|
||||
</p>
|
||||
|
|
@ -29,6 +29,8 @@ Also checkout the vendor-specific documentation:
|
|||
[Lattice](https://trabucayre.github.io/openFPGALoader/vendors/lattice.html),
|
||||
[Xilinx](https://trabucayre.github.io/openFPGALoader/vendors/xilinx.html).
|
||||
|
||||
OpenFPGALoader has a dedicated channel: [#openFPGALoader at libera.chat](https://web.libera.chat/#openFPGALoader).
|
||||
|
||||
## Quick Usage
|
||||
|
||||
`arty` in the example below is one of the many FPGA board configurations listed [here](https://trabucayre.github.io/openFPGALoader/compatibility/board.html).
|
||||
|
|
@ -47,56 +49,96 @@ openFPGALoader -c cmsisdap fpga_bitstream.bit
|
|||
## Usage
|
||||
|
||||
```
|
||||
Usage: ./openFPGALoader [OPTION...] BIT_FILE
|
||||
Usage: openFPGALoader [OPTION...] BIT_FILE
|
||||
openFPGALoader -- a program to flash FPGA
|
||||
|
||||
--altsetting arg DFU interface altsetting (only for DFU mode)
|
||||
--bitstream arg bitstream
|
||||
-b, --board arg board name, may be used instead of cable
|
||||
-c, --cable arg jtag interface
|
||||
--invert-read-edge JTAG mode / FTDI: read on negative edge instead
|
||||
of positive
|
||||
--vid arg probe Vendor ID
|
||||
--pid arg probe Product ID
|
||||
--ftdi-serial arg FTDI chip serial number
|
||||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
||||
A-D)
|
||||
-d, --device arg device to use (/dev/ttyUSBx)
|
||||
--detect detect FPGA
|
||||
--dfu DFU mode
|
||||
--dump-flash Dump flash mode
|
||||
--external-flash select ext flash for device with internal and
|
||||
external storage
|
||||
--file-size arg provides size in Byte to dump, must be used with
|
||||
dump-flash
|
||||
--file-type arg provides file type instead of let's deduced by
|
||||
using extension
|
||||
--flash-sector arg flash sector (Lattice parts only)
|
||||
--fpga-part arg fpga model flavor + package
|
||||
--freq arg jtag frequency (Hz)
|
||||
-f, --write-flash write bitstream in flash (default: false)
|
||||
--index-chain arg device index in JTAG-chain
|
||||
--list-boards list all supported boards
|
||||
--list-cables list all supported cables
|
||||
--list-fpga list all supported FPGA
|
||||
-m, --write-sram write bitstream in SRAM (default: true)
|
||||
-o, --offset arg start offset in EEPROM
|
||||
--pins arg pin config (only for ft232R) TDI:TDO:TCK:TMS
|
||||
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
||||
--protect-flash arg protect SPI flash area
|
||||
--quiet Produce quiet output (no progress bar)
|
||||
-r, --reset reset FPGA after operations
|
||||
--spi SPI mode (only for FTDI in serial mode)
|
||||
--unprotect-flash Unprotect flash blocks
|
||||
-v, --verbose Produce verbose output
|
||||
--verbose-level arg verbose level -1: quiet, 0: normal, 1:verbose,
|
||||
2:debug
|
||||
-h, --help Give this help list
|
||||
--verify Verify write operation (SPI Flash only)
|
||||
-V, --Version Print program version
|
||||
--altsetting arg DFU interface altsetting (only for DFU mode)
|
||||
--bitstream arg bitstream
|
||||
--secondary-bitstream arg
|
||||
secondary bitstream (some Xilinx UltraScale
|
||||
boards)
|
||||
-b, --board arg board name, may be used instead of cable
|
||||
-B, --bridge arg disable spiOverJtag model detection by
|
||||
providing bitstream(intel/xilinx)
|
||||
-c, --cable arg jtag interface
|
||||
--invert-read-edge JTAG mode / FTDI: read on negative edge
|
||||
instead of positive
|
||||
--vid arg probe Vendor ID
|
||||
--pid arg probe Product ID
|
||||
--cable-index arg probe index (FTDI and cmsisDAP)
|
||||
--busdev-num arg select a probe by it bus and device number
|
||||
(bus_num:device_addr)
|
||||
--ftdi-serial arg FTDI chip serial number
|
||||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
||||
A-D)
|
||||
--detect detect FPGA
|
||||
--dfu DFU mode
|
||||
--dump-flash Dump flash mode
|
||||
--bulk-erase Bulk erase flash
|
||||
--target-flash arg for boards with multiple flash chips (some
|
||||
Xilinx UltraScale boards), select the target
|
||||
flash: primary (default), secondary or both
|
||||
--external-flash select ext flash for device with internal and
|
||||
external storage
|
||||
--file-size arg provides size in Byte to dump, must be used
|
||||
with dump-flash
|
||||
--file-type arg provides file type instead of let's deduced
|
||||
by using extension
|
||||
--flash-sector arg flash sector (Lattice parts only)
|
||||
--fpga-part arg fpga model flavor + package
|
||||
--freq arg jtag frequency (Hz)
|
||||
-f, --write-flash write bitstream in flash (default: false)
|
||||
--index-chain arg device index in JTAG-chain
|
||||
--ip arg IP address (XVC and remote bitbang client)
|
||||
--list-boards list all supported boards
|
||||
--list-cables list all supported cables
|
||||
--list-fpga list all supported FPGA
|
||||
-m, --write-sram write bitstream in SRAM (default: true)
|
||||
-o, --offset arg Start address (in bytes) for read/write into
|
||||
non volatile memory (default: 0)
|
||||
--pins arg pin config TDI:TDO:TCK:TMS
|
||||
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
||||
--protect-flash arg protect SPI flash area
|
||||
--quiet Produce quiet output (no progress bar)
|
||||
-r, --reset reset FPGA after operations
|
||||
--scan-usb scan USB to display connected probes
|
||||
--skip-load-bridge skip writing bridge to SRAM when in
|
||||
write-flash mode
|
||||
--skip-reset skip resetting the device when in write-flash
|
||||
mode
|
||||
--spi SPI mode (only for FTDI in serial mode)
|
||||
--unprotect-flash Unprotect flash blocks
|
||||
-v, --verbose Produce verbose output
|
||||
--verbose-level arg verbose level -1: quiet, 0: normal,
|
||||
1:verbose, 2:debug
|
||||
-h, --help Give this help list
|
||||
--verify Verify write operation (SPI Flash only)
|
||||
--port arg Xilinx Virtual Cable and remote bitbang Port
|
||||
(default 3721)
|
||||
--mcufw arg Microcontroller firmware
|
||||
--conmcu Connect JTAG to MCU
|
||||
-V, --Version Print program version
|
||||
|
||||
Mandatory or optional arguments to long options are also mandatory or optional
|
||||
for any corresponding short options.
|
||||
|
||||
Report bugs to <gwenhael.goavec-merou@trabucayre.com>.
|
||||
```
|
||||
|
||||
By default **spiOverJtag** are search into `${CMAKE_INSTALL_FULL_DATAROOTDIR}`
|
||||
(*/usr/local/share/* by default). It's possible to change this behaviour by
|
||||
using an environment variable:
|
||||
|
||||
```bash
|
||||
export OPENFPGALOADER_SOJ_DIR=/somewhere
|
||||
openFPGALoader xxxx
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
OPENFPGALOADER_SOJ_DIR=/somewhere openFPGALoader xxxx
|
||||
```
|
||||
|
||||
`OPENFPGALOADER_SOJ_DIR` must point to directory containing **spiOverJtag**
|
||||
bitstreams.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
FIND_PROGRAM(GZIP_PRG
|
||||
NAMES gzip
|
||||
PATHS /bin
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
${CYGWIN_INSTALL_PATH}/bin
|
||||
${MSYS_INSTALL_PATH}/usr/bin
|
||||
)
|
||||
|
||||
IF(NOT GZIP_PRG)
|
||||
message("Unable to find 'gzip' program")
|
||||
ENDIF(NOT GZIP_PRG)
|
||||
|
||||
|
|
@ -54,9 +54,10 @@ Gowin:
|
|||
- GW1NS-2C
|
||||
- GW1NSR-4C
|
||||
- GW1NZ-1
|
||||
- GW2A-18C
|
||||
URL: https://www.gowinsemi.com/en/product/detail/2/
|
||||
Memory: OK
|
||||
Flash: IF
|
||||
Flash: IF / EF
|
||||
|
||||
|
||||
Intel:
|
||||
|
|
@ -68,7 +69,9 @@ Intel:
|
|||
Flash: OK
|
||||
|
||||
- Description: Cyclone IV CE
|
||||
Model: EP4CE22
|
||||
Model:
|
||||
- EP4CE22
|
||||
- EP4CE115
|
||||
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-iv/features.html
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
|
@ -76,7 +79,9 @@ Intel:
|
|||
- Description: Cyclone V E
|
||||
Model:
|
||||
- 5CEA2
|
||||
- 5CEA5
|
||||
- 5CEBA4
|
||||
- 5CEBA9
|
||||
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-v.html
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
|
@ -96,6 +101,12 @@ Intel:
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- Description: Max 10
|
||||
Model: 10M08
|
||||
URL: https://www.intel.fr/content/www/fr/fr/products/details/fpga/max/10.html
|
||||
Memory: SVF
|
||||
Flash: SVF
|
||||
|
||||
|
||||
Lattice:
|
||||
|
||||
|
|
@ -107,8 +118,16 @@ Lattice:
|
|||
|
||||
- Description: ECP5
|
||||
Model:
|
||||
- 25F
|
||||
- 5G 85F
|
||||
- LFE5U-12
|
||||
- LFE5U-25
|
||||
- LFE5U-45
|
||||
- LFE5U-85
|
||||
- LFE5UM-25
|
||||
- LFE5UM-45
|
||||
- LFE5UM-85
|
||||
- LFE5UM5G-25
|
||||
- LFE5UM5G-45
|
||||
- LFE5UM5G-85
|
||||
URL: http://www.latticesemi.com/Products/FPGAandCPLD/ECP5
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
|
@ -163,6 +182,7 @@ Xilinx:
|
|||
|
||||
- Description: Artix 7
|
||||
Model:
|
||||
- xc7a25t
|
||||
- xc7a35ti
|
||||
- xc7a50t
|
||||
- xc7a75t
|
||||
|
|
@ -176,16 +196,42 @@ Xilinx:
|
|||
Model:
|
||||
- xc7k160t
|
||||
- xc7k325t
|
||||
- xc7k410t
|
||||
- xc7k420t
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-7.html#productTable
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- Description: Spartan 3
|
||||
Model: xc3s200
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/spartan-3.html
|
||||
- Description: Artix UltraScale+
|
||||
Model:
|
||||
- xcau25p
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/artix-ultrascale-plus.html
|
||||
Memory: OK
|
||||
Flash: TBD
|
||||
|
||||
- Description: Kintex UltraScale
|
||||
Model:
|
||||
- xcku035
|
||||
- xcku040
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-ultrascale.html#productTable
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- Description: Virtex UltraScale+
|
||||
Model:
|
||||
- xcvu9p
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/virtex-ultrascale-plus.html#productTable
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- Description: Spartan 3
|
||||
Model:
|
||||
- xc3s200
|
||||
- xc3s500e
|
||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/spartan-3.html
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- Description: Spartan 6
|
||||
Model:
|
||||
- xc6slx9
|
||||
|
|
@ -216,8 +262,10 @@ Xilinx:
|
|||
Memory: NA
|
||||
Flash: OK
|
||||
|
||||
- Description: XC2C (coolrunner II)
|
||||
Model: xc2c32a
|
||||
- Description: XC2C/XA2C (coolrunner II)
|
||||
Model:
|
||||
- xc2c32a
|
||||
- xa2c64a
|
||||
URL: https://www.xilinx.com/support/documentation/data_sheets/ds090.pdf
|
||||
Memory: TBD
|
||||
Flash: OK
|
||||
|
|
@ -240,7 +288,10 @@ Xilinx:
|
|||
Flash: NA
|
||||
|
||||
- Description: ZynqMPSoC
|
||||
Model: xczu2cg
|
||||
Model:
|
||||
- xczu2cg
|
||||
- xczu9eg
|
||||
- xczu11eg
|
||||
URL: https://www.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
|
|
|||
251
doc/boards.yml
251
doc/boards.yml
|
|
@ -13,6 +13,13 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: litex-acorn-baseboard-mini
|
||||
Description: The LiteX-Acorn-Baseboards are baseboards developed around the SQRL's Acorn board (or Nite/LiteFury)
|
||||
URL: https://github.com/enjoy-digital/litex-acorn-baseboard/
|
||||
FPGA: Artix xc7a200tsbg484
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: alchitry_au
|
||||
Description: Alchitry Au
|
||||
URL: https://alchitry.com/products/alchitry-au-fpga-development-board
|
||||
|
|
@ -20,6 +27,27 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: alchitry_au_plus
|
||||
Description: Alchitry Au+ (Plus)
|
||||
URL: https://www.sparkfun.com/products/17514
|
||||
FPGA: Artix xc7a100tftg256
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: alinx_ax516
|
||||
Description: ALINX AX516
|
||||
URL: https://www.alinx.com/en/detail/281
|
||||
FPGA: Spartan6 xc6slx16csg324
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: analogMax
|
||||
Description: Trenz TEI0010 - AnalogMax
|
||||
URL: https://wiki.trenz-electronic.de/display/PD/TEI0010+-+AnalogMax
|
||||
FPGA: Max 10 10M08SAU169C8G
|
||||
Memory: SVF
|
||||
Flash: SVF
|
||||
|
||||
- ID: arty_a7_35t
|
||||
Description: Digilent Arty A7
|
||||
URL: https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start
|
||||
|
|
@ -94,16 +122,23 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: cmod_s7
|
||||
Description: Digilent Cmod S7
|
||||
URL: https://https://digilent.com/reference/programmable-logic/cmod-s7/start
|
||||
FPGA: Spartan7 xc7s25csga225
|
||||
Memory: NA
|
||||
Flash: OK
|
||||
|
||||
- ID: gatemate_evb_jtag
|
||||
Description: Cologne Chip GateMate FPGA Evaluation Board (JTAG mode)
|
||||
URL: https://colognechip.com/programmable-logic/gatemate/
|
||||
URL: https://colognechip.com/programmable-logic/gatemate-evaluation-board/
|
||||
FPGA: Cologne Chip GateMate Series
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: gatemate_evb_spi
|
||||
Description: Cologne Chip GateMate FPGA Evaluation Board (SPI mode)
|
||||
URL: https://colognechip.com/programmable-logic/gatemate/
|
||||
URL: https://colognechip.com/programmable-logic/gatemate-evaluation-board/
|
||||
FPGA: Cologne Chip GateMate Series
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
|
@ -115,6 +150,14 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: cmoda7_35t
|
||||
Description: Digilent CmodA7
|
||||
URL: https://digilent.com/reference/programmable-logic/cmod-a7/start
|
||||
FPGA: Artix xc7a35tcpg236
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
Constraints: Cmod-A7-35T
|
||||
|
||||
- ID: colorlight
|
||||
Description: Colorlight 5A-75B (version 7)
|
||||
URL: https://fr.aliexpress.com/item/32281130824.html
|
||||
|
|
@ -152,6 +195,20 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: c10lp-refkit
|
||||
Description: Trenz c10lp-refkit
|
||||
URL: https://shop.trenz-electronic.de/en/TEI0009-02-055-8CA-Cyclone-10-LP-RefKit-10CL055-Development-Board-32-MByte-SDRAM-16-MByte-Flash
|
||||
FPGA: Cyclone 10 LP 10CL055YU484C8G
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: c5g
|
||||
Description: Terasic C5G (Cyclone V GX Starter Kit)
|
||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=830
|
||||
FPGA: Cyclone V GX 5CGXFC5C6F27C7N
|
||||
Memory: OK
|
||||
Flash: NT
|
||||
|
||||
- ID: de0
|
||||
Description: Terasic DE0
|
||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=364
|
||||
|
|
@ -172,6 +229,12 @@
|
|||
FPGA: Cyclone V SoC 5CSEMA4U23C6
|
||||
Memory: OK
|
||||
|
||||
- ID: de10lite
|
||||
Description: Terasic de10lite
|
||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=218&No=1021&PartNo=1
|
||||
FPGA: MAX 10 10M50DAF484C7G
|
||||
Memory: OK
|
||||
|
||||
- ID: de10nano
|
||||
Description: Terasic de10Nano
|
||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=205&No=1046
|
||||
|
|
@ -184,6 +247,12 @@
|
|||
FPGA: Cyclone V SoC 5CSEMA5F31C6
|
||||
Memory: OK
|
||||
|
||||
- ID: deca
|
||||
Description: Arrow/Terasic DECA
|
||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=&No=944&PartNo=1
|
||||
FPGA: MAX 10 10M50DAF484C6GES
|
||||
Memory: OK
|
||||
|
||||
- ID: ecp5_evn
|
||||
Description: Lattice ECP5 5G Evaluation Board
|
||||
URL: https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP5EvaluationBoard
|
||||
|
|
@ -224,6 +293,13 @@
|
|||
Memory: OK
|
||||
Flash: IF
|
||||
|
||||
- ID: hseda-xc6slx16
|
||||
Description: XILINX SPARTAN6 XC6SLX16 Microblaze SDRAM USB2.0 FPGA
|
||||
URL: http://hseda.com/product/xilinx/XC6SLX16/XC6SLX16.htm
|
||||
FPGA: Spartan6 xc6slx16-ftg256
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: ice40_generic
|
||||
Description: iCEBreaker
|
||||
URL: https://1bitsquared.com/collections/fpga/products/icebreaker
|
||||
|
|
@ -254,7 +330,7 @@
|
|||
Description: iCE40-HX8K
|
||||
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx
|
||||
FPGA: iCE40 HX8k
|
||||
Memory: NT
|
||||
Memory: OK
|
||||
Flash: AS
|
||||
Constraints: iCE40-HX8K
|
||||
|
||||
|
|
@ -274,6 +350,14 @@
|
|||
Flash: AS
|
||||
Constraints: iCE40HX8K-EVB
|
||||
|
||||
- ID: ice40_generic
|
||||
Description: iCE40 UltraPlus Breakout Board (iCE40UP5K-B-EVN)
|
||||
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40UltraPlusBreakoutBoard
|
||||
FPGA: iCE40-UP5K
|
||||
Memory: NT
|
||||
Flash: AS
|
||||
Constraints: iCE40-UP
|
||||
|
||||
- ID: ice40_generic
|
||||
Description: Icezum Alhambra II
|
||||
URL: https://alhambrabits.com/alhambra
|
||||
|
|
@ -290,6 +374,20 @@
|
|||
Flash: NT
|
||||
Constraints: KC705
|
||||
|
||||
- ID: LD-KONFEKT
|
||||
Description: Lone Dynamics Corporation - Machdyne Konfekt computer
|
||||
URL: https://machdyne.com/product/konfekt-computer/
|
||||
FPGA: ECP5 LFE5U-12F-6BG256C
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: LD-SCHOKO
|
||||
Description: Lone Dynamics Corporation - Machdyne Schoko computer
|
||||
URL: https://machdyne.com/product/schoko-computer/
|
||||
FPGA: ECP5 LFE5U-45F-6CABGA256
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: licheeTang
|
||||
Description: Sipeed Lichee Tang
|
||||
URL: https://tang.sipeed.com/en/hardware-overview/lichee-tang/
|
||||
|
|
@ -318,6 +416,22 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: nexys_a7_50
|
||||
Description: Digilent Nexys A7(Nexys 4 DDR)
|
||||
URL: https://digilent.com/reference/programmable-logic/nexys-a7/start
|
||||
FPGA: Artix xc7a50tcsg324
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
Constraints: Nexys4DDR
|
||||
|
||||
- ID: nexys_a7_100
|
||||
Description: Digilent Nexys A7(Nexys 4 DDR)
|
||||
URL: https://digilent.com/reference/programmable-logic/nexys-a7/start
|
||||
FPGA: Artix nexys_a7_100
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
Constraints: Nexys4DDR
|
||||
|
||||
- ID: nexysVideo
|
||||
Description: Digilent Nexys Video
|
||||
URL: https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start
|
||||
|
|
@ -325,6 +439,20 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: xem8320
|
||||
Description: Opal Kelly XEM8320
|
||||
URL: https://opalkelly.com/products/xem8320/
|
||||
FPGA: Artix UltraScale+ xcau25p-2ffvb676e
|
||||
Memory: OK
|
||||
Flash: TBD
|
||||
|
||||
- ID: orbtrace_dfu
|
||||
Description: ORBTrace mini (dfu mode)
|
||||
URL: https://store.zyp.no/product/orbtrace-mini
|
||||
FPGA: ECP5 LFE5U-25F-8BG256C
|
||||
Memory: NA
|
||||
Flash: OK (DFU)
|
||||
|
||||
- ID: orangeCrab
|
||||
Description: Orange Crab
|
||||
URL: https://github.com/gregdavill/OrangeCrab
|
||||
|
|
@ -333,6 +461,13 @@
|
|||
Flash: OK (DFU)
|
||||
Constraints: OrangeCrab-r0.2
|
||||
|
||||
- ID: papilio_one
|
||||
Description: Papilio One
|
||||
URL: https://papilio.cc/index.php?n=Papilio.PapilioOne
|
||||
FPGA: Spartan3E xc3s500e-vq100
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: pipistrello
|
||||
Description: Saanlima Pipistrello LX45
|
||||
URL: http://pipistrello.saanlima.com/index.php?title=Welcome_to_Pipistrello
|
||||
|
|
@ -340,6 +475,13 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: pynq_z2
|
||||
Description: PYNQ-Z2
|
||||
URL: https://www.tulembedded.com/FPGA/ProductsPYNQ-Z2.html
|
||||
FPGA: Zynq7000 xc7z020clg400
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: qmtechCycloneIV
|
||||
Description: QMTech CycloneIV Core Board
|
||||
URL: https://fr.aliexpress.com/item/32949281189.html
|
||||
|
|
@ -354,6 +496,13 @@
|
|||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: qmtechCycloneV_5ce523
|
||||
Description: QMTech CycloneV Core Board
|
||||
URL: https://fr.aliexpress.com/item/1005001782703399.html
|
||||
FPGA: Cyclone V 5CEFA5F23I7
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: qmtechKintex7
|
||||
Description: QMTech Kintex7 Core Board
|
||||
URL: https://www.aliexpress.com/item/1005003668804223.html
|
||||
|
|
@ -390,12 +539,19 @@
|
|||
Flash: NA
|
||||
|
||||
- ID: SPEC150
|
||||
Description: CERN Simple PCIe FMC carrier SPEC
|
||||
Description: CERN Simple PCIe FMC carrier SPEC
|
||||
URL: https://ohwr.org/project/spec150/wikis/home
|
||||
FPGA: Spartan6 xc6slx150Tfgg484
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: stlv7325
|
||||
Description: Sitlinv STLV7325 Board
|
||||
URL: https://www.aliexpress.com/item/1005001275162791.html
|
||||
FPGA: Kintex xc7k325tffg676
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: tangnano
|
||||
Description: Sipeed Tang Nano
|
||||
URL: https://tangnano.sipeed.com/en/
|
||||
|
|
@ -423,6 +579,20 @@
|
|||
Memory: OK
|
||||
Flash: IF/EF
|
||||
|
||||
- ID: tangnano20k
|
||||
Description: Sipeed Tang Nano 20k
|
||||
URL: https://wiki.sipeed.com/nano20k
|
||||
FPGA: Gowin Arora GW2A(R)-18(C)
|
||||
Memory: OK
|
||||
Flash: EF
|
||||
|
||||
- ID: tangprimer20k
|
||||
Description: Sipeed Tang Primer 20k
|
||||
URL: https://wiki.sipeed.com/en/primer20k
|
||||
FPGA: Gowin Arora GW2A(R)-18(C)
|
||||
Memory: OK
|
||||
Flash: EF
|
||||
|
||||
- ID: tec0117
|
||||
Description: Trenz Gowin LittleBee (TEC0117)
|
||||
URL: https://shop.trenz-electronic.de/en/TEC0117-01-FPGA-Module-with-GOWIN-LittleBee-and-8-MByte-internal-SDRAM
|
||||
|
|
@ -430,6 +600,20 @@
|
|||
Memory: OK
|
||||
Flash: IF
|
||||
|
||||
- ID: trion_t120_bga576_spi
|
||||
Description: Efinix Trion T120 BGA576 Dev Kit
|
||||
URL: https://www.efinixinc.com/products-devkits-triont120bga576.html
|
||||
FPGA: Trion T120BGA576
|
||||
Memory: NA
|
||||
Flash: AS
|
||||
|
||||
- ID: trion_ti60_f225_spi
|
||||
Description: Efinix Titanium F225 Dev Kit
|
||||
URL: https://www.efinixinc.com/products-devkits-titaniumti60f225.html
|
||||
FPGA: Titanium Ti60F225
|
||||
Memory: NA
|
||||
Flash: AS
|
||||
|
||||
- ID: ulx3s
|
||||
Description: Radiona ULX3S
|
||||
URL: https://radiona.org/ulx3s/
|
||||
|
|
@ -463,19 +647,19 @@
|
|||
Memory: NA
|
||||
Flash: AS
|
||||
|
||||
- ID: trion_t120_bga576_spi
|
||||
Description: Efinix Trion T120 BGA576 Dev Kit
|
||||
URL: https://www.efinixinc.com/products-devkits-triont120bga576.html
|
||||
FPGA: Trion T120BGA576
|
||||
Memory: NA
|
||||
Flash: AS
|
||||
- ID: usrpx300
|
||||
Description: Ettus Research USRP X300
|
||||
URL: https://www.ettus.com/all-products/x300-kit/
|
||||
FPGA: Kintex xc7k325tffg900
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: trion_ti60_f225_spi
|
||||
Description: Efinix Titanium F225 Dev Kit
|
||||
URL: https://www.efinixinc.com/products-devkits-titaniumti60f225.html
|
||||
FPGA: Titanium Ti60F225
|
||||
Memory: NA
|
||||
Flash: AS
|
||||
- ID: usrpx310
|
||||
Description: Ettus Research USRP X300
|
||||
URL: https://www.ettus.com/all-products/x310-kit/
|
||||
FPGA: Kintex xc7k410tffg900
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: xmf3
|
||||
Description: PLDkit XMF3
|
||||
|
|
@ -499,6 +683,20 @@
|
|||
Flash: NA
|
||||
Constraints: ZC706
|
||||
|
||||
- ID: zcu102
|
||||
Description: Xilinx ZCU102
|
||||
URL: https://www.xilinx.com/products/boards-and-kits/ek-u1-zcu102-g.html
|
||||
FPGA: zynqMPSoC XCZU9EG
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: zcu106
|
||||
Description: Xilinx ZCU106
|
||||
URL: https://www.xilinx.com/products/boards-and-kits/zcu106.html
|
||||
FPGA: zynqMPSoC XCZU7EV
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: zedboard
|
||||
Description: Avnet ZedBoard
|
||||
URL: https://www.avnet.com/wps/portal/us/products/avnet-boards/avnet-board-families/zedboard/
|
||||
|
|
@ -520,3 +718,24 @@
|
|||
FPGA: zynq7000 xc7z020clg400
|
||||
Memory: OK
|
||||
Flash: NA
|
||||
|
||||
- ID: vcu118
|
||||
Description: Xilinx VCU118
|
||||
URL: https://www.xilinx.com/products/boards-and-kits/vcu118.html
|
||||
FPGA: Virtex UltraScale+ xcvu9p-flga2104
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: vcu128
|
||||
Description: Xilinx VCU128
|
||||
URL: https://www.xilinx.com/products/boards-and-kits/vcu128.html
|
||||
FPGA: Virtex UltraScale+ xcvu37p-fsvh2892
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
||||
- ID: kcu116
|
||||
Description: Xilinx KCU116
|
||||
URL: https://www.xilinx.com/products/boards-and-kits/kcu116.html
|
||||
FPGA: Kintex UltraScale+ xcku5p-ffvb676
|
||||
Memory: OK
|
||||
Flash: OK
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ ft2232:
|
|||
Description: USB-JTAG/UART debugger based on BL702 microcontroler.
|
||||
URL: https://github.com/sipeed/RV-Debugger-BL702
|
||||
|
||||
- Name: Sipeed RV-Debugger-BL702
|
||||
Description: RV-Debugger-BL702 is an opensource project that implement a JTAG+UART debugger with BL702C-A0.
|
||||
URL: https://github.com/sipeed/RV-Debugger-BL702
|
||||
|
||||
- Name: honeycomb USB-JTAG interface.
|
||||
Description: FT2232C clone based on STM32F042 microcontroler
|
||||
URL: https://github.com/Disasm/f042-ftdi
|
||||
|
|
@ -172,6 +176,19 @@ ecpix5-debug:
|
|||
URL: https://shop.lambdaconcept.com/home/46-ecpix-5.html
|
||||
|
||||
|
||||
jlink:
|
||||
|
||||
- Name: jlink
|
||||
Description: SEGGER J-Link Debug Probes
|
||||
URL: https://www.segger.com/products/debug-probes/j-link
|
||||
|
||||
- Name: jlink_base
|
||||
Description: SEGGER J-Link BASE Debug Probes
|
||||
|
||||
- Name: jtrace_pro
|
||||
Description: SEGGER J-Trace PRO Debug Probes
|
||||
|
||||
|
||||
jtag-smt2-nc:
|
||||
|
||||
- Name: jtag-smt2-nc
|
||||
|
|
@ -179,6 +196,13 @@ jtag-smt2-nc:
|
|||
URL: https://digilent.com/shop/jtag-smt2-nc-surface-mount-programming-module
|
||||
|
||||
|
||||
lpc-link2:
|
||||
|
||||
- Name: lpc-link2
|
||||
Description: LPC-Link2 (OM13054) cmsisDAP firmware
|
||||
URL: https://www.nxp.com/design/microcontrollers-developer-resources/lpc-link2:OM13054
|
||||
|
||||
|
||||
orbtrace:
|
||||
|
||||
- Name: orbtrace interface
|
||||
|
|
@ -186,6 +210,27 @@ orbtrace:
|
|||
URL: https://github.com/orbcode/orbtrace
|
||||
|
||||
|
||||
papilio:
|
||||
|
||||
- Name: papilio
|
||||
Description: Papilio FPGA Platform
|
||||
URL: https://papilio.cc/
|
||||
|
||||
|
||||
steppenprobe:
|
||||
|
||||
- Name: steppenprobe
|
||||
Description: Open Source Hardware JTAG/SWD/UART/SWO interface board based on FTDI FT2232H
|
||||
URL: https://github.com/diegoherranz/steppenprobe
|
||||
|
||||
|
||||
remote-bitgang:
|
||||
|
||||
- Name: OpenOCD remote bitbang
|
||||
Description: The remote_bitbang JTAG driver is used to drive JTAG from a remote (TCP) process
|
||||
URL: https://github.com/openocd-org/openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
|
||||
|
||||
|
||||
tigard:
|
||||
|
||||
- Name: tigard
|
||||
|
|
@ -204,3 +249,30 @@ usb-blasterII:
|
|||
- Name: intel USB Blaster II interface
|
||||
Description: JTAG programmer cable from intel/altera (EZ-USB FX2 + EPM570)
|
||||
URL: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_usb_blstr_ii_cable.pdf
|
||||
|
||||
|
||||
xvc-client:
|
||||
|
||||
- Name: Xilinx Virtual Cable
|
||||
Description: Xilinx Virtual Cable (XVC) is a TCP/IP-based protocol that acts like a JTAG cable.
|
||||
URL: https://github.com/Xilinx/XilinxVirtualCable
|
||||
|
||||
|
||||
xvc-server:
|
||||
|
||||
- Name: Xilinx Virtual Cable (server side)
|
||||
Description: Xilinx Virtual Cable (XVC) is a TCP/IP-based protocol that acts like a JTAG cable.
|
||||
URL: https://github.com/Xilinx/XilinxVirtualCable
|
||||
|
||||
|
||||
libgpiod:
|
||||
|
||||
- Name: Bitbang GPIO
|
||||
Description: Bitbang GPIO pins on Linux host.
|
||||
URL: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
|
||||
|
||||
jetson-nano-gpio:
|
||||
|
||||
- Name: Bitbang GPIO
|
||||
Description: Bitbang GPIO pins on Jetson Nano Linux host. Use /dev/mem to have a faster clock.
|
||||
URL: https://github.com/jwatte/jetson-gpio-example
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Resetting an FPGA
|
|||
openFPGALoader [options] -r
|
||||
|
||||
Using negative edge for TDO's sampling
|
||||
====================================
|
||||
======================================
|
||||
|
||||
If transaction are unstable you can try to change read edge by using
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ Automatic file type detection bypass
|
|||
====================================
|
||||
|
||||
Default behavior is to use file extension to determine file parser.
|
||||
To avoid this mecanism ``--file-type type`` must be used.
|
||||
To avoid this mechanism ``--file-type type`` must be used.
|
||||
|
||||
FT231/FT232 bitbang mode and pins configuration
|
||||
===============================================
|
||||
|
|
@ -82,3 +82,20 @@ 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
|
||||
one to write raw binary file to an arbitrary adress in FLASH.
|
||||
|
||||
Using an alternative directory for *spiOverJtag*
|
||||
================================================
|
||||
|
||||
By setting ``OPENFPGALOADER_SOJ_DIR`` it's possible to override default
|
||||
*spiOverJtag* bitstreams directory:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
export OPENFPGALOADER_SOJ_DIR=/somewhere
|
||||
openFPGALoader xxxx
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
OPENFPGALOADER_SOJ_DIR=/somewhere openFPGALoader xxxx
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ First steps with openFPGALoader
|
|||
Install
|
||||
=======
|
||||
|
||||
Packages are available for Linux distributionsm, Windows (MSYS2) and macOS:
|
||||
Packages are available for Linux distributions, Windows (MSYS2) and macOS:
|
||||
|
||||
* *Arch Linux*: ``sudo pacman -S openfpgaloader``
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Alternatively, you could build from source. First: install required libraries:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo pacman -S git cmake make gcc pkgconf libftdi libusb zlib hidapi
|
||||
sudo pacman -S git cmake make gcc pkgconf libftdi libusb zlib hidapi gzip
|
||||
|
||||
Build step is similar as Debian
|
||||
|
||||
|
|
@ -41,6 +41,8 @@ This application uses ``libftdi1``, so this library must be installed (and, depe
|
|||
.. code-block:: bash
|
||||
|
||||
sudo apt install \
|
||||
git \
|
||||
gzip \
|
||||
libftdi1-2 \
|
||||
libftdi1-dev \
|
||||
libhidapi-hidraw0 \
|
||||
|
|
@ -85,6 +87,14 @@ You may also need to add this if you see link errors between ``libusb`` and ``pt
|
|||
|
||||
-DLINK_CMAKE_THREADS=ON
|
||||
|
||||
By default, ``libgpiod`` support is enabled
|
||||
If you don't want this option, use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
-DENABLE_LIBGPIOD=OFF
|
||||
|
||||
Additionaly you have to install ``libgpiod``
|
||||
|
||||
To build the app:
|
||||
|
||||
|
|
@ -125,6 +135,14 @@ These rules set access right and group (``plugdev``) when a converter is plugged
|
|||
|
||||
After that you need to unplug and replug your device.
|
||||
|
||||
.. HINT::
|
||||
``usermod`` is used to add ``$USER`` as a member of ``plugdev`` group.
|
||||
However this update is not taken into account immediately: it's required to
|
||||
logout from current session and login again.
|
||||
Check, by using ``id $USER``, if ``plugdev`` is mentioned after ``groups=``.
|
||||
An alternate (and temporary) solution is to use ``sudo - $USER`` to have
|
||||
your user seen as a member of ``plugdev`` group (works only for the current terminal).
|
||||
|
||||
macOS
|
||||
=====
|
||||
|
||||
|
|
@ -134,6 +152,19 @@ openFPGALoader is available as a `Homebrew <https://brew.sh>`__ formula:
|
|||
|
||||
brew install openfpgaloader
|
||||
|
||||
Alternatively, if you want to build it by hand:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
brew install --only-dependencies openfpgaloader
|
||||
brew install cmake pkg-config zlib gzip
|
||||
git clone https://github.com/trabucayre/openFPGALoader
|
||||
cd openFPGALoader
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j
|
||||
|
||||
Windows
|
||||
=======
|
||||
|
||||
|
|
|
|||
|
|
@ -8,3 +8,38 @@ I installed openFPGALoader but it says `command not found` when I try to launch
|
|||
|
||||
The correct spelling of the program is *openFPGALoader* with FPGA and the "L" of "Loader" in uppercase.
|
||||
Ensure the spelling of the program is correct.
|
||||
|
||||
Gowin device could not communicate since last bitstream flashed. (issue `#206 <https://github.com/trabucayre/openFPGALoader/issues/206>`_)
|
||||
==========================================================================================================================================
|
||||
|
||||
Gowin's FPGA may fails to be detected if **JTAGSEL_N** (pin 08 for *GW1N-4K*) is used as a GPIO.
|
||||
To recover you have to pull down this pin (before power up) to recover JTAG interface (*UG292 - JTAGSELL_N section*).
|
||||
|
||||
JTAG init failed
|
||||
================
|
||||
|
||||
Avoid using USB hubs and connect it directly to your PC USB port.
|
||||
|
||||
|
||||
Tang Primer 20k program slow and stucked (issue `#250 <https://github.com/trabucayre/openFPGALoader/issues/250>`_)
|
||||
==================================================================================================================
|
||||
|
||||
Check your openFPGALoader version:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
openFPGALoader -V
|
||||
|
||||
If it is older than release then v0.9.0, install the most recent version (from commit `f5b89bff68a5e2147404a895c075773884077438 <https://github.com/trabucayre/openFPGALoader/commit/fe259fb78d185b3113661d04cd7efa9ae0232425>`_ or later).
|
||||
|
||||
Cannot flash Tang Nano 9k (issue `#251 <https://github.com/trabucayre/openFPGALoader/issues/251>`_)
|
||||
===================================================================================================
|
||||
|
||||
This is a device issue, erase its Embedded Flash using Official GoWin Programmer (preferentially in Windows) and SRAM too, then you can use openFPGALoader again.
|
||||
|
||||
Unable to open FTDI device: -4 (usb_open() failed) (issue `#245 <https://github.com/trabucayre/openFPGALoader/issues/245>`_)
|
||||
============================================================================================================================
|
||||
|
||||
Edit your `/etc/udev/rules.d/99-ftdi.rules` file exchanging your programming device permissions.
|
||||
|
||||
For more information, check the udev section from `this guide <install.rst>`_
|
||||
|
|
@ -17,7 +17,7 @@ Supported configuration files are bitfiles ``*.bit`` and it's ASCII equivalents
|
|||
JTAG Configuration
|
||||
------------------
|
||||
|
||||
Performs an active hardware reset and writes the configuration into the FPGA latches via JTAG. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xF0 (JTAG).
|
||||
Performs an active hardware reset and writes the configuration into the FPGA latches via JTAG. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xC (JTAG).
|
||||
|
||||
1. Program using Evaluation Board:
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ Performs an active hardware reset and writes the configuration into the FPGA lat
|
|||
SPI Configuration
|
||||
-----------------
|
||||
|
||||
Performs an active hardware reset and writes the configuration into the FPGA latches via SPI. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0x40 (SPI passive).
|
||||
Performs an active hardware reset and writes the configuration into the FPGA latches via SPI. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0x4 (SPI passive).
|
||||
|
||||
1. Program using Evaluation Board:
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ Performs an active hardware reset and writes the configuration into the FPGA lat
|
|||
JTAG Flash Access
|
||||
-----------------
|
||||
|
||||
It is possible to access external flashes via the internal JTAG-SPI-bypass. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xF0 (JTAG). Note that the FPGA will not start automatically.
|
||||
It is possible to access external flashes via the internal JTAG-SPI-bypass. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xC (JTAG). Note that the FPGA will not start automatically.
|
||||
|
||||
1. Write to flash using Evaluation Board:
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ The `offset` parameter can be used to store data at any point in the flash, e.g.
|
|||
SPI Flash Access
|
||||
----------------
|
||||
|
||||
If the programming device and FPGA share the same SPI signals, it is possible to hold the FPGA in reset and write data to the flash. The configuration mode can be set as desired. If the FPGA should start from the external memory after reset, the configuration mode pins ``CFG_MD[3:0]`` set to 0x00 (SPI active).
|
||||
If the programming device and FPGA share the same SPI signals, it is possible to hold the FPGA in reset and write data to the flash. The configuration mode can be set as desired. If the FPGA should start from the external memory after reset, the configuration mode pins ``CFG_MD[3:0]`` set to 0x0 (SPI active).
|
||||
|
||||
1. Write to flash using Evaluation Board:
|
||||
|
||||
|
|
@ -92,4 +92,4 @@ The `offset` parameter can be used to store data at any point in the flash, e.g.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader -b gatemate_evb_spi -o <offset> <bitfile>.cfg.bit
|
||||
openFPGALoader -b gatemate_evb_spi -o <offset> <bitfile>.cfg.bit
|
||||
|
|
|
|||
|
|
@ -25,3 +25,27 @@ or, for xyloni board
|
|||
|
||||
Since openFPGALoader access the flash directly in SPI mode the ``-b fireant``, ``-b xyloni_spi`` is required (no
|
||||
autodetection possible).
|
||||
|
||||
Trion and Titanium JTAG usage
|
||||
==========================================
|
||||
|
||||
*openFPGALoader* supports loading to RAM and SPI Flash with JTAG
|
||||
|
||||
Tested with J-Link BASE
|
||||
|
||||
bin file load
|
||||
-------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader --cable jlink_base -m /somewhere/project/outflow/*.bin
|
||||
|
||||
hex file flash
|
||||
-------------
|
||||
|
||||
Example for ti60f225.
|
||||
NOTE: JTAG chains with more than one device (eg --index-chain) are currently not supported for writing to SPI flash
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader --cable jlink_base --fpga-part ti60f225 -f /somewhere/project/outflow/*.hex
|
||||
|
|
@ -31,7 +31,11 @@ where ``BOARD_NAME`` is:
|
|||
|
||||
* ``tec0117``
|
||||
* ``tangnano``
|
||||
* ``tangnano1k``
|
||||
* ``tangnano4k``
|
||||
* ``tangnano9k``
|
||||
* ``tangnano20k``
|
||||
* ``tangprimer20k``
|
||||
* ``runber``
|
||||
|
||||
Flash
|
||||
|
|
@ -53,3 +57,8 @@ where ``BOARD_NAME`` is:
|
|||
|
||||
It's possible to flash external SPI Flash (connected to MSPI) in bscan mode by using ``--external-flash`` instead of
|
||||
``-f``.
|
||||
|
||||
.. NOTE::
|
||||
|
||||
Gowin's FPGA may fails to be detected if **JTAGSEL_N** (pin 08 for *GW1N-4K*) is used as a GPIO.
|
||||
To recover you have to pull down this pin (before power up) to recover JTAG interface (*UG292 - JTAGSELL_N section*).
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Intel/Altera
|
|||
.. NOTE::
|
||||
|
||||
* CYC1000
|
||||
* C10LP-RefKit
|
||||
* DE0
|
||||
* de0nano
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ SVF and RBF files are supported.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
quartus_cpf -c -q -g 3.3 -n 12.0MHz p project_name.sof project_name.svf
|
||||
quartus_cpf -c -q 12.0MHz -g 3.3 -n p project_name.sof project_name.svf
|
||||
|
||||
``sof`` to ``rbf`` generation:
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ SVF and RBF files are supported.
|
|||
quartus_cpf --option=bitstream_compression=off -c project_name.sof project_name.rbf
|
||||
|
||||
.. WARNING::
|
||||
As mentionned in ``cyclone`` handbooks, real-time decompression is not supported by FPGA in JTAG mode.
|
||||
As mentioned in ``cyclone`` handbooks, real-time decompression is not supported by FPGA in JTAG mode.
|
||||
Keep in mind to disable this option.
|
||||
|
||||
file load:
|
||||
|
|
@ -41,7 +42,7 @@ file load:
|
|||
# or
|
||||
openFPGALoader -b boardname project_name.rbf
|
||||
|
||||
with ``boardname`` = ``de0``, ``cyc1000``, ``de0nano``, ``de0nanoSoc`` or ``qmtechCycloneV``.
|
||||
with ``boardname`` = ``de0``, ``cyc1000``, ``c10lp-refkit``, ``de0nano``, ``de0nanoSoc`` or ``qmtechCycloneV``.
|
||||
|
||||
SPI flash
|
||||
---------
|
||||
|
|
@ -52,12 +53,17 @@ RPD and RBF are supported.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
# CYC1000
|
||||
quartus_cpf -o auto_create_rpd=on -c -d EPCQ16A -s 10CL025YU256C8G project_name.svf project_name.jic
|
||||
# C10LP-RefKit
|
||||
quartus_cpf -o auto_create_rpd=on -c -d EPCQ16A -s 10CL055YU484C8G project_name.svf project_name.jic
|
||||
|
||||
file load:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader -b cyc1000 -r project_name_auto.rpd
|
||||
openFPGALoader -b boardname -r project_name_auto.rpd
|
||||
# or
|
||||
openFPGALoader -b cyc1000 -r project_name.rbf
|
||||
openFPGALoader -b boardname -r project_name.rbf
|
||||
|
||||
with ``boardname`` = ``cyc1000``, ``c10lp-refkit``.
|
||||
|
|
|
|||
|
|
@ -16,13 +16,18 @@ File load:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader [-b yourboard] impl1/*.jed
|
||||
openFPGALoader [-b yourboard] [--flash-sector CFG0] impl1/*.jed
|
||||
|
||||
where ``yourboard`` may be:
|
||||
|
||||
* ``machX02EVN``
|
||||
* ``machX03EVN``
|
||||
* ``machXO3SK``
|
||||
|
||||
and where ``--flash-sector CFG0`` is needed for the MachXO3D Breakout Board.
|
||||
|
||||
``.bit`` may also be used for *machXO2*
|
||||
|
||||
SRAM
|
||||
----
|
||||
|
||||
|
|
@ -37,6 +42,7 @@ File load:
|
|||
where ``yourboard`` may be:
|
||||
|
||||
* ``machX02EVN``
|
||||
* ``machX03EVN``
|
||||
* ``machXO3SK``
|
||||
|
||||
iCE40
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ SPI flash
|
|||
.. NOTE::
|
||||
``.bit``, ``.bin``, and ``.mcs`` are supported for FLASH.
|
||||
|
||||
``.mcs`` must be generated through vivado with a tcl script like:
|
||||
``.mcs`` must be generated through Vivado with a tcl script like:
|
||||
|
||||
.. code-block:: tcl
|
||||
|
||||
|
|
@ -94,5 +94,24 @@ File load:
|
|||
.. NOTE::
|
||||
``--fpga-part`` is only required if this information is not provided at ``board.hpp`` level or if the board is not
|
||||
officially supported.
|
||||
device/packagee format is something like xc7a35tcsg324 (arty model).
|
||||
device/package format is something like xc7a35tcsg324 (arty model).
|
||||
See :ghsrc:`src/board.hpp <src/board.hpp>`, or :ghsrc:`spiOverJtag <spiOverJtag>` directory for examples.
|
||||
|
||||
Some boards with UltraScale FPGAs, like the VCU118 and KCU16, support the SPIx8 (Dual Quad SPI) configuration.
|
||||
In this case, the ``spix8`` option ``write_cfgmem`` on the above example can be used to generate two ``.mcs`` files,
|
||||
to fit bigger designs or for faster programming. Only ``.mcs`` files can be used to program the FPGA in this case.
|
||||
|
||||
In this case, to load the two ``.mcs`` files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader --board vcu118 -f --target-flash both --bitstream *.runs/impl_1/*_primary.mcs --secondary-bitstream *.runs/impl_1/*_secondary.mcs
|
||||
|
||||
On these boards, each SPI flash can be programmed independently with the ``--target-flash`` option.
|
||||
The default target is the ``primary`` flash.
|
||||
|
||||
For example, to program only the secondary flash with arbitrary data not related to FPGA configuration:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
openFPGALoader --board vcu118 -f --target-flash secondary --bitstream arbitrary_data
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ build() {
|
|||
-G "MSYS Makefiles" \
|
||||
-DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \
|
||||
../../../..
|
||||
cmake --build .
|
||||
MSYS2_ARG_CONV_EXCL="-DDATA_DIR=" cmake --build .
|
||||
}
|
||||
|
||||
check() {
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
tmp_*
|
||||
*.bit
|
||||
*.rbf
|
||||
|
|
|
|||
|
|
@ -36,60 +36,115 @@ elif subpart == "xc7a":
|
|||
family = "Artix"
|
||||
tool = "vivado"
|
||||
elif subpart == "xc7k":
|
||||
family = "Kintex 7"
|
||||
tool = "vivado"
|
||||
device_size = int(part.split('k')[1].split('t')[0])
|
||||
if device_size <= 160:
|
||||
family = "Kintex 7"
|
||||
tool = "vivado"
|
||||
else:
|
||||
family = "Kintex7"
|
||||
tool = "ise"
|
||||
speed = -2
|
||||
elif subpart == "xc7s":
|
||||
family = "Spartan 7"
|
||||
tool = "vivado"
|
||||
elif subpart == "xc6s":
|
||||
family = "Spartan6"
|
||||
tool = "ise"
|
||||
speed = -3
|
||||
elif subpart == "xc3s":
|
||||
family = "Spartan3E"
|
||||
tool = "ise"
|
||||
speed = -4
|
||||
elif subpart in ["xcvu", "xcku"]:
|
||||
family = "Xilinx UltraScale"
|
||||
tool = "vivado"
|
||||
else:
|
||||
print("Error: unknown device")
|
||||
os.sys.exit()
|
||||
|
||||
if tool in ["ise", "vivado"]:
|
||||
pkg_name = {
|
||||
"xc3s500evq100" : "xc3s_vq100",
|
||||
"xc6slx9tqg144" : "xc6s_tqg144",
|
||||
"xc6slx9csg324" : "xc6s_csg324",
|
||||
"xc6slx16ftg256" : "xc6s_ftg256",
|
||||
"xc6slx16csg324" : "xc6s_csg324",
|
||||
"xc6slx45csg324" : "xc6s_csg324",
|
||||
"xc6slx100fgg484" : "xc6s_fgg484",
|
||||
"xc6slx150tcsg484" : "xc6s_csg484",
|
||||
"xc6slx150tfgg484" : "xc6s_fgg484",
|
||||
"xc7a25tcpg238" : "xc7a_cpg238",
|
||||
"xc7a25tcsg325" : "xc7a_csg325",
|
||||
"xc7a35tcpg236" : "xc7a_cpg236",
|
||||
"xc7a35tcsg324" : "xc7a_csg324",
|
||||
"xc7a35tftg256" : "xc7a_ftg256",
|
||||
"xc7a50tcpg236" : "xc7a_cpg236",
|
||||
"xc7a50tfgg484" : "xc7a_fgg484",
|
||||
"xc7a50tcsg324" : "xc7a_csg324",
|
||||
"xc7a50tfgg484" : "xc7a_fgg484",
|
||||
"xc7a75tfgg484" : "xc7a_fgg484",
|
||||
"xc7a100tcsg324" : "xc7a_csg324",
|
||||
"xc7a100tfgg484" : "xc7a_fgg484",
|
||||
"xc7a100tfgg676" : "xc7a_fgg676",
|
||||
"xc7a200tsbg484" : "xc7a_sbg484",
|
||||
"xc7a200tfbg484" : "xc7a_fbg484",
|
||||
"xc7k160tffg676" : "xc7k_ffg676",
|
||||
"xc7k325tffg676" : "xc7k_ffg676",
|
||||
"xc7k325tffg900" : "xc7k_ffg900",
|
||||
"xc7k420tffg901" : "xc7k_ffg901",
|
||||
"xc7s25csga225" : "xc7s_csga225",
|
||||
"xc7s25csga324" : "xc7s_csga324",
|
||||
"xc7s50csga324" : "xc7s_csga324"
|
||||
"xc7s50csga324" : "xc7s_csga324",
|
||||
"xcvu9p-flga2104" : "xcvu9p_flga2104",
|
||||
"xcvu37p-fsvh2892" : "xcvu37p_fsvh2892",
|
||||
"xcku5p-ffvb676" : "xcku5p_ffvb676",
|
||||
}[part]
|
||||
if tool == "ise":
|
||||
cst_type = "UCF"
|
||||
tool_options = {'family': family,
|
||||
'device': {
|
||||
"xc6slx16ftg256": "xc6slx16",
|
||||
"xc6slx16csg324": "xc6slx16",
|
||||
"xc6slx45csg324": "xc6slx45",
|
||||
"xc6slx100fgg484": "xc6slx100",
|
||||
"xc6slx150tfgg484": "xc6slx150t"}[part],
|
||||
"xc3s500evq100": "xc3s500e",
|
||||
"xc6slx9tqg144": "xc6slx9",
|
||||
"xc6slx9csg324": "xc6slx9",
|
||||
"xc6slx16ftg256": "xc6slx16",
|
||||
"xc6slx16csg324": "xc6slx16",
|
||||
"xc6slx45csg324": "xc6slx45",
|
||||
"xc6slx100fgg484": "xc6slx100",
|
||||
"xc6slx150tcsg484": "xc6slx150t",
|
||||
"xc6slx150tfgg484": "xc6slx150t",
|
||||
"xc7k325tffg676": "xc7k325t",
|
||||
"xc7k325tffg900": "xc7k325t",
|
||||
"xc7k420tffg901": "xc7k420t",
|
||||
}[part],
|
||||
'package': {
|
||||
"xc6slx16ftg256": "ftg256",
|
||||
"xc6slx16csg324": "csg324",
|
||||
"xc6slx45csg324": "csg324",
|
||||
"xc6slx100fgg484": "fgg384",
|
||||
"xc6slx150tfgg484": "fgg484"}[part],
|
||||
'speed' : -3
|
||||
"xc3s500evq100": "vq100",
|
||||
"xc6slx9tqg144": "tqg144",
|
||||
"xc6slx9csg324": "csg324",
|
||||
"xc6slx16ftg256": "ftg256",
|
||||
"xc6slx16csg324": "csg324",
|
||||
"xc6slx45csg324": "csg324",
|
||||
"xc6slx100fgg484": "fgg384",
|
||||
"xc6slx150tcsg484": "csg484",
|
||||
"xc6slx150tfgg484": "fgg484",
|
||||
"xc7k325tffg676": "ffg676",
|
||||
"xc7k325tffg900": "ffg900",
|
||||
"xc7k420tffg901": "ffg901",
|
||||
}[part],
|
||||
'speed' : speed
|
||||
}
|
||||
else:
|
||||
cst_type = "xdc"
|
||||
tool_options = {'part': part+ '-1'}
|
||||
if family == "Xilinx UltraScale":
|
||||
if part in ["xcvu9p-flga2104", "xcku5p-ffvb676"]:
|
||||
tool_options = {'part': part + '-1-e'}
|
||||
parameters["secondaryflash"]= {
|
||||
'datatype': 'int',
|
||||
'paramtype': 'vlogdefine',
|
||||
'description': 'secondary flash',
|
||||
'default': 1}
|
||||
elif part == "xcvu37p-fsvh2892":
|
||||
tool_options = {'part': part + '-2L-e'}
|
||||
else:
|
||||
tool_options = {'part': part + '-1'}
|
||||
cst_file = currDir + "constr_" + pkg_name + "." + cst_type.lower()
|
||||
files.append({'name': currDir + 'xilinx_spiOverJtag.v',
|
||||
'file_type': 'verilogSource'})
|
||||
|
|
@ -97,10 +152,14 @@ if tool in ["ise", "vivado"]:
|
|||
else:
|
||||
full_part = {
|
||||
"10cl025256": "10CL025YU256C8G",
|
||||
"10cl055484": "10CL055YU484C8G",
|
||||
"ep4ce11523": "EP4CE115F23C7",
|
||||
"ep4ce2217" : "EP4CE22F17C6",
|
||||
"ep4ce1523" : "EP4CE15F23C8",
|
||||
"5ce223" : "5CEFA2F23I7",
|
||||
"5ce523" : "5CEFA5F23I7",
|
||||
"5ce423" : "5CEBA4F23C8",
|
||||
"5ce927" : "5CEBA9F27C7",
|
||||
"5cse423" : "5CSEMA4U23C6",
|
||||
"5cse623" : "5CSEBA6U23I7"}[part]
|
||||
files.append({'name': currDir + 'altera_spiOverJtag.v',
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT ON
|
||||
set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "ACTIVE SERIAL X4"
|
||||
set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION ON
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
NET "sdi_dq0" LOC = P27 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdo_dq1" LOC = P44 | IOSTANDARD = LVCMOS33;
|
||||
NET "csn" LOC = P24 | IOSTANDARD = LVCMOS33;
|
||||
NET "sck" LOC = P50 | IOSTANDARD = LVCMOS33;
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
CONFIG VCCAUX = "2.5";
|
||||
|
||||
NET "sdi_dq0" LOC = AB17 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdo_dq1" LOC = Y17 | IOSTANDARD = LVCMOS33;
|
||||
NET "wpn_dq2" LOC = V13 | IOSTANDARD = LVCMOS33;
|
||||
NET "hldn_dq3" LOC = W13 | IOSTANDARD = LVCMOS33;
|
||||
NET "csn" LOC = AB5 | IOSTANDARD = LVCMOS33;
|
||||
NET "sck" LOC = W17 | IOSTANDARD = LVCMOS33;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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 G19 IOSTANDARD LVCMOS33} [get_ports {csn}];
|
||||
set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {sdi_dq0}];
|
||||
set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {sdo_dq1}];
|
||||
set_property -dict {PACKAGE_PIN E19 IOSTANDARD LVCMOS33} [get_ports {wpn_dq2}];
|
||||
set_property -dict {PACKAGE_PIN F19 IOSTANDARD LVCMOS33} [get_ports {hldn_dq3}];
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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 L15 IOSTANDARD LVCMOS33} [get_ports {csn}];
|
||||
set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports {sdi_dq0}];
|
||||
set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS33} [get_ports {sdo_dq1}];
|
||||
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {wpn_dq2}];
|
||||
set_property -dict {PACKAGE_PIN J16 IOSTANDARD LVCMOS33} [get_ports {hldn_dq3}];
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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 T19 IOSTANDARD LVTTL} [get_ports {csn}]
|
||||
set_property -dict {PACKAGE_PIN P22 IOSTANDARD LVTTL} [get_ports {sdi_dq0}]
|
||||
set_property -dict {PACKAGE_PIN R22 IOSTANDARD LVTTL} [get_ports {sdo_dq1}]
|
||||
set_property -dict {PACKAGE_PIN P21 IOSTANDARD LVTTL} [get_ports {wpn_dq2}]
|
||||
set_property -dict {PACKAGE_PIN R21 IOSTANDARD LVTTL} [get_ports {hldn_dq3}]
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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 T19 IOSTANDARD LVTTL} [get_ports {csn}]
|
||||
set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVTTL} [get_ports {sdi_dq0}]
|
||||
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVTTL} [get_ports {sdo_dq1}]
|
||||
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVTTL} [get_ports {wpn_dq2}]
|
||||
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVTTL} [get_ports {hldn_dq3}]
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
NET "csn" LOC = C23 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdi_dq0" LOC = B24 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdo_dq1" LOC = A25 | IOSTANDARD = LVCMOS33;
|
||||
NET "wpn_dq2" LOC = B22 | IOSTANDARD = LVCMOS33;
|
||||
NET "hldn_dq3" LOC = A22 | IOSTANDARD = LVCMOS33;
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
NET "csn" LOC = U19 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdi_dq0" LOC = P24 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdo_dq1" LOC = R25 | IOSTANDARD = LVCMOS33;
|
||||
NET "wpn_dq2" LOC = R20 | IOSTANDARD = LVCMOS33;
|
||||
NET "hldn_dq3" LOC = R21 | IOSTANDARD = LVCMOS33;
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
NET "csn" LOC = V26 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdi_dq0" LOC = R30 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdo_dq1" LOC = T30 | IOSTANDARD = LVCMOS33;
|
||||
NET "wpn_dq2" LOC = R28 | IOSTANDARD = LVCMOS33;
|
||||
NET "hldn_dq3" LOC = T28 | IOSTANDARD = LVCMOS33;
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
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 L11 IOSTANDARD LVCMOS33} [get_ports {csn}];
|
||||
set_property -dict {PACKAGE_PIN H14 IOSTANDARD LVCMOS33} [get_ports {sdi_dq0}];
|
||||
set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports {sdo_dq1}];
|
||||
set_property -dict {PACKAGE_PIN J12 IOSTANDARD LVCMOS33} [get_ports {wpn_dq2}];
|
||||
set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports {hldn_dq3}];
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
||||
set_property CONFIG_VOLTAGE 1.8 [current_design]
|
||||
# Table 1-2 from UG570
|
||||
set_property CFGBVS GND [current_design]
|
||||
|
||||
# Primary QSPI flash
|
||||
# Connection done through the STARTUPE3 block
|
||||
|
||||
# Secondary QSPI flash
|
||||
set_property PACKAGE_PIN N23 [get_ports "sdi_sec_dq0"] ;# Bank 65 VCCO - VCC1V8 - IO_L22P_T3U_N6_DBC_AD0P_D04_65
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "sdi_sec_dq0"] ;# Bank 65 VCCO - VCC1V8 - IO_L22P_T3U_N6_DBC_AD0P_D04_65
|
||||
set_property PACKAGE_PIN P23 [get_ports "sdo_sec_dq1"] ;# Bank 65 VCCO - VCC1V8 - IO_L22N_T3U_N7_DBC_AD0N_D05_65
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "sdo_sec_dq1"] ;# Bank 65 VCCO - VCC1V8 - IO_L22N_T3U_N7_DBC_AD0N_D05_65
|
||||
set_property PACKAGE_PIN R20 [get_ports "wpn_sec_dq2"] ;# Bank 65 VCCO - VCC1V8 - IO_L21P_T3L_N4_AD8P_D06_65
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "wpn_sec_dq2"] ;# Bank 65 VCCO - VCC1V8 - IO_L21P_T3L_N4_AD8P_D06_65
|
||||
set_property PACKAGE_PIN R21 [get_ports "hldn_sec_dq3"] ;# Bank 65 VCCO - VCC1V8 - IO_L21N_T3L_N5_AD8N_D07_65
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "hldn_sec_dq3"] ;# Bank 65 VCCO - VCC1V8 - IO_L21N_T3L_N5_AD8N_D07_65
|
||||
set_property PACKAGE_PIN U22 [get_ports "csn_sec"] ;# Bank 65 VCCO - VCC1V8 - IO_L2N_T0L_N3_FWE_FCS2_B_65
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "csn_sec"] ;# Bank 65 VCCO - VCC1V8 - IO_L2N_T0L_N3_FWE_FCS2_B_65
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
||||
set_property CONFIG_VOLTAGE 1.8 [current_design]
|
||||
# Table 3-5 from UG1302
|
||||
set_property CFGBVS GND [current_design]
|
||||
|
||||
# Primary QSPI flash
|
||||
# Connection done through the STARTUPE3 block
|
||||
# sdi_dq0 - PACKAGE_PIN AW15 - QSPI0_DQ0 Bank 0 - D00_MOSI_0
|
||||
# sdo_dq1 - PACKAGE_PIN AY15 - QSPI0_DQ1 Bank 0 - D01_DIN_0
|
||||
# wpn_dq2 - PACKAGE_PIN AY14 - QSPI0_DQ2 Bank 0 - D02_0
|
||||
# hldn_dq3 - PACKAGE_PIN AY13 - QSPI0_DQ3 Bank 0 - D03_0
|
||||
# csn - PACKAGE_PIN BC15 - QSPI0_CS_B Bank 0 - RDWR_FCS_B_0
|
||||
# sck - PACKAGE_PIN BD14 - QSPI_CCLK Bank 0 - CCLK_0
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
||||
set_property CONFIG_VOLTAGE 1.8 [current_design]
|
||||
# Table 1-2 from UG570
|
||||
set_property CFGBVS GND [current_design]
|
||||
|
||||
# Primary QSPI flash
|
||||
# Connection done through the STARTUPE3 block
|
||||
# sdi_dq0 - PACKAGE_PIN AP11 - QSPI0_DQ0 Bank 0 - D00_MOSI_0
|
||||
# sdo_dq1 - PACKAGE_PIN AN11 - QSPI0_DQ1 Bank 0 - D01_DIN_0
|
||||
# wpn_dq2 - PACKAGE_PIN AM11 - QSPI0_DQ2 Bank 0 - D02_0
|
||||
# hldn_dq3 - PACKAGE_PIN AL11 - QSPI0_DQ3 Bank 0 - D03_0
|
||||
# csn - PACKAGE_PIN AJ11 - QSPI0_CS_B Bank 0 - RDWR_FCS_B_0
|
||||
# sck - PACKAGE_PIN AF13 - QSPI_CCLK Bank 0 - CCLK_0
|
||||
|
||||
# Secondary QSPI flash
|
||||
set_property PACKAGE_PIN AM19 [get_ports "sdi_sec_dq0"];
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "sdi_sec_dq0"];
|
||||
set_property PACKAGE_PIN AM18 [get_ports "sdo_sec_dq1"];
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "sdo_sec_dq1"];
|
||||
set_property PACKAGE_PIN AN20 [get_ports "wpn_sec_dq2"];
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "wpn_sec_dq2"];
|
||||
set_property PACKAGE_PIN AP20 [get_ports "hldn_sec_dq3"];
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "hldn_sec_dq3"];
|
||||
set_property PACKAGE_PIN BF16 [get_ports "csn_sec"];
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports "csn_sec"];
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
module spiOverJtag (
|
||||
input jtag_1_CAPTURE,
|
||||
input jtag_1_DRCK,
|
||||
input jtag_1_RESET,
|
||||
input jtag_1_RUNTEST,
|
||||
input jtag_1_SEL,
|
||||
input jtag_1_SHIFT,
|
||||
input jtag_1_TCK,
|
||||
input jtag_1_TDI,
|
||||
input jtag_1_TMS,
|
||||
input jtag_1_UPDATE,
|
||||
output jtag_1_TDO,
|
||||
|
||||
output csn,
|
||||
output sck,
|
||||
output sdi_dq0,
|
||||
input sdo_dq1,
|
||||
output wpn_dq2,
|
||||
output hldn_dq3
|
||||
);
|
||||
|
||||
wire capture, drck, sel, update;
|
||||
wire runtest;
|
||||
wire tdi;
|
||||
reg fsm_csn;
|
||||
|
||||
assign wpn_dq2 = 1'b1;
|
||||
assign hldn_dq3 = 1'b1;
|
||||
// jtag -> spi flash
|
||||
assign sdi_dq0 = tdi;
|
||||
wire tdo = (sel) ? sdo_dq1 : tdi;
|
||||
assign csn = fsm_csn;
|
||||
|
||||
wire tmp_cap_s = capture && sel;
|
||||
wire tmp_up_s = update && sel;
|
||||
|
||||
always @(posedge drck, posedge runtest) begin
|
||||
if (runtest) begin
|
||||
fsm_csn <= 1'b1;
|
||||
end else begin
|
||||
if (tmp_cap_s) begin
|
||||
fsm_csn <= 1'b0;
|
||||
end else if (tmp_up_s) begin
|
||||
fsm_csn <= 1'b1;
|
||||
end else begin
|
||||
fsm_csn <= fsm_csn;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign sck = drck;
|
||||
assign capture = jtag_1_CAPTURE;
|
||||
assign drck = jtag_1_DRCK;
|
||||
assign runtest = jtag_1_RUNTEST;
|
||||
assign sel = jtag_1_SEL;
|
||||
assign tdi = jtag_1_TDI;
|
||||
assign update = jtag_1_UPDATE;
|
||||
assign jtag_1_TDO = tdo;
|
||||
endmodule
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
CONFIG VCCAUX = "2.5";
|
||||
|
||||
NET "sdo" LOC = P65 | IOSTANDARD = LVCMOS33;
|
||||
NET "sdi" LOC = P64 | IOSTANDARD = LVCMOS33;
|
||||
NET "csn" LOC = P38 | IOSTANDARD = LVCMOS33;
|
||||
NET "sck" LOC = P70 | IOSTANDARD = LVCMOS33;
|
||||
|
|
@ -7,6 +7,8 @@ file delete -force $build_path
|
|||
|
||||
# Project creation
|
||||
set grade [dict create \
|
||||
xc7a25tcpg238 -1 \
|
||||
xc7a25tcsg325 -1 \
|
||||
xc7a35tcpg236 -1 \
|
||||
xc7a35tcsg324 -1 \
|
||||
xc7a35tftg256 -1 \
|
||||
|
|
@ -16,10 +18,13 @@ set grade [dict create \
|
|||
xc7a200tsbg484 -1 \
|
||||
xc7k325tffg676 -1 \
|
||||
xc7k325tffg900 -2 \
|
||||
xc7s25csga225 -1 \
|
||||
xc7s50csga324 -1 \
|
||||
]
|
||||
|
||||
set pkg_name [dict create \
|
||||
xc7a25tcpg238 xc7a_cpg238 \
|
||||
xc7a25tcsg325 xc7a_csg325 \
|
||||
xc7a35tcpg236 xc7a_cpg236 \
|
||||
xc7a35tcsg324 xc7a_csg324 \
|
||||
xc7a35tftg256 xc7a_ftg256 \
|
||||
|
|
@ -30,6 +35,7 @@ set pkg_name [dict create \
|
|||
xc7a200tfbg484 xc7a_fbg484 \
|
||||
xc7k325tffg676 xc7k_ffg676 \
|
||||
xc7k325tffg900 xc7k_ffg900 \
|
||||
xc7s25csga225 xc7s_csga225 \
|
||||
xc7s50csga324 xc7s_csga324 \
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,27 @@
|
|||
module spiOverJtag
|
||||
(
|
||||
`ifndef virtexultrascale
|
||||
output csn,
|
||||
|
||||
`ifdef spartan6
|
||||
output sck,
|
||||
`endif
|
||||
`ifdef spartan3e
|
||||
output sck,
|
||||
`endif
|
||||
output sdi_dq0,
|
||||
input sdo_dq1,
|
||||
output wpn_dq2,
|
||||
output hldn_dq3
|
||||
`endif // virtexultrascale
|
||||
|
||||
`ifdef secondaryflash
|
||||
output sdi_sec_dq0,
|
||||
input sdo_sec_dq1,
|
||||
output wpn_sec_dq2,
|
||||
output hldn_sec_dq3,
|
||||
output csn_sec
|
||||
`endif // secondaryflash
|
||||
);
|
||||
|
||||
wire capture, drck, sel, update;
|
||||
|
|
@ -41,7 +55,44 @@ module spiOverJtag
|
|||
|
||||
`ifdef spartan6
|
||||
assign sck = drck;
|
||||
`else
|
||||
`else // !spartan6
|
||||
`ifdef spartan3e
|
||||
assign sck = drck;
|
||||
assign runtest = tmp_up_s;
|
||||
`else // !spartan6 && !spartan3e
|
||||
`ifdef virtexultrascale
|
||||
wire [3:0] di;
|
||||
assign sdo_dq1 = di[1];
|
||||
wire [3:0] do = {hldn_dq3, wpn_dq2, 1'b0, sdi_dq0};
|
||||
wire [3:0] dts = 4'b0010;
|
||||
// secondary BSCANE3 signals
|
||||
wire sel_sec, drck_sec;
|
||||
|
||||
wire sck = (sel_sec) ? drck_sec : drck;
|
||||
|
||||
STARTUPE3 #(
|
||||
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
|
||||
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency (ns) for simulation.
|
||||
) startupe3_inst (
|
||||
.CFGCLK (), // 1-bit output: Configuration main clock output.
|
||||
.CFGMCLK (), // 1-bit output: Configuration internal oscillator clock output.
|
||||
.DI (di), // 4-bit output: Allow receiving on the D input pin.
|
||||
.EOS (), // 1-bit output: Active-High output signal indicating the End Of Startup.
|
||||
.PREQ (), // 1-bit output: PROGRAM request to fabric output.
|
||||
.DO (do), // 4-bit input: Allows control of the D pin output.
|
||||
.DTS (dts), // 4-bit input: Allows tristate of the D pin.
|
||||
.FCSBO (csn), // 1-bit input: Controls the FCS_B pin for flash access.
|
||||
.FCSBTS (1'b0), // 1-bit input: Tristate the FCS_B pin.
|
||||
.GSR (1'b0), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port).
|
||||
.GTS (1'b0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name).
|
||||
.KEYCLEARB(1'b0), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM).
|
||||
.PACK (1'b0), // 1-bit input: PROGRAM acknowledge input.
|
||||
.USRCCLKO (sck), // 1-bit input: User CCLK input.
|
||||
.USRCCLKTS(1'b0), // 1-bit input: User CCLK 3-state enable input.
|
||||
.USRDONEO (1'b1), // 1-bit input: User DONE pin output control.
|
||||
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output.
|
||||
);
|
||||
`else // !spartan6 && !spartan3e && !virtexultrascale
|
||||
STARTUPE2 #(
|
||||
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
|
||||
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation.
|
||||
|
|
@ -61,7 +112,28 @@ module spiOverJtag
|
|||
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output
|
||||
);
|
||||
`endif
|
||||
`endif
|
||||
`endif
|
||||
|
||||
`ifdef spartan3e
|
||||
BSCAN_SPARTAN3 bscane2_inst (
|
||||
.CAPTURE(capture), // 1-bit output: CAPTURE output from TAP controller.
|
||||
.DRCK1 (drck), // 1-bit output: Gated TCK output. When SEL
|
||||
// is asserted, DRCK toggles when
|
||||
// CAPTURE or SHIFT are asserted.
|
||||
.DRCK2 (), // 1-bit output: USER2 function
|
||||
.RESET (), // 1-bit output: Reset output for TAP controller.
|
||||
.SEL1 (sel), // 1-bit output: USER1 instruction active output.
|
||||
.SEL2 (), // 1-bit output: USER2 instruction active output.
|
||||
.SHIFT (), // 1-bit output: SHIFT output from TAP controller.
|
||||
.TDI (tdi), // 1-bit output: Test Data Input (TDI) output
|
||||
// from TAP controller.
|
||||
.UPDATE (update), // 1-bit output: UPDATE output from TAP controller
|
||||
.TDO1 (tdo), // 1-bit input: Test Data Output (TDO) input
|
||||
// for USER1 function.
|
||||
.TDO2 () // 1-bit input: USER2 function
|
||||
);
|
||||
`else
|
||||
`ifdef spartan6
|
||||
BSCAN_SPARTAN6 #(
|
||||
`else
|
||||
|
|
@ -88,5 +160,60 @@ module spiOverJtag
|
|||
.TDO (tdo) // 1-bit input: Test Data Output (TDO) input
|
||||
// for USER function.
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef secondaryflash
|
||||
reg fsm_csn_sec;
|
||||
wire tdo_sec;
|
||||
|
||||
assign wpn_sec_dq2 = 1'b1;
|
||||
assign hldn_sec_dq3 = 1'b1;
|
||||
assign sdi_sec_dq0 = tdi;
|
||||
assign tdo_sec = (sel_sec) ? sdo_sec_dq1 : tdi;
|
||||
assign csn_sec = fsm_csn_sec;
|
||||
|
||||
wire tmp_cap_sec_s = capture && sel_sec;
|
||||
wire tmp_up_sec_s = update && sel_sec;
|
||||
|
||||
always @(posedge drck_sec, posedge runtest) begin
|
||||
if (runtest) begin
|
||||
fsm_csn_sec <= 1'b1;
|
||||
end else begin
|
||||
if (tmp_cap_sec_s) begin
|
||||
fsm_csn_sec <= 1'b0;
|
||||
end else if (tmp_up_sec_s) begin
|
||||
fsm_csn_sec <= 1'b1;
|
||||
end else begin
|
||||
fsm_csn_sec <= fsm_csn_sec;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
BSCANE2 #(
|
||||
.JTAG_CHAIN(2) // Value for USER command.
|
||||
) bscane2_sec_inst (
|
||||
.CAPTURE(), // 1-bit output: CAPTURE output from TAP controller.
|
||||
.DRCK (drck_sec), // 1-bit output: Gated TCK output. When SEL
|
||||
// is asserted, DRCK toggles when
|
||||
// CAPTURE or SHIFT are asserted.
|
||||
.RESET (), // 1-bit output: Reset output for TAP controller.
|
||||
.RUNTEST(), // 1-bit output: Output asserted when TAP
|
||||
// controller is in Run Test/Idle state.
|
||||
.SEL (sel_sec), // 1-bit output: USER instruction active output.
|
||||
.SHIFT (), // 1-bit output: SHIFT output from TAP controller.
|
||||
.TCK (), // 1-bit output: Test Clock output.
|
||||
// Fabric connection to TAP Clock pin.
|
||||
.TDI (), // 1-bit output: Test Data Input (TDI) output
|
||||
// from TAP controller.
|
||||
.TMS (), // 1-bit output: Test Mode Select output.
|
||||
// Fabric connection to TAP.
|
||||
.UPDATE (), // 1-bit output: UPDATE output from TAP controller
|
||||
.TDO (tdo_sec) // 1-bit input: Test Data Output (TDO) input
|
||||
// for USER function.
|
||||
);
|
||||
`else // secondaryflash
|
||||
assign sel_sec = 1'b0;
|
||||
assign drck_sec = 1'b0;
|
||||
`endif // secondaryflash
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -9,26 +9,31 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "jtag.hpp"
|
||||
#include "device.hpp"
|
||||
#include "epcq.hpp"
|
||||
#include "progressBar.hpp"
|
||||
#include "rawParser.hpp"
|
||||
#if defined (_WIN64) || defined (_WIN32)
|
||||
#include "pathHelper.hpp"
|
||||
#endif
|
||||
|
||||
#define IDCODE 6
|
||||
#define USER0 0x0C
|
||||
#define USER1 0x0E
|
||||
#define BYPASS 0x3FF
|
||||
#define IRLENGTH 10
|
||||
// DATA_DIR is defined at compile time.
|
||||
#define BIT_FOR_FLASH (DATA_DIR "/openFPGALoader/test_sfl.svf")
|
||||
|
||||
Altera::Altera(Jtag *jtag, const std::string &filename,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
const std::string &device_package, bool verify, int8_t verbose):
|
||||
const std::string &device_package,
|
||||
const std::string &spiOverJtagPath, bool verify, int8_t verbose,
|
||||
bool skip_load_bridge, bool skip_reset):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 256, verify),
|
||||
_svf(_jtag, _verbose), _device_package(device_package),
|
||||
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
|
||||
skip_reset),
|
||||
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
||||
_vir_addr(0x1000), _vir_length(14)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
|
|
@ -148,19 +153,46 @@ void Altera::programMem(RawParser &_bit)
|
|||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
}
|
||||
|
||||
bool Altera::post_flash_access()
|
||||
{
|
||||
if (_skip_reset)
|
||||
printInfo("Skip resetting device");
|
||||
else
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Altera::prepare_flash_access()
|
||||
{
|
||||
if (_skip_load_bridge) {
|
||||
printInfo("Skip loading bridge for spiOverjtag");
|
||||
return true;
|
||||
}
|
||||
return load_bridge();
|
||||
}
|
||||
|
||||
bool Altera::load_bridge()
|
||||
{
|
||||
if (_device_package.empty()) {
|
||||
printError("Can't program SPI flash: missing device-package information");
|
||||
return false;
|
||||
std::string bitname;
|
||||
if (!_spiOverJtagPath.empty()) {
|
||||
bitname = _spiOverJtagPath;
|
||||
} else {
|
||||
if (_device_package.empty()) {
|
||||
printError("Can't program SPI flash: missing device-package information");
|
||||
return false;
|
||||
}
|
||||
|
||||
bitname = get_shell_env_var("OPENFPGALOADER_SOJ_DIR", DATA_DIR "/openFPGALoader");
|
||||
#ifdef HAS_ZLIB
|
||||
bitname += "/spiOverJtag_" + _device_package + ".rbf.gz";
|
||||
#else
|
||||
bitname += "/spiOverJtag_" + _device_package + ".rbf";
|
||||
#endif
|
||||
}
|
||||
|
||||
// DATA_DIR is defined at compile time.
|
||||
std::string bitname = DATA_DIR "/openFPGALoader/spiOverJtag_";
|
||||
#ifdef HAS_ZLIB
|
||||
bitname += _device_package + ".rbf.gz";
|
||||
#else
|
||||
bitname += _device_package + ".rbf";
|
||||
#if defined (_WIN64) || defined (_WIN32)
|
||||
/* Convert relative path embedded at compile time to an absolute path */
|
||||
bitname = PathHelper::absolutePath(bitname);
|
||||
#endif
|
||||
|
||||
std::cout << "use: " << bitname << std::endl;
|
||||
|
|
@ -190,13 +222,9 @@ void Altera::program(unsigned int offset, bool unprotect_flash)
|
|||
*/
|
||||
/* mem mode -> svf */
|
||||
if (_mode == Device::MEM_MODE) {
|
||||
if (_file_extension == "svf") {
|
||||
_svf.parse(_filename);
|
||||
} else {
|
||||
RawParser _bit(_filename, false);
|
||||
_bit.parse();
|
||||
programMem(_bit);
|
||||
}
|
||||
RawParser _bit(_filename, false);
|
||||
_bit.parse();
|
||||
programMem(_bit);
|
||||
} else if (_mode == Device::SPI_MODE) {
|
||||
// reverse only bitstream raw binaries data no
|
||||
bool reverseOrder = false;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ class Altera: public Device, SPIInterface {
|
|||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type,
|
||||
const std::string &device_package,
|
||||
bool verify, int8_t verbose);
|
||||
const std::string &spiOverJtagPath,
|
||||
bool verify, int8_t verbose,
|
||||
bool skip_load_bridge, bool skip_reset);
|
||||
~Altera();
|
||||
|
||||
void programMem(RawParser &_bit);
|
||||
|
|
@ -56,6 +58,12 @@ class Altera: public Device, SPIInterface {
|
|||
bool unprotect_flash() override {
|
||||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
/*!
|
||||
* \brief bulk erase SPI flash
|
||||
*/
|
||||
bool bulk_erase_flash() override {
|
||||
return SPIInterface::bulk_erase_flash();
|
||||
}
|
||||
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) override;
|
||||
|
|
@ -64,8 +72,8 @@ class Altera: public Device, SPIInterface {
|
|||
uint32_t timeout, bool verbose = false) override;
|
||||
|
||||
protected:
|
||||
bool prepare_flash_access() override {return load_bridge();}
|
||||
bool post_flash_access() override {reset(); return true;}
|
||||
bool prepare_flash_access() override;
|
||||
bool post_flash_access() override;
|
||||
|
||||
private:
|
||||
/*!
|
||||
|
|
@ -92,8 +100,8 @@ class Altera: public Device, SPIInterface {
|
|||
void shiftVDR(uint8_t * tx, uint8_t * rx, uint32_t len,
|
||||
int end_state = Jtag::UPDATE_DR, bool debug = false);
|
||||
|
||||
SVF_jtag _svf;
|
||||
std::string _device_package;
|
||||
std::string _spiOverJtagPath; /**< spiOverJtag explicit path */
|
||||
uint32_t _vir_addr; /**< addr affected to virtual jtag */
|
||||
uint32_t _vir_length; /**< length of virtual jtag IR */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
|
|||
const std::string &file_type,
|
||||
Device::prog_type_t prg_type, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 0, verify), _svf(_jtag, _verbose)
|
||||
SPIInterface(filename, verbose, 0, verify)
|
||||
{
|
||||
if (prg_type == Device::RD_FLASH) {
|
||||
_mode = Device::READ_MODE;
|
||||
|
|
@ -64,11 +64,6 @@ void Anlogic::program(unsigned int offset, bool unprotect_flash)
|
|||
if (_mode == Device::NONE_MODE)
|
||||
return;
|
||||
|
||||
if (_file_extension == "svf") {
|
||||
_svf.parse(_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
AnlogicBitParser bit(_filename, (_mode == Device::MEM_MODE), _verbose);
|
||||
|
||||
printInfo("Parse file ", false);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@ class Anlogic: public Device, SPIInterface {
|
|||
return SPIInterface::unprotect_flash();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief bulk erase SPI flash
|
||||
*/
|
||||
bool bulk_erase_flash() override {
|
||||
return SPIInterface::bulk_erase_flash();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief dump len byte from base_addr from SPI flash
|
||||
* \param[in] base_addr: start offset
|
||||
|
|
@ -66,8 +73,6 @@ class Anlogic: public Device, SPIInterface {
|
|||
*/
|
||||
virtual bool post_flash_access() override {reset(); return true;}
|
||||
|
||||
private:
|
||||
SVF_jtag _svf;
|
||||
};
|
||||
|
||||
#endif // SRC_ANLOGIC_HPP_
|
||||
|
|
|
|||
|
|
@ -107,11 +107,11 @@ int AnlogicBitParser::parse()
|
|||
|
||||
_bit_data.clear();
|
||||
for (auto it = blocks.begin(); it != blocks.end(); it++) {
|
||||
for (size_t pos = 0; pos < it->size(); pos++) {
|
||||
for (size_t xpos = 0; xpos < it->size(); xpos++) {
|
||||
if (_reverseOrder == true)
|
||||
_bit_data += reverseByte(((*it)[pos]));
|
||||
_bit_data += reverseByte(((*it)[xpos]));
|
||||
else
|
||||
_bit_data += ((*it)[pos]);
|
||||
_bit_data += ((*it)[xpos]);
|
||||
}
|
||||
}
|
||||
_bit_length = _bit_data.size() * 8;
|
||||
|
|
|
|||
|
|
@ -44,9 +44,8 @@ enum analogicCableFreq {
|
|||
ANLOGICCABLE_FREQ_90K = 0xff
|
||||
};
|
||||
|
||||
AnlogicCable::AnlogicCable(uint32_t clkHZ, uint8_t verbose):
|
||||
_verbose(verbose),
|
||||
dev_handle(NULL), usb_ctx(NULL), _tdi(0), _tms(0)
|
||||
AnlogicCable::AnlogicCable(uint32_t clkHZ):
|
||||
dev_handle(NULL), usb_ctx(NULL)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
class AnlogicCable : public JtagInterface {
|
||||
public:
|
||||
AnlogicCable(uint32_t clkHZ, uint8_t verbose);
|
||||
AnlogicCable(uint32_t clkHZ);
|
||||
virtual ~AnlogicCable();
|
||||
|
||||
int setClkFreq(uint32_t clkHZ) override;
|
||||
|
|
@ -43,13 +43,9 @@ class AnlogicCable : public JtagInterface {
|
|||
int flush() override;
|
||||
|
||||
private:
|
||||
uint8_t _verbose;
|
||||
|
||||
int write(uint8_t *in_buf, uint8_t *out_buf, int len, int rd_len);
|
||||
|
||||
libusb_device_handle *dev_handle;
|
||||
libusb_context *usb_ctx;
|
||||
uint8_t _tdi;
|
||||
uint8_t _tms;
|
||||
};
|
||||
#endif // SRC_ANLOGICCABLE_HPP_
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ int BitParser::parseHeader()
|
|||
int pos_data = 0;
|
||||
int ret = 1;
|
||||
short length;
|
||||
string tmp(64, ' ');
|
||||
string tmp;
|
||||
int pos, prev_pos;
|
||||
|
||||
/* Field 1 : misc header */
|
||||
|
|
@ -109,10 +109,21 @@ int BitParser::parse()
|
|||
/* process all field */
|
||||
int pos = parseHeader();
|
||||
|
||||
/* rest of the file is data to send */
|
||||
_bit_data.resize(_raw_data.size() - pos);
|
||||
std::move(_raw_data.begin() + pos, _raw_data.end(), _bit_data.begin());
|
||||
_bit_length = _bit_data.size();
|
||||
/* _bit_length is length of data to send */
|
||||
int rest_of_file_length = _file_size - pos;
|
||||
if (_bit_length < rest_of_file_length) {
|
||||
printWarn("File is longer than bitstream length declared in the header: " +
|
||||
std::to_string(rest_of_file_length) + " vs " + std::to_string(_bit_length)
|
||||
);
|
||||
} else if (_bit_length > rest_of_file_length) {
|
||||
printError("File is shorter than bitstream length declared in the header: " +
|
||||
std::to_string(rest_of_file_length) + " vs " + std::to_string(_bit_length)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
_bit_data.resize(_bit_length);
|
||||
std::move(_raw_data.begin() + pos, _raw_data.begin() + pos + _bit_length, _bit_data.begin());
|
||||
|
||||
if (_reverseOrder) {
|
||||
for (int i = 0; i < _bit_length; i++) {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ static std::map <std::string, target_board_t> board_list = {
|
|||
JTAG_BOARD("colorlight", "", "", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("colorlight-i5", "", "cmsisdap", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("colorlight-i9", "", "cmsisdap", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "ft2232",0,0,CABLE_DEFAULT),
|
||||
JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||
JTAG_BOARD("c10lp-refkit", "10cl055484", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||
|
|
|
|||
141
src/cable.hpp
141
src/cable.hpp
|
|
@ -3,13 +3,12 @@
|
|||
* Copyright (C) 2019 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*/
|
||||
|
||||
#ifndef CABLE_HPP
|
||||
#define CABLE_HPP
|
||||
#ifndef SRC_CABLE_HPP_
|
||||
#define SRC_CABLE_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "ftdipp_mpsse.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
/*!
|
||||
* \brief define type of communication
|
||||
|
|
@ -19,51 +18,115 @@ enum communication_type {
|
|||
MODE_CH552_JTAG, /*! ch552_jtag firmware */
|
||||
MODE_FTDI_BITBANG, /*! used with ft232RL/ft231x */
|
||||
MODE_FTDI_SERIAL, /*! ft2232, ft232H */
|
||||
MODE_JLINK, /*! ft2232, ft232H */
|
||||
MODE_DIRTYJTAG, /*! JTAG probe firmware for STM32F1 */
|
||||
MODE_USBBLASTER, /*! JTAG probe firmware for USBBLASTER */
|
||||
MODE_CMSISDAP, /*! CMSIS-DAP JTAG probe */
|
||||
MODE_DFU, /*! DFU based probe */
|
||||
MODE_XVC_CLIENT, /*! Xilinx Virtual Cable client */
|
||||
MODE_LIBGPIOD_BITBANG, /*! Bitbang gpio pins */
|
||||
MODE_JETSONNANO_BITBANG, /*! Bitbang gpio pins */
|
||||
MODE_REMOTEBITBANG, /*! Remote Bitbang mode */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief FTDI specific configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
int type;
|
||||
FTDIpp_MPSSE::mpsse_bit_config config;
|
||||
} cable_t;
|
||||
int interface; /*! FTDI interface (A, B, C, D) */
|
||||
int bit_low_val; /*! xDBUS 0-7 default value */
|
||||
int bit_low_dir; /*! xDBUS 0-7 default direction (0: in, 1: out) */
|
||||
int bit_high_val; /*! xCBUS 0-7 default value */
|
||||
int bit_high_dir; /*! xCBUS 0-7 default direction (0: in, 1: out) */
|
||||
int index;
|
||||
int status_pin;
|
||||
} mpsse_bit_config;
|
||||
|
||||
/*!
|
||||
* \brief FTDI interface ID
|
||||
*/
|
||||
enum ftdi_if {
|
||||
FTDI_INTF_A = 1,
|
||||
FTDI_INTF_B = 2,
|
||||
FTDI_INTF_C = 3,
|
||||
FTDI_INTF_D = 4
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief cable characteristics
|
||||
*/
|
||||
struct cable_t {
|
||||
communication_type type; /*! see enum communication_type */
|
||||
int vid; /*! Vendor ID */
|
||||
int pid; /*! Product ID */
|
||||
uint8_t bus_addr; /*! bus number (must be set to 0: user defined */
|
||||
uint8_t device_addr; /*! device number (must be set 0: user defined */
|
||||
mpsse_bit_config config; /*! FTDI specific configurations */
|
||||
};
|
||||
|
||||
/* FTDI serial (MPSSE) configuration */
|
||||
#define FTDI_SER(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \
|
||||
{MODE_FTDI_SERIAL, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}}
|
||||
/* FTDI bitbang configuration */
|
||||
#define FTDI_BB(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \
|
||||
{MODE_FTDI_BITBANG, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}}
|
||||
/* CMSIS DAP configuration */
|
||||
#define CMSIS_CL(_vid, _pid) \
|
||||
{MODE_CMSISDAP, _vid, _pid, 0, 0, {}}
|
||||
/* Others cable configuration */
|
||||
#define CABLE_DEF(_type, _vid, _pid) \
|
||||
{_type, _vid, _pid, 0, 0, {}}
|
||||
|
||||
static std::map <std::string, cable_t> cable_list = {
|
||||
// last 4 bytes are ADBUS7-0 value, ADBUS7-0 direction, ACBUS7-0 value, ACBUS7-0 direction
|
||||
// some cables requires explicit values on some of the I/Os
|
||||
{"anlogicCable", {MODE_ANLOGICCABLE, {}}},
|
||||
{"arm-usb-ocd-h", {MODE_FTDI_SERIAL, {0x15ba, 0x002b, INTERFACE_A, 0x08, 0x1B, 0x09, 0x0B}}},
|
||||
{"bus_blaster", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x1B, 0x08, 0x0B}}},
|
||||
{"bus_blaster_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"ch552_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"cmsisdap", {MODE_CMSISDAP, {0x0d28, 0x0204, 0, 0, 0, 0, 0 }}},
|
||||
{"gatemate_pgm", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x10, 0x9B, 0x14, 0x17}}},
|
||||
{"gatemate_evb_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x10, 0x1B, 0x00, 0x01}}},
|
||||
{"gatemate_evb_spi", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x00, 0x1B, 0x00, 0x01}}},
|
||||
{"dfu", {MODE_DFU, {}}},
|
||||
{"digilent", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
||||
{"digilent_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0xe8, 0xeb, 0x00, 0x60}}},
|
||||
{"digilent_hs2", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
||||
{"digilent_hs3", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x88, 0x8B, 0x20, 0x30}}},
|
||||
{"digilent_ad", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x80, 0x80}}},
|
||||
{"dirtyJtag", {MODE_DIRTYJTAG, {}}},
|
||||
{"efinix_spi_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
|
||||
{"efinix_jtag_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_B, 0x08, 0x8B, 0x00, 0x00}}},
|
||||
{"efinix_spi_ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
|
||||
{"ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"ft2232_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x00, 0x00}}},
|
||||
{"ft231X", {MODE_FTDI_BITBANG, {0x0403, 0x6015, INTERFACE_A, 0x00, 0x00, 0x00, 0x00}}},
|
||||
{"ft232", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"ft232RL", {MODE_FTDI_BITBANG, {0x0403, 0x6001, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
||||
{"ecpix5-debug", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xF8, 0xFB, 0xFF, 0xFF}}},
|
||||
{"jtag-smt2-nc", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
||||
{"orbtrace", {MODE_CMSISDAP, {0x1209, 0x3443, 0, 0, 0, 0, 0 }}},
|
||||
{"tigard", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x3B, 0x00, 0x00}}},
|
||||
{"usb-blaster", {MODE_USBBLASTER, {0x09Fb, 0x6001, 0, 0, 0, 0, 0 }}},
|
||||
{"usb-blasterII", {MODE_USBBLASTER, {0x09Fb, 0x6810, 0, 0, 0, 0, 0 }}},
|
||||
{"anlogicCable", CABLE_DEF(MODE_ANLOGICCABLE, 0x0547, 0x1002)},
|
||||
{"arm-usb-ocd-h", FTDI_SER(0x15ba, 0x002b, FTDI_INTF_A, 0x08, 0x1B, 0x09, 0x0B)},
|
||||
{"bus_blaster", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x1B, 0x08, 0x0B)},
|
||||
{"bus_blaster_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"ch552_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"cmsisdap", CMSIS_CL(0x0d28, 0x0204 )},
|
||||
{"gatemate_pgm", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x10, 0x9B, 0x14, 0x17)},
|
||||
{"gatemate_evb_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x10, 0x1B, 0x00, 0x01)},
|
||||
{"gatemate_evb_spi", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x00, 0x1B, 0x00, 0x01)},
|
||||
{"dfu", CABLE_DEF(MODE_DFU, 0, 0 )},
|
||||
{"digilent", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||
{"digilent_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0xe8, 0xeb, 0x00, 0x60)},
|
||||
{"digilent_hs2", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||
{"digilent_hs3", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x88, 0x8B, 0x20, 0x30)},
|
||||
{"digilent_ad", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x80, 0x80)},
|
||||
{"dirtyJtag", CABLE_DEF(MODE_DIRTYJTAG, 0x1209, 0xC0CA )},
|
||||
{"efinix_spi_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
|
||||
{"efinix_jtag_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_B, 0x08, 0x8B, 0x00, 0x00)},
|
||||
{"efinix_spi_ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
|
||||
{"ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"ft2232_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x00, 0x00)},
|
||||
{"ft231X", FTDI_BB (0x0403, 0x6015, FTDI_INTF_A, 0x00, 0x00, 0x00, 0x00)},
|
||||
{"ft232", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"ft232RL", FTDI_BB( 0x0403, 0x6001, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||
{"ecpix5-debug", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xF8, 0xFB, 0xFF, 0xFF)},
|
||||
{"jlink", CABLE_DEF(MODE_JLINK, 0x1366, 0x0105 )},
|
||||
{"jlink_base", CABLE_DEF(MODE_JLINK, 0x1366, 0x0101 )},
|
||||
{"jtrace_pro", CABLE_DEF(MODE_JLINK, 0x1366, 0x1020 )},
|
||||
{"jtag-smt2-nc", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||
{"lpc-link2", CMSIS_CL(0x1fc9, 0x0090 )},
|
||||
{"orbtrace", CMSIS_CL(0x1209, 0x3443 )},
|
||||
{"papilio", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x09, 0x0B)},
|
||||
{"steppenprobe", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x58, 0xFB, 0x00, 0x99)},
|
||||
{"tigard", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x3B, 0x00, 0x00)},
|
||||
{"usb-blaster", CABLE_DEF(MODE_USBBLASTER, 0x09Fb, 0x6001 )},
|
||||
{"usb-blasterII", CABLE_DEF(MODE_USBBLASTER, 0x09Fb, 0x6810 )},
|
||||
{"xvc-client", CABLE_DEF(MODE_XVC_CLIENT, 0x0000, 0x0000 )},
|
||||
#ifdef ENABLE_LIBGPIOD
|
||||
{"libgpiod", CABLE_DEF(MODE_LIBGPIOD_BITBANG, 0, 0x0000 )},
|
||||
#endif
|
||||
#ifdef ENABLE_JETSONNANOGPIO
|
||||
{"jetson-nano-gpio", {MODE_JETSONNANO_BITBANG, {}}},
|
||||
#endif
|
||||
#ifdef ENABLE_REMOTEBITBANG
|
||||
{"remote-bitbang", CABLE_DEF(MODE_REMOTEBITBANG, 0x0000, 0x0000 )},
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // SRC_CABLE_HPP_
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@ using namespace std;
|
|||
#define display(...) do {}while(0)
|
||||
#endif
|
||||
|
||||
CH552_jtag::CH552_jtag(const FTDIpp_MPSSE::mpsse_bit_config &cable,
|
||||
string dev, const string &serial, uint32_t clkHZ, uint8_t verbose):
|
||||
CH552_jtag::CH552_jtag(const cable_t &cable,
|
||||
const string &dev, const string &serial, uint32_t clkHZ,
|
||||
uint8_t verbose):
|
||||
FTDIpp_MPSSE(cable, dev, serial, clkHZ, verbose), _to_read(0)
|
||||
{
|
||||
init_internal(cable);
|
||||
init_internal(cable.config);
|
||||
}
|
||||
|
||||
CH552_jtag::~CH552_jtag()
|
||||
|
|
@ -59,7 +60,7 @@ CH552_jtag::~CH552_jtag()
|
|||
"Loopback failed, expect problems on later runs %d\n", read);
|
||||
}
|
||||
|
||||
void CH552_jtag::init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable)
|
||||
void CH552_jtag::init_internal(const mpsse_bit_config &cable)
|
||||
{
|
||||
display("iProduct : %s\n", _iproduct);
|
||||
|
||||
|
|
@ -181,7 +182,7 @@ int CH552_jtag::writeTDI(uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last)
|
|||
*/
|
||||
int tx_buff_size = mpsse_get_buffer_size();
|
||||
int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len
|
||||
// else supress last bit -> with TMS
|
||||
// else suppress last bit -> with TMS
|
||||
int nb_byte = real_len >> 3; // number of byte to send
|
||||
int nb_bit = (real_len & 0x07); // residual bits
|
||||
int xfer = tx_buff_size - 7; // 2 byte for opcode and size 2 time
|
||||
|
|
@ -286,7 +287,7 @@ int CH552_jtag::writeTDI(uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last)
|
|||
|
||||
unsigned char last_bit = (tdi) ? *tx_ptr : 0;
|
||||
|
||||
/* next: serie of bit to send: inconditionnaly write AND read
|
||||
/* next: serie of bit to send: unconditionally write AND read
|
||||
*/
|
||||
if (nb_bit != 0) {
|
||||
display("%s read/write %d bit\n", __func__, nb_bit);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cable.hpp"
|
||||
#include "jtagInterface.hpp"
|
||||
#include "ftdipp_mpsse.hpp"
|
||||
|
||||
|
|
@ -22,7 +23,7 @@
|
|||
|
||||
class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
|
||||
public:
|
||||
CH552_jtag(const FTDIpp_MPSSE::mpsse_bit_config &cable, std::string dev,
|
||||
CH552_jtag(const cable_t &cable, const std::string &dev,
|
||||
const std::string &serial, uint32_t clkHZ, uint8_t verbose = false);
|
||||
virtual ~CH552_jtag();
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
|
|||
int flush() override;
|
||||
|
||||
private:
|
||||
void init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable);
|
||||
void init_internal(const mpsse_bit_config &cable);
|
||||
uint32_t _to_read; /*!< amount of byte to read */
|
||||
};
|
||||
#endif // SRC_CH552_JTAG_HPP_
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ enum cmsisdap_status {
|
|||
DAP_ERROR = 0xff
|
||||
};
|
||||
|
||||
CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
|
||||
_device_idx(0), _vid(vid), _pid(pid),
|
||||
CmsisDAP::CmsisDAP(const cable_t &cable, int index, uint8_t verbose):_verbose(verbose),
|
||||
_device_idx(0), _vid(cable.vid), _pid(cable.pid),
|
||||
_serial_number(L""), _dev(NULL), _num_tms(0), _is_connect(false)
|
||||
{
|
||||
std::vector<struct hid_device_info *> dev_found;
|
||||
|
|
@ -109,7 +109,7 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
|
|||
* if vid/pid are 0 this function return all;
|
||||
* if vid/pid are >0 only one (or 0) device returned
|
||||
*/
|
||||
devs = hid_enumerate(vid, pid);
|
||||
devs = hid_enumerate(cable.vid, cable.pid);
|
||||
|
||||
for (cur_dev = devs; NULL != cur_dev; cur_dev = cur_dev->next) {
|
||||
dev_found.push_back(cur_dev);
|
||||
|
|
@ -121,18 +121,36 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
|
|||
throw std::runtime_error("No device found");
|
||||
}
|
||||
/* more than one device: can't continue without more information */
|
||||
if (dev_found.size() > 1) {
|
||||
if (dev_found.size() > 1 && index == -1) {
|
||||
hid_exit();
|
||||
throw std::runtime_error(
|
||||
"Error: more than one device. Please provides VID/PID");
|
||||
"Error: more than one device. Please provides VID/PID or cable-index");
|
||||
}
|
||||
|
||||
/* if index check for if interface exist */
|
||||
if (index != -1) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < dev_found.size(); i++) {
|
||||
if (dev_found[i]->interface_number == index) {
|
||||
found = true;
|
||||
_device_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
hid_exit();
|
||||
throw std::runtime_error(
|
||||
"Error: no compatible interface with index " + std::to_string(_device_idx));
|
||||
}
|
||||
}
|
||||
|
||||
printInfo("Found " + std::to_string(dev_found.size()) + " compatible device:");
|
||||
for (size_t i = 0; i < dev_found.size(); i++) {
|
||||
char val[256];
|
||||
snprintf(val, sizeof(val), "\t0x%04x 0x%04x %ls",
|
||||
snprintf(val, sizeof(val), "\t0x%04x 0x%04x 0x%d %ls",
|
||||
dev_found[i]->vendor_id,
|
||||
dev_found[i]->product_id,
|
||||
dev_found[i]->interface_number,
|
||||
dev_found[i]->product_string);
|
||||
printInfo(val);
|
||||
}
|
||||
|
|
@ -144,6 +162,10 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
|
|||
_serial_number = wstring(dev_found[_device_idx]->serial_number);
|
||||
/* open the device */
|
||||
_dev = hid_open_path(dev_found[_device_idx]->path);
|
||||
if (!_dev) {
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't open device. Check permissions for ") + dev_found[_device_idx]->path);
|
||||
}
|
||||
/* cleanup enumeration */
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,18 +12,20 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cable.hpp"
|
||||
#include "jtagInterface.hpp"
|
||||
|
||||
class CmsisDAP: public JtagInterface {
|
||||
public:
|
||||
/*!
|
||||
* \brief contructor: open device with vid/pid if != 0
|
||||
* \brief constructor: open device with vid/pid if != 0
|
||||
* else search for a compatible device
|
||||
* \param[in] vid: vendor id
|
||||
* \param[in] pid: product id
|
||||
* \param[in] index: interface number
|
||||
* \param[in] verbose: verbose level 0 normal, 1 verbose
|
||||
*/
|
||||
CmsisDAP(const int vid, const int pid, uint8_t verbose);
|
||||
CmsisDAP(const cable_t &cable, int index, uint8_t verbose);
|
||||
|
||||
~CmsisDAP();
|
||||
|
||||
|
|
@ -77,13 +79,13 @@ class CmsisDAP: public JtagInterface {
|
|||
private:
|
||||
/*!
|
||||
* \brief connect device in JTAG mode
|
||||
* \return 1 if success <= 0 otherwhise
|
||||
* \return 1 if success <= 0 otherwise
|
||||
*/
|
||||
int dapConnect();
|
||||
|
||||
/*!
|
||||
* \brief disconnect device
|
||||
* \return 1 if success <= 0 otherwhise
|
||||
* \return 1 if success <= 0 otherwise
|
||||
*/
|
||||
int dapDisconnect();
|
||||
int dapResetTarget();
|
||||
|
|
|
|||
|
|
@ -12,14 +12,15 @@
|
|||
|
||||
CologneChip::CologneChip(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
uint16_t rstn_pin, uint16_t done_pin, uint16_t failn_pin, uint16_t oen_pin,
|
||||
uint16_t rstn_pin, uint16_t done_pin, uint16_t fail_pin, uint16_t oen_pin,
|
||||
bool verify, int8_t verbose) :
|
||||
Device(NULL, filename, file_type, verify, verbose), _rstn_pin(rstn_pin),
|
||||
_done_pin(done_pin), _failn_pin(failn_pin), _oen_pin(oen_pin)
|
||||
_done_pin(done_pin), _fail_pin(fail_pin), _oen_pin(oen_pin)
|
||||
{
|
||||
_spi = spi;
|
||||
_spi->gpio_set_input(_done_pin | _failn_pin);
|
||||
_spi->gpio_set_input(_done_pin | _fail_pin);
|
||||
_spi->gpio_set_output(_rstn_pin | _oen_pin);
|
||||
_ftdi_jtag = nullptr;
|
||||
|
||||
if (prg_type == Device::WR_SRAM) {
|
||||
_mode = Device::MEM_MODE;
|
||||
|
|
@ -34,6 +35,7 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
|
|||
bool verify, int8_t verbose) :
|
||||
Device(jtag, filename, file_type, verify, verbose)
|
||||
{
|
||||
_spi = nullptr;
|
||||
/* check which cable/board we're using in order to select pin definitions */
|
||||
std::string spi_board_name;
|
||||
if (board_name != "-") {
|
||||
|
|
@ -47,13 +49,13 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
|
|||
/* pin configurations valid for both evaluation board and programer */
|
||||
_rstn_pin = spi_board->reset_pin;
|
||||
_done_pin = spi_board->done_pin;
|
||||
_failn_pin = DBUS6;
|
||||
_fail_pin = DBUS6;
|
||||
_oen_pin = spi_board->oe_pin;
|
||||
|
||||
/* cast _jtag->_jtag from JtagInterface to FtdiJtagMPSSE to access GPIO */
|
||||
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(_jtag->_jtag);
|
||||
|
||||
_ftdi_jtag->gpio_set_input(_done_pin | _failn_pin);
|
||||
_ftdi_jtag->gpio_set_input(_done_pin | _fail_pin);
|
||||
_ftdi_jtag->gpio_set_output(_rstn_pin | _oen_pin);
|
||||
|
||||
if (prg_type == Device::WR_SRAM) {
|
||||
|
|
@ -72,7 +74,7 @@ void CologneChip::reset()
|
|||
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
||||
usleep(SLEEP_US);
|
||||
_spi->gpio_set(_rstn_pin);
|
||||
} else if (_ftdi_jtag) {
|
||||
} else {
|
||||
_ftdi_jtag->gpio_clear(_rstn_pin | _oen_pin);
|
||||
usleep(SLEEP_US);
|
||||
_ftdi_jtag->gpio_set(_rstn_pin);
|
||||
|
|
@ -80,24 +82,24 @@ void CologneChip::reset()
|
|||
}
|
||||
|
||||
/**
|
||||
* Obtain CFG_DONE and ~CFG_FAILED signals. Configuration is successfull iff
|
||||
* CFG_DONE=true and ~CFG_FAILED=false.
|
||||
* Obtain CFG_DONE and CFG_FAILED signals. Configuration is successful if
|
||||
* CFG_DONE=true and CFG_FAILED=false.
|
||||
*/
|
||||
bool CologneChip::cfgDone()
|
||||
{
|
||||
uint16_t status = 0;
|
||||
if (_spi) {
|
||||
status = _spi->gpio_get(true);
|
||||
} else if (_ftdi_jtag) {
|
||||
} else {
|
||||
status = _ftdi_jtag->gpio_get(true);
|
||||
}
|
||||
bool done = (status & _done_pin) > 0;
|
||||
bool fail = (status & _failn_pin) == 0;
|
||||
bool fail = (status & _fail_pin) > 0;
|
||||
return (done && !fail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints information if configuration was successfull.
|
||||
* Prints information if configuration was successful.
|
||||
*/
|
||||
void CologneChip::waitCfgDone()
|
||||
{
|
||||
|
|
@ -118,13 +120,12 @@ void CologneChip::waitCfgDone()
|
|||
/**
|
||||
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
|
||||
*/
|
||||
bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
|
||||
uint32_t len)
|
||||
bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||
{
|
||||
if (_spi) {
|
||||
/* enable output and hold reset */
|
||||
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
||||
} else if (_ftdi_jtag) {
|
||||
} else {
|
||||
/* enable output and disable reset */
|
||||
_ftdi_jtag->gpio_clear(_oen_pin);
|
||||
_ftdi_jtag->gpio_set(_rstn_pin);
|
||||
|
|
@ -137,12 +138,12 @@ bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
|
|||
if (_spi) {
|
||||
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false,
|
||||
_verbose);
|
||||
} else if (_ftdi_jtag) {
|
||||
} else {
|
||||
flash = new SPIFlash(this, false, _verbose);
|
||||
}
|
||||
flash->reset();
|
||||
flash->power_up();
|
||||
flash->dump(filename, base_addr, len);
|
||||
flash->dump(_filename, base_addr, len);
|
||||
} catch (std::exception &e) {
|
||||
printError("Fail");
|
||||
printError(std::string(e.what()));
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class CologneChip: public Device, SPIInterface {
|
|||
public:
|
||||
CologneChip(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
uint16_t rstn_pin, uint16_t done_pin, uint16_t failn_pin, uint16_t oen_pin,
|
||||
uint16_t rstn_pin, uint16_t done_pin, uint16_t fail_pin, uint16_t oen_pin,
|
||||
bool verify, int8_t verbose);
|
||||
CologneChip(Jtag* jtag, const std::string &filename,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
|
|
@ -34,12 +34,14 @@ class CologneChip: public Device, SPIInterface {
|
|||
|
||||
bool cfgDone();
|
||||
void waitCfgDone();
|
||||
bool dumpFlash(const std::string &filename, uint32_t base_addr, uint32_t len);
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
|
||||
virtual bool protect_flash(uint32_t len) override {
|
||||
(void) len;
|
||||
printError("protect flash not supported"); return false;}
|
||||
virtual bool unprotect_flash() override {
|
||||
printError("unprotect flash not supported"); return false;}
|
||||
virtual bool bulk_erase_flash() override {
|
||||
printError("bulk erase flash not supported"); return false;}
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
|
||||
int idCode() override {return 0;}
|
||||
|
|
@ -64,7 +66,7 @@ class CologneChip: public Device, SPIInterface {
|
|||
FtdiJtagMPSSE *_ftdi_jtag = NULL;
|
||||
uint16_t _rstn_pin;
|
||||
uint16_t _done_pin;
|
||||
uint16_t _failn_pin;
|
||||
uint16_t _fail_pin;
|
||||
uint16_t _oen_pin;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
/*!
|
||||
* \brief return shell environment variable value
|
||||
* \param[in] key: variable name
|
||||
* \return variable value or ""
|
||||
*/
|
||||
const std::string get_shell_env_var(const char* key,
|
||||
const char *def_val) noexcept {
|
||||
const char* ret = std::getenv(key);
|
||||
return std::string(ret ? ret : def_val);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*/
|
||||
|
||||
#ifndef SRC_COMMON_HPP_
|
||||
#define SRC_COMMON_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
/*!
|
||||
* \brief return shell environment variable value
|
||||
* \param[in] key: variable name
|
||||
* \param[in] def_val: value to return when not found
|
||||
* \return variable value or def_val
|
||||
*/
|
||||
const std::string get_shell_env_var(const char* key,
|
||||
const char *def_val="") noexcept;
|
||||
|
||||
#endif // SRC_COMMON_HPP_
|
||||
|
|
@ -35,7 +35,7 @@ ConfigBitstreamParser::ConfigBitstreamParser(const string &filename, int mode,
|
|||
{
|
||||
(void) mode;
|
||||
if (!filename.empty()) {
|
||||
uint32_t offset = filename.find_last_of(".");
|
||||
size_t offset = filename.find_last_of(".");
|
||||
|
||||
FILE *_fd = fopen(filename.c_str(), "rb");
|
||||
if (!_fd) {
|
||||
|
|
|
|||
|
|
@ -731,7 +731,7 @@ namespace cxxopts
|
|||
}
|
||||
|
||||
// The fallback parser. It uses the stringstream parser to parse all types
|
||||
// that have not been overloaded explicitly. It has to be placed in the
|
||||
// that have not been overloaded explicitly. It has to be placed in the
|
||||
// source code before all other more specialized templates.
|
||||
template <typename T>
|
||||
void
|
||||
|
|
|
|||
|
|
@ -48,10 +48,13 @@ class Device {
|
|||
printError("dump flash not supported"); return false;}
|
||||
virtual bool protect_flash(uint32_t len) = 0;
|
||||
virtual bool unprotect_flash() = 0;
|
||||
virtual bool bulk_erase_flash() = 0;
|
||||
|
||||
virtual int idCode() = 0;
|
||||
virtual void reset();
|
||||
|
||||
virtual bool connectJtagToMCU() {return false;}
|
||||
|
||||
protected:
|
||||
Jtag *_jtag;
|
||||
std::string _filename;
|
||||
|
|
|
|||
139
src/dfu.cpp
139
src/dfu.cpp
|
|
@ -46,8 +46,8 @@ enum dfu_cmd {
|
|||
* - index as jtag chain (fix issue when more than one device connected)
|
||||
*/
|
||||
|
||||
DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
||||
int16_t altsetting,
|
||||
DFU::DFU(const string &filename, bool bypass_bitstream,
|
||||
uint16_t vid, uint16_t pid, int16_t altsetting,
|
||||
int verbose_lvl):_verbose(verbose_lvl > 0), _debug(verbose_lvl > 1),
|
||||
_quiet(verbose_lvl < 0), dev_idx(0), _vid(0), _pid(0),
|
||||
_altsetting(altsetting),
|
||||
|
|
@ -55,38 +55,43 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
|||
_bit(NULL)
|
||||
{
|
||||
struct dfu_status status;
|
||||
int dfu_vid = 0, dfu_pid = 0;
|
||||
int dfu_vid = 0, dfu_pid = 0, ret;
|
||||
|
||||
printInfo("Open file ", false);
|
||||
printInfo("Open file : ", false);
|
||||
|
||||
try {
|
||||
_bit = new DFUFileParser(filename, _verbose > 0);
|
||||
printSuccess("DONE");
|
||||
} catch (std::exception &e) {
|
||||
printError("FAIL");
|
||||
throw runtime_error("Error: Fail to open file");
|
||||
}
|
||||
if (bypass_bitstream) {
|
||||
_bit = nullptr;
|
||||
printInfo("bypassed");
|
||||
} else {
|
||||
try {
|
||||
_bit = new DFUFileParser(filename, _verbose > 0);
|
||||
printSuccess("DONE");
|
||||
} catch (std::exception &e) {
|
||||
printError("FAIL");
|
||||
throw runtime_error("Error: Fail to open file");
|
||||
}
|
||||
|
||||
printInfo("Parse file ", false);
|
||||
try {
|
||||
_bit->parse();
|
||||
printSuccess("DONE");
|
||||
} catch (std::exception &e) {
|
||||
printError("FAIL");
|
||||
delete _bit;
|
||||
throw runtime_error("Error: Fail to parse file");
|
||||
}
|
||||
printInfo("Parse file ", false);
|
||||
try {
|
||||
_bit->parse();
|
||||
printSuccess("DONE");
|
||||
} catch (std::exception &e) {
|
||||
printError("FAIL");
|
||||
delete _bit;
|
||||
throw runtime_error("Error: Fail to parse file");
|
||||
}
|
||||
|
||||
if (_verbose > 0)
|
||||
_bit->displayHeader();
|
||||
if (_verbose > 0)
|
||||
_bit->displayHeader();
|
||||
|
||||
/* get VID and PID from dfu file */
|
||||
try {
|
||||
dfu_vid = std::stoi(_bit->getHeaderVal("idVendor"), 0, 16);
|
||||
dfu_pid = std::stoi(_bit->getHeaderVal("idProduct"), 0, 16);
|
||||
} catch (std::exception &e) {
|
||||
if (_verbose)
|
||||
printWarn(e.what());
|
||||
/* get VID and PID from dfu file */
|
||||
try {
|
||||
dfu_vid = std::stoi(_bit->getHeaderVal("idVendor"), 0, 16);
|
||||
dfu_pid = std::stoi(_bit->getHeaderVal("idProduct"), 0, 16);
|
||||
} catch (std::exception &e) {
|
||||
if (_verbose)
|
||||
printWarn(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
if (libusb_init(&usb_ctx) < 0) {
|
||||
|
|
@ -128,12 +133,16 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
|||
displayDFU();
|
||||
|
||||
/* don't try device without vid/pid */
|
||||
if (_vid == 0 || _pid == 0) {
|
||||
if ((_vid == 0 || _pid == 0) && _bit) {
|
||||
libusb_exit(usb_ctx);
|
||||
delete _bit;
|
||||
throw std::runtime_error("Can't open device vid/pid == 0");
|
||||
}
|
||||
|
||||
/* the If bitstream has been bypassed -> it's the end */
|
||||
if (!_bit)
|
||||
return;
|
||||
|
||||
/* open the first */
|
||||
if (open_DFU(0) == EXIT_FAILURE) {
|
||||
libusb_exit(usb_ctx);
|
||||
|
|
@ -143,10 +152,14 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
|||
|
||||
printf("%02x %02x\n", _vid, _pid);
|
||||
|
||||
char state = get_state();
|
||||
if (_verbose > 0) {
|
||||
printInfo("Default DFU status " + dfu_dev_state_val[state]);
|
||||
get_status(&status);
|
||||
if ((ret = get_status(&status)) < 0) {
|
||||
delete _bit;
|
||||
throw std::runtime_error("get device status failed with error code " +
|
||||
std::to_string(ret));
|
||||
}
|
||||
|
||||
printInfo("Default DFU status " + dfu_dev_state_val[status.bState]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +167,8 @@ DFU::~DFU()
|
|||
{
|
||||
close_DFU();
|
||||
libusb_exit(usb_ctx);
|
||||
delete _bit;
|
||||
if (_bit)
|
||||
delete _bit;
|
||||
}
|
||||
|
||||
/* open the device using VID and PID
|
||||
|
|
@ -162,6 +176,7 @@ DFU::~DFU()
|
|||
int DFU::open_DFU(int index)
|
||||
{
|
||||
struct dfu_dev curr_dfu;
|
||||
int ret;
|
||||
|
||||
if (_vid == 0 || _pid == 0) {
|
||||
printError("Error: Can't open device without VID/PID");
|
||||
|
|
@ -178,15 +193,16 @@ int DFU::open_DFU(int index)
|
|||
printError("Error: fail to open device");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (libusb_claim_interface(dev_handle, curr_intf) != 0) {
|
||||
if ((ret = libusb_claim_interface(dev_handle, curr_intf)) != 0) {
|
||||
libusb_close(dev_handle);
|
||||
printError("Error: fail to claim interface");
|
||||
printError("Error: fail to claim interface with error code " + std::to_string(ret));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (libusb_set_interface_alt_setting(dev_handle, curr_intf, 0) != 0) {
|
||||
if ((ret = libusb_set_interface_alt_setting(dev_handle, curr_intf, _altsetting)) != 0) {
|
||||
libusb_release_interface(dev_handle, curr_intf);
|
||||
libusb_close(dev_handle);
|
||||
printError("Error: fail to set interface");
|
||||
printError("Error: fail to set interface " + std::to_string(curr_intf) +
|
||||
" with error code " + std::to_string(ret));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -303,10 +319,11 @@ int DFU::searchDFUDevices()
|
|||
|
||||
int ret = libusb_open(usb_dev, &handle);
|
||||
if (ret == 0) {
|
||||
if (searchIfDFU(handle, usb_dev, &desc) != 0) {
|
||||
ret = searchIfDFU(handle, usb_dev, &desc);
|
||||
libusb_close(handle);
|
||||
if (ret != 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
libusb_close(handle);
|
||||
} else if (_debug) {
|
||||
char mess[256];
|
||||
sprintf(mess,"Unable to open device: "
|
||||
|
|
@ -366,10 +383,17 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle,
|
|||
my_dev.device = libusb_get_device_address(dev);
|
||||
my_dev.bMaxPacketSize0 = desc->bMaxPacketSize0;
|
||||
|
||||
memset(my_dev.iProduct, 0, 128);
|
||||
libusb_get_string_descriptor_ascii(handle, desc->iProduct,
|
||||
my_dev.iProduct, 128);
|
||||
if (strlen((char *)my_dev.iProduct) == 0)
|
||||
snprintf((char *)my_dev.iProduct, 128, "empty");
|
||||
|
||||
memset(my_dev.iInterface, 0, 128);
|
||||
libusb_get_string_descriptor_ascii(handle, intf->iInterface,
|
||||
my_dev.iInterface, 128);
|
||||
if (strlen((char *)my_dev.iInterface) == 0)
|
||||
snprintf((char *)my_dev.iInterface, 128, "empty");
|
||||
|
||||
int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path));
|
||||
my_dev.path[r] = '\0';
|
||||
|
|
@ -433,9 +457,11 @@ int DFU::set_state(char newState)
|
|||
{
|
||||
int ret = 0;
|
||||
struct dfu_status status;
|
||||
char curr_state = get_state();
|
||||
while (curr_state != newState) {
|
||||
switch (curr_state) {
|
||||
if (get_status(&status) < 0)
|
||||
return -1;
|
||||
|
||||
while (status.bState != newState) {
|
||||
switch (status.bState) {
|
||||
case STATE_appIDLE:
|
||||
if (dfu_detach() == EXIT_FAILURE)
|
||||
return -1;
|
||||
|
|
@ -446,7 +472,6 @@ int DFU::set_state(char newState)
|
|||
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
||||
return -1;
|
||||
}
|
||||
curr_state = status.bState;
|
||||
break;
|
||||
case STATE_appDETACH:
|
||||
if (newState == STATE_appIDLE) {
|
||||
|
|
@ -484,15 +509,14 @@ int DFU::set_state(char newState)
|
|||
printError("Fails to send packet\n");
|
||||
return ret;
|
||||
}
|
||||
if ((ret = get_state()) < 0)
|
||||
if (get_status(&status) < 0)
|
||||
return ret;
|
||||
/* not always true:
|
||||
* the newState may be the next one or another */
|
||||
if (ret != newState) {
|
||||
printError(dfu_dev_state_val[ret]);
|
||||
if (status.bState != newState) {
|
||||
printError(dfu_dev_state_val[status.bState]);
|
||||
return -1;
|
||||
}
|
||||
curr_state = ret;
|
||||
break;
|
||||
case STATE_dfuERROR:
|
||||
if (newState == STATE_appIDLE) {
|
||||
|
|
@ -520,7 +544,6 @@ int DFU::set_state(char newState)
|
|||
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
||||
return -1;
|
||||
}
|
||||
curr_state = status.bState;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -550,6 +573,10 @@ int DFU::get_status(struct dfu_status *status)
|
|||
(((uint32_t)buffer[1] & 0xff) << 0);
|
||||
status->bState = buffer[4];
|
||||
status->iString = buffer[5];
|
||||
} else if (res < 0) {
|
||||
printError("Get DFU status failed with error " +
|
||||
std::to_string(res) +
|
||||
"(" + std::string(libusb_error_name(res)) + ")");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -657,6 +684,10 @@ int DFU::download()
|
|||
printError("Error: No device. Can't download file");
|
||||
return -1;
|
||||
}
|
||||
if (!_bit) {
|
||||
printError("Error: No bitstream. Stop");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret, ret_val = EXIT_SUCCESS;
|
||||
uint8_t *buffer, *ptr;
|
||||
|
|
@ -673,7 +704,9 @@ int DFU::download()
|
|||
}
|
||||
|
||||
/* download must start in dfu IDLE state */
|
||||
if (get_state() != STATE_dfuIDLE)
|
||||
if (get_status(&status) < 0)
|
||||
return -1;
|
||||
if (status.bState != STATE_dfuIDLE)
|
||||
set_state(STATE_dfuIDLE);
|
||||
|
||||
xfer_len = libusb_le16_to_cpu(curr_dev.dfu_desc.wTransferSize);
|
||||
|
|
@ -733,12 +766,16 @@ int DFU::download()
|
|||
/* send the zero sized download request
|
||||
* dfuDNLOAD_IDLE -> dfuMANITEST-SYNC
|
||||
*/
|
||||
ret = set_state(STATE_dfuMANIFEST_SYNC);
|
||||
printInfo("send zero sized download request: ", false);
|
||||
//ret = set_state(STATE_dfuMANIFEST_SYNC);
|
||||
ret = send(true, DFU_DNLOAD, transaction, NULL, 0);
|
||||
if (ret < 0) {
|
||||
printError("Error: fail to change state " + to_string(ret));
|
||||
return -6;
|
||||
}
|
||||
|
||||
printSuccess("DONE");
|
||||
|
||||
/* Now FSM must be in dfuMANITEST-SYNC */
|
||||
bool must_continue = true;
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ class DFU {
|
|||
* \param[in] altsetting: device altsetting to use
|
||||
* \param[in] verbose_lvl: verbose level 0 normal, -1 quiet, 1 verbose
|
||||
*/
|
||||
DFU(const std::string &filename, uint16_t vid, uint16_t pid,
|
||||
DFU(const std::string &filename, bool bypass_bitstream,
|
||||
uint16_t vid, uint16_t pid,
|
||||
int16_t altsetting, int verbose_lvl);
|
||||
|
||||
~DFU();
|
||||
|
|
@ -234,7 +235,7 @@ class DFU {
|
|||
int dev_idx; /**< device index in dfu_dev */
|
||||
uint16_t _vid; /**< device Vendor ID */
|
||||
uint16_t _pid; /**< device Product ID */
|
||||
int16_t _altsetting; /**< device altesetting */
|
||||
int16_t _altsetting; /**< device altsetting */
|
||||
struct libusb_context *usb_ctx; /**< usb context */
|
||||
libusb_device_handle * dev_handle; /**< current device handle */
|
||||
int curr_intf; /**< device interface to use */
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ class DFUFileParser: public ConfigBitstreamParser {
|
|||
DFUFileParser(const std::string &filename, bool verbose);
|
||||
/*!
|
||||
* \brief read full content of the file, fill the buffer
|
||||
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwhise
|
||||
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwise
|
||||
*/
|
||||
int parse() override;
|
||||
/*!
|
||||
* \brief read DFU suffix content of the file, fill _hdr structure
|
||||
* \return EXIT_SUCCESS if suffix is fully read, EXIT_FAILURE otherwhise
|
||||
* \return EXIT_SUCCESS if suffix is fully read, EXIT_FAILURE otherwise
|
||||
*/
|
||||
int parseHeader();
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ using namespace std;
|
|||
#define DIRTYJTAG_WRITE_EP 0x01
|
||||
#define DIRTYJTAG_READ_EP 0x82
|
||||
|
||||
#define DIRTYJTAG_TIMEOUT 1000
|
||||
|
||||
enum dirtyJtagCmd {
|
||||
CMD_STOP = 0x00,
|
||||
|
|
@ -44,7 +45,7 @@ enum CommandModifier {
|
|||
|
||||
struct version_specific
|
||||
{
|
||||
uint8_t no_read; // command modifer for xfer no read
|
||||
uint8_t no_read; // command modifier for xfer no read
|
||||
uint16_t max_bits; // max bit count that can be transferred
|
||||
};
|
||||
|
||||
|
|
@ -87,7 +88,8 @@ DirtyJtag::DirtyJtag(uint32_t clkHZ, uint8_t verbose):
|
|||
}
|
||||
|
||||
_version = 0;
|
||||
getVersion();
|
||||
if (!getVersion())
|
||||
throw std::runtime_error("Fail to get version");
|
||||
|
||||
if (setClkFreq(clkHZ) < 0) {
|
||||
cerr << "Fail to set frequency" << endl;
|
||||
|
|
@ -103,7 +105,7 @@ DirtyJtag::~DirtyJtag()
|
|||
libusb_exit(usb_ctx);
|
||||
}
|
||||
|
||||
void DirtyJtag::getVersion()
|
||||
bool DirtyJtag::getVersion()
|
||||
{
|
||||
int actual_length;
|
||||
int ret;
|
||||
|
|
@ -111,17 +113,17 @@ void DirtyJtag::getVersion()
|
|||
CMD_STOP};
|
||||
uint8_t rx_buf[64];
|
||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, 2, &actual_length, 1000);
|
||||
buf, 2, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
cerr << "getVersion: usb bulk write failed " << ret << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
||||
rx_buf, 64, &actual_length, 1000);
|
||||
rx_buf, 64, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
cerr << "getVersion: read: usb bulk read failed " << ret << endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
} while (actual_length == 0);
|
||||
if (!strncmp("DJTAG1\n", (char*)rx_buf, 7)) {
|
||||
|
|
@ -134,6 +136,8 @@ void DirtyJtag::getVersion()
|
|||
cerr << "dirtyJtag version unknown" << endl;
|
||||
_version = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -158,7 +162,7 @@ int DirtyJtag::setClkFreq(uint32_t clkHZ)
|
|||
static_cast<uint8_t>(0xff & ((clkHZ / 1000) )),
|
||||
CMD_STOP};
|
||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, 4, &actual_length, 1000);
|
||||
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
cerr << "setClkFreq: usb bulk write failed " << ret << endl;
|
||||
return -EXIT_FAILURE;
|
||||
|
|
@ -197,7 +201,8 @@ int DirtyJtag::writeTMS(uint8_t *tms, uint32_t len, bool flush_buffer)
|
|||
}
|
||||
buf[buffer_idx++] = CMD_STOP;
|
||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, buffer_idx, &actual_length, 1000);
|
||||
buf, buffer_idx, &actual_length,
|
||||
DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0)
|
||||
{
|
||||
cerr << "writeTMS: usb bulk write failed " << ret << endl;
|
||||
|
|
@ -220,7 +225,7 @@ int DirtyJtag::toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len)
|
|||
buf[2] = (clk_len > 64) ? 64 : (uint8_t)clk_len;
|
||||
|
||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, 4, &actual_length, 1000);
|
||||
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
cerr << "toggleClk: usb bulk write failed " << ret << endl;
|
||||
return -EXIT_FAILURE;
|
||||
|
|
@ -240,16 +245,16 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
{
|
||||
int actual_length;
|
||||
uint32_t real_bit_len = len - (end ? 1 : 0);
|
||||
uint32_t real_byte_len = (len + 7) / 8;
|
||||
uint32_t kRealByteLen = (len + 7) / 8;
|
||||
|
||||
uint8_t tx_cpy[real_byte_len];
|
||||
uint8_t tx_cpy[kRealByteLen];
|
||||
uint8_t tx_buf[512], rx_buf[512];
|
||||
uint8_t *tx_ptr, *rx_ptr = rx;
|
||||
|
||||
if (tx)
|
||||
memcpy(tx_cpy, tx, real_byte_len);
|
||||
memcpy(tx_cpy, tx, kRealByteLen);
|
||||
else
|
||||
memset(tx_cpy, 0, real_byte_len);
|
||||
memset(tx_cpy, 0, kRealByteLen);
|
||||
tx_ptr = tx_cpy;
|
||||
|
||||
tx_buf[0] = CMD_XFER | (rx ? 0 : v_options[_version].no_read);
|
||||
|
|
@ -282,7 +287,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
actual_length = 0;
|
||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
(unsigned char *)tx_buf, (byte_to_send + header_offset),
|
||||
&actual_length, 1000);
|
||||
&actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if ((ret < 0) || (actual_length != (int)(byte_to_send + header_offset))) {
|
||||
cerr << "writeTDI: fill: usb bulk write failed " << ret <<
|
||||
"actual length: " << actual_length << endl;
|
||||
|
|
@ -294,7 +299,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
int transfer_length = (bit_to_send > 255) ? byte_to_send :32;
|
||||
do {
|
||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
||||
rx_buf, transfer_length, &actual_length, 1000);
|
||||
rx_buf, transfer_length, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
cerr << "writeTDI: read: usb bulk read failed " << ret << endl;
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -338,7 +343,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
CMD_STOP,
|
||||
};
|
||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, sizeof(buf), &actual_length, 1000) < 0)
|
||||
buf, sizeof(buf), &actual_length,
|
||||
DIRTYJTAG_TIMEOUT) < 0)
|
||||
{
|
||||
cerr << "writeTDI: last bit error: usb bulk write failed 1" << endl;
|
||||
return -EXIT_FAILURE;
|
||||
|
|
@ -346,7 +352,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
do
|
||||
{
|
||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
||||
&sig, 1, &actual_length, 1000) < 0)
|
||||
&sig, 1, &actual_length,
|
||||
DIRTYJTAG_TIMEOUT) < 0)
|
||||
{
|
||||
cerr << "writeTDI: last bit error: usb bulk read failed" << endl;
|
||||
return -EXIT_FAILURE;
|
||||
|
|
@ -360,7 +367,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
|||
buf[2] &= ~SIG_TCK;
|
||||
buf[3] = CMD_STOP;
|
||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||
buf, 4, &actual_length, 1000) < 0)
|
||||
buf, 4, &actual_length,
|
||||
DIRTYJTAG_TIMEOUT) < 0)
|
||||
{
|
||||
cerr << "writeTDI: last bit error: usb bulk write failed 2" << endl;
|
||||
return -EXIT_FAILURE;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class DirtyJtag : public JtagInterface {
|
|||
uint8_t _verbose;
|
||||
|
||||
int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last);
|
||||
void getVersion();
|
||||
bool getVersion();
|
||||
|
||||
libusb_device_handle *dev_handle;
|
||||
libusb_context *usb_ctx;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
|
||||
void printError(std::string err, bool eol)
|
||||
void printError(const std::string &err, bool eol)
|
||||
{
|
||||
if (isatty(STDERR_FILENO))
|
||||
std::cerr << KRED << err << "\e[0m";
|
||||
|
|
@ -31,7 +31,7 @@ void printError(std::string err, bool eol)
|
|||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
void printWarn(std::string warn, bool eol)
|
||||
void printWarn(const std::string &warn, bool eol)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
std::cout << KYEL << warn << "\e[0m" << std::flush;
|
||||
|
|
@ -42,7 +42,7 @@ void printWarn(std::string warn, bool eol)
|
|||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void printInfo(std::string info, bool eol)
|
||||
void printInfo(const std::string &info, bool eol)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
std::cout << KBLUL << info << "\e[0m" << std::flush;
|
||||
|
|
@ -53,7 +53,7 @@ void printInfo(std::string info, bool eol)
|
|||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void printSuccess(std::string success, bool eol)
|
||||
void printSuccess(const std::string &success, bool eol)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO))
|
||||
std::cout << KGRN << success << "\e[0m" << std::flush;
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
void printError(std::string err, bool eol = true);
|
||||
void printWarn(std::string warn, bool eol = true);
|
||||
void printInfo(std::string info, bool eol = true);
|
||||
void printSuccess(std::string success, bool eol = true);
|
||||
void printError(const std::string &err, bool eol = true);
|
||||
void printWarn(const std::string &warn, bool eol = true);
|
||||
void printInfo(const std::string &info, bool eol = true);
|
||||
void printSuccess(const std::string &success, bool eol = true);
|
||||
|
||||
#endif // DISPLAY_HPP_
|
||||
|
|
|
|||
346
src/efinix.cpp
346
src/efinix.cpp
|
|
@ -9,16 +9,22 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "device.hpp"
|
||||
#include "display.hpp"
|
||||
#include "efinixHexParser.hpp"
|
||||
#include "ftdispi.hpp"
|
||||
#include "device.hpp"
|
||||
#include "ftdiJtagMPSSE.hpp"
|
||||
#include "ftdispi.hpp"
|
||||
#include "jtag.hpp"
|
||||
#include "part.hpp"
|
||||
#include "progressBar.hpp"
|
||||
#include "rawParser.hpp"
|
||||
#if defined (_WIN64) || defined (_WIN32)
|
||||
#include "pathHelper.hpp"
|
||||
#endif
|
||||
#include "spiFlash.hpp"
|
||||
|
||||
Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
|
||||
|
|
@ -27,21 +33,47 @@ Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
|
|||
uint16_t oe_pin,
|
||||
bool verify, int8_t verbose):
|
||||
Device(NULL, filename, file_type, verify, verbose), _ftdi_jtag(NULL),
|
||||
_rst_pin(rst_pin), _done_pin(done_pin), _cs_pin(0), _oe_pin(oe_pin)
|
||||
_rst_pin(rst_pin), _done_pin(done_pin), _cs_pin(0), _oe_pin(oe_pin),
|
||||
_fpga_family(UNKNOWN_FAMILY), _irlen(0), _device_package(""),
|
||||
_spiOverJtagPath("")
|
||||
{
|
||||
_spi = spi;
|
||||
_spi->gpio_set_input(_done_pin);
|
||||
_spi->gpio_set_output(_rst_pin | _oe_pin);
|
||||
init_common(Device::WR_FLASH);
|
||||
}
|
||||
|
||||
Efinix::Efinix(Jtag* jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
const std::string &board_name,
|
||||
bool verify, int8_t verbose):
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
const std::string &board_name, const std::string &device_package,
|
||||
const std::string &spiOverJtagPath, bool verify, int8_t verbose):
|
||||
Device(jtag, filename, file_type, verify, verbose),
|
||||
SPIInterface(filename, verbose, 256, false, false, false),
|
||||
_spi(NULL), _rst_pin(0), _done_pin(0), _cs_pin(0),
|
||||
_oe_pin(0)
|
||||
_oe_pin(0), _fpga_family(UNKNOWN_FAMILY), _irlen(0),
|
||||
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath)
|
||||
{
|
||||
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(jtag->get_ll_class());
|
||||
|
||||
/* detect FPGA type (Trion or Titanium) */
|
||||
|
||||
const uint32_t idcode = _jtag->get_target_device_id();
|
||||
const std::string family = fpga_list[idcode].family;
|
||||
if (family == "Titanium") {
|
||||
if (_file_extension == "hex" && prg_type == Device::WR_SRAM) {
|
||||
throw std::runtime_error("Error: loading (RAM) hex file is not "
|
||||
"allowed for Titanium devices");
|
||||
} else if (_file_extension == "bit" && prg_type == Device::WR_FLASH) {
|
||||
throw std::runtime_error("Error: writing bit (FLASH) file is not "
|
||||
"allowed for Titanium devices");
|
||||
}
|
||||
_fpga_family = TITANIUM_FAMILY;
|
||||
} else if (family == "Trion") {
|
||||
_fpga_family = TRION_FAMILY;
|
||||
} else {
|
||||
throw std::runtime_error("Error: unknown family " + family);
|
||||
}
|
||||
/* get irlen value from model */
|
||||
_irlen = fpga_list[idcode].irlength;
|
||||
|
||||
/* WA: before using JTAG, device must restart with cs low
|
||||
* but cs and rst for xyloni are connected to interfaceA (ie SPI)
|
||||
* TODO: some boards have cs, reset and done in both interface
|
||||
|
|
@ -56,45 +88,76 @@ Efinix::Efinix(Jtag* jtag, const std::string &filename,
|
|||
} else if (board_name == "titanium_ti60_f225_jtag") {
|
||||
spi_board_name = "titanium_ti60_f225";
|
||||
} else {
|
||||
throw std::runtime_error("Error: unknown board name");
|
||||
init_common(prg_type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 2: retrieve spi board */
|
||||
target_board_t *spi_board = &(board_list[spi_board_name]);
|
||||
const target_board_t *spi_board = &(board_list[spi_board_name]);
|
||||
|
||||
/* 3: SPI cable */
|
||||
cable_t *spi_cable = &(cable_list[spi_board->cable_name]);
|
||||
cable_t spi_cable = (cable_list[spi_board->cable_name]);
|
||||
spi_cable.bus_addr = _ftdi_jtag->bus_addr();
|
||||
spi_cable.device_addr = _ftdi_jtag->device_addr();
|
||||
|
||||
/* 4: get pinout (cs, oe, rst) */
|
||||
_cs_pin = spi_board->spi_pins_config.cs_pin;
|
||||
_rst_pin = spi_board->reset_pin;
|
||||
_oe_pin = spi_board->oe_pin;
|
||||
_done_pin = spi_board->done_pin;
|
||||
|
||||
/* 5: open SPI interface */
|
||||
_spi = new FtdiSpi(spi_cable->config, spi_board->spi_pins_config,
|
||||
_spi = new FtdiSpi(spi_cable, spi_board->spi_pins_config,
|
||||
jtag->getClkFreq(), verbose > 0);
|
||||
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(jtag);
|
||||
|
||||
/* 6: configure pins direction and default state */
|
||||
_spi->gpio_set_output(_oe_pin | _rst_pin | _cs_pin);
|
||||
init_common(prg_type);
|
||||
}
|
||||
|
||||
void Efinix::init_common(const Device::prog_type_t &prg_type)
|
||||
{
|
||||
if (_spi) {
|
||||
_spi->gpio_set_input(_done_pin);
|
||||
_spi->gpio_set_output(_rst_pin | _oe_pin);
|
||||
}
|
||||
|
||||
switch (prg_type) {
|
||||
case Device::WR_FLASH:
|
||||
_mode = (_jtag) ? Device::FLASH_MODE : Device::SPI_MODE;
|
||||
break;
|
||||
case Device::WR_SRAM:
|
||||
if (!_jtag) {
|
||||
throw std::runtime_error("Efinix: SRAM load requires jtag");
|
||||
}
|
||||
_mode = MEM_MODE;
|
||||
break;
|
||||
default:
|
||||
_mode = NONE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
Efinix::~Efinix()
|
||||
{}
|
||||
{
|
||||
if (_jtag && _spi)
|
||||
delete _spi;
|
||||
}
|
||||
|
||||
void Efinix::reset()
|
||||
{
|
||||
if (_ftdi_jtag) // not supported
|
||||
if (!_spi) {
|
||||
printError("jtag: reset not supported");
|
||||
return;
|
||||
}
|
||||
uint32_t timeout = 1000;
|
||||
_spi->gpio_clear(_rst_pin | _oe_pin);
|
||||
usleep(1000);
|
||||
_spi->gpio_set(_rst_pin | _oe_pin);
|
||||
|
||||
printInfo("Reset ", false);
|
||||
do {
|
||||
timeout--;
|
||||
usleep(12000);
|
||||
} while (((_spi->gpio_get(true) & _done_pin) == 0) || timeout > 0);
|
||||
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
|
||||
if (timeout == 0)
|
||||
printError("FAIL");
|
||||
else
|
||||
|
|
@ -105,13 +168,15 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
|
|||
{
|
||||
if (_file_extension.empty())
|
||||
return;
|
||||
if (_mode == Device::NONE_MODE)
|
||||
return;
|
||||
|
||||
ConfigBitstreamParser *bit;
|
||||
try {
|
||||
if (_file_extension == "hex") {
|
||||
bit = new EfinixHexParser(_filename, _verbose);
|
||||
if (_file_extension == "hex" || _file_extension == "bit") {
|
||||
bit = new EfinixHexParser(_filename);
|
||||
} else {
|
||||
if (offset == 0) {
|
||||
if (offset == 0 && _spi) {
|
||||
printError("Error: can't write raw data at the beginning of the flash");
|
||||
throw std::exception();
|
||||
}
|
||||
|
|
@ -131,21 +196,37 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
|
|||
return;
|
||||
}
|
||||
|
||||
unsigned char *data = bit->getData();
|
||||
int length = bit->getLength() / 8;
|
||||
const uint8_t *data = bit->getData();
|
||||
const int length = bit->getLength() / 8;
|
||||
|
||||
if (_verbose)
|
||||
bit->displayHeader();
|
||||
|
||||
if (_ftdi_jtag)
|
||||
programJTAG(data, length);
|
||||
else
|
||||
programSPI(offset, data, length, unprotect_flash);
|
||||
switch (_mode) {
|
||||
case MEM_MODE:
|
||||
programJTAG(data, length);
|
||||
break;
|
||||
case FLASH_MODE:
|
||||
if (_jtag)
|
||||
SPIInterface::write(offset, const_cast<uint8_t *>(data),
|
||||
length, unprotect_flash);
|
||||
else
|
||||
programSPI(offset, data, length, unprotect_flash);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
delete bit;
|
||||
}
|
||||
|
||||
bool Efinix::dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len)
|
||||
bool Efinix::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||
{
|
||||
if (!_spi) {
|
||||
printError("jtag: dumpFlash not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t timeout = 1000;
|
||||
_spi->gpio_clear(_rst_pin);
|
||||
|
||||
|
|
@ -155,7 +236,7 @@ bool Efinix::dumpFlash(const std::string &filename,
|
|||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||
flash.reset();
|
||||
flash.power_up();
|
||||
flash.dump(filename, base_addr, len);
|
||||
flash.dump(_filename, base_addr, len);
|
||||
} catch (std::exception &e) {
|
||||
printError("Fail");
|
||||
printError(std::string(e.what()));
|
||||
|
|
@ -179,11 +260,9 @@ bool Efinix::dumpFlash(const std::string &filename,
|
|||
return false;
|
||||
}
|
||||
|
||||
void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash)
|
||||
void Efinix::programSPI(unsigned int offset, const uint8_t *data,
|
||||
const int length, const bool unprotect_flash)
|
||||
{
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
_spi->gpio_clear(_rst_pin | _oe_pin);
|
||||
|
||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
|
||||
|
|
@ -193,24 +272,13 @@ void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
|||
|
||||
printf("%02x\n", flash.read_status_reg());
|
||||
flash.read_id();
|
||||
flash.erase_and_prog(offset, data, length);
|
||||
flash.erase_and_prog(offset, const_cast<uint8_t *>(data), length);
|
||||
|
||||
/* verify write if required */
|
||||
if (_verify)
|
||||
flash.verify(offset, data, length);
|
||||
|
||||
_spi->gpio_set(_rst_pin | _oe_pin);
|
||||
usleep(12000);
|
||||
|
||||
printInfo("Wait for CDONE ", false);
|
||||
do {
|
||||
timeout--;
|
||||
usleep(12000);
|
||||
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
|
||||
if (timeout == 0)
|
||||
printError("FAIL");
|
||||
else
|
||||
printSuccess("DONE");
|
||||
reset();
|
||||
}
|
||||
|
||||
#define SAMPLE_PRELOAD 0x02
|
||||
|
|
@ -219,21 +287,28 @@ void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
|||
#define IDCODE 0x03
|
||||
#define PROGRAM 0x04
|
||||
#define ENTERUSER 0x07
|
||||
#define IRLENGTH 4
|
||||
#define USER1 0x08
|
||||
|
||||
void Efinix::programJTAG(uint8_t *data, int length)
|
||||
void Efinix::programJTAG(const uint8_t *data, const int length)
|
||||
{
|
||||
int xfer_len = 512, tx_end;
|
||||
uint8_t tx[512];
|
||||
|
||||
/* trion has to be reseted with cs low */
|
||||
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
|
||||
usleep(30000);
|
||||
_spi->gpio_set(_rst_pin); // assert RST
|
||||
usleep(50000);
|
||||
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
|
||||
usleep(50000);
|
||||
if (_fpga_family == TITANIUM_FAMILY)
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
|
||||
if(_spi) {
|
||||
/* trion has to be reseted with cs low */
|
||||
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
|
||||
usleep(30000);
|
||||
_spi->gpio_set(_rst_pin); // assert RST
|
||||
usleep(50000);
|
||||
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
if (_fpga_family == TITANIUM_FAMILY)
|
||||
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
|
||||
/* force run_test_idle state */
|
||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||
usleep(100000);
|
||||
|
|
@ -241,8 +316,8 @@ void Efinix::programJTAG(uint8_t *data, int length)
|
|||
/* send PROGRAM state and stay in SHIFT_DR until
|
||||
* full configuration data has been sent
|
||||
*/
|
||||
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR);
|
||||
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR); // T20 fix
|
||||
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR);
|
||||
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR); // T20 fix
|
||||
|
||||
ProgressBar progress("Load SRAM", length, 50, _quiet);
|
||||
|
||||
|
|
@ -264,9 +339,160 @@ void Efinix::programJTAG(uint8_t *data, int length)
|
|||
|
||||
usleep(10000);
|
||||
|
||||
_jtag->shiftIR(ENTERUSER, IRLENGTH, Jtag::EXIT1_IR);
|
||||
_jtag->shiftIR(ENTERUSER, _irlen, Jtag::EXIT1_IR);
|
||||
|
||||
memset(tx, 0, 512);
|
||||
_jtag->shiftDR(tx, NULL, 100);
|
||||
_jtag->shiftIR(IDCODE, IRLENGTH);
|
||||
_jtag->shiftIR(IDCODE, _irlen);
|
||||
uint8_t idc[4];
|
||||
_jtag->shiftDR(NULL, idc, 4);
|
||||
printf("%02x%02x%02x%02x\n",
|
||||
idc[0], idc[1], idc[2], idc[3]);
|
||||
}
|
||||
|
||||
bool Efinix::post_flash_access()
|
||||
{
|
||||
if (_skip_reset)
|
||||
printInfo("Skip resetting device");
|
||||
else
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Efinix::prepare_flash_access()
|
||||
{
|
||||
if (_skip_load_bridge) {
|
||||
printInfo("Skip loading bridge for spiOverjtag");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string bitname;
|
||||
if (!_spiOverJtagPath.empty()) {
|
||||
bitname = _spiOverJtagPath;
|
||||
} else {
|
||||
if (_device_package.empty()) {
|
||||
printError("Can't program SPI flash: missing device-package information");
|
||||
return false;
|
||||
}
|
||||
|
||||
bitname = get_shell_env_var("OPENFPGALOADER_SOJ_DIR",
|
||||
DATA_DIR "/openFPGALoader");
|
||||
bitname += "/spiOverJtag_efinix_" + _device_package + ".bit.gz";
|
||||
}
|
||||
|
||||
#if defined (_WIN64) || defined (_WIN32)
|
||||
/* Convert relative path embedded at compile time to an absolute path */
|
||||
bitname = PathHelper::absolutePath(bitname);
|
||||
#endif
|
||||
|
||||
std::cout << "use: " << bitname << std::endl;
|
||||
|
||||
/* first: load spi over jtag */
|
||||
try {
|
||||
EfinixHexParser bridge(bitname);
|
||||
bridge.parse();
|
||||
const uint8_t *data = bridge.getData();
|
||||
const int length = bridge.getLength() / 8;
|
||||
programJTAG(data, length);
|
||||
} catch (std::exception &e) {
|
||||
printError(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* */
|
||||
/* SPI interface */
|
||||
/* */
|
||||
|
||||
/*
|
||||
* jtag : jtag interface
|
||||
* cmd : opcode for SPI flash
|
||||
* tx : buffer to send
|
||||
* rx : buffer to fill
|
||||
* len : number of byte to send/receive (cmd not comprise)
|
||||
* so to send only a cmd set len to 0 (or omit this param)
|
||||
*/
|
||||
int Efinix::spi_put(uint8_t cmd,
|
||||
uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||
{
|
||||
int kXferLen = len + 1 + ((rx == NULL) ? 0 : 1);
|
||||
uint8_t jtx[kXferLen];
|
||||
jtx[0] = EfinixHexParser::reverseByte(cmd);
|
||||
uint8_t jrx[kXferLen];
|
||||
if (tx != NULL) {
|
||||
for (uint32_t i=0; i < len; i++)
|
||||
jtx[i+1] = EfinixHexParser::reverseByte(tx[i]);
|
||||
}
|
||||
/* addr BSCAN user1 */
|
||||
_jtag->shiftIR(USER1, _irlen);
|
||||
/* send first already stored cmd,
|
||||
* in the same time store each byte
|
||||
* to next
|
||||
*/
|
||||
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*kXferLen);
|
||||
|
||||
if (rx != NULL) {
|
||||
for (uint32_t i=0; i < len; i++)
|
||||
rx[i] = EfinixHexParser::reverseByte(jrx[i+1] >> 1) | (jrx[i+2] & 0x01);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Efinix::spi_put(uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||
{
|
||||
int kXferLen = len + ((rx == NULL) ? 0 : 1);
|
||||
uint8_t jtx[kXferLen];
|
||||
uint8_t jrx[kXferLen];
|
||||
if (tx != NULL) {
|
||||
for (uint32_t i=0; i < len; i++)
|
||||
jtx[i] = EfinixHexParser::reverseByte(tx[i]);
|
||||
}
|
||||
/* addr BSCAN user1 */
|
||||
_jtag->shiftIR(USER1, _irlen);
|
||||
/* send first already stored cmd,
|
||||
* in the same time store each byte
|
||||
* to next
|
||||
*/
|
||||
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*kXferLen);
|
||||
|
||||
if (rx != NULL) {
|
||||
for (uint32_t i=0; i < len; i++)
|
||||
rx[i] = EfinixHexParser::reverseByte(jrx[i] >> 1) | (jrx[i+1] & 0x01);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Efinix::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose)
|
||||
{
|
||||
uint8_t rx[2], dummy[2], tmp;
|
||||
uint8_t tx = EfinixHexParser::reverseByte(cmd);
|
||||
uint32_t count = 0;
|
||||
|
||||
_jtag->shiftIR(USER1, _irlen, Jtag::UPDATE_IR);
|
||||
_jtag->shiftDR(&tx, NULL, 8, Jtag::SHIFT_DR);
|
||||
|
||||
do {
|
||||
_jtag->shiftDR(dummy, rx, 8*2, Jtag::SHIFT_DR);
|
||||
tmp = (EfinixHexParser::reverseByte(rx[0] >> 1)) | (0x01 & rx[1]);
|
||||
count++;
|
||||
if (count == timeout){
|
||||
printf("timeout: %x %x %x\n", tmp, rx[0], rx[1]);
|
||||
break;
|
||||
}
|
||||
if (verbose) {
|
||||
printf("%x %x %x %u\n", tmp, mask, cond, count);
|
||||
}
|
||||
} while ((tmp & mask) != cond);
|
||||
_jtag->shiftDR(dummy, rx, 8*2, Jtag::EXIT1_DR);
|
||||
_jtag->go_test_logic_reset();
|
||||
|
||||
if (count == timeout) {
|
||||
printf("%x\n", tmp);
|
||||
std::cout << "wait: Error" << std::endl;
|
||||
return -ETIME;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
* Copyright (C) 2020 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
* Copyright (C) 2020-2023 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
*/
|
||||
|
||||
#ifndef SRC_EFINIX_HPP_
|
||||
|
|
@ -12,41 +12,64 @@
|
|||
#include "ftdiJtagMPSSE.hpp"
|
||||
#include "ftdispi.hpp"
|
||||
#include "jtag.hpp"
|
||||
#include "spiInterface.hpp"
|
||||
|
||||
class Efinix: public Device {
|
||||
class Efinix: public Device, SPIInterface {
|
||||
public:
|
||||
Efinix(FtdiSpi *spi, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
uint16_t rst_pin, uint16_t done_pin, uint16_t oe_pin,
|
||||
bool verify, int8_t verbose);
|
||||
Efinix(Jtag* jtag, const std::string &filename,
|
||||
const std::string &file_type,
|
||||
const std::string &board_name,
|
||||
const std::string &file_type, Device::prog_type_t prg_type,
|
||||
const std::string &board_name, const std::string &device_package,
|
||||
const std::string &spiOverJtagPath,
|
||||
bool verify, int8_t verbose);
|
||||
~Efinix();
|
||||
|
||||
void program(unsigned int offset, bool unprotect_flash) override;
|
||||
bool dumpFlash(const std::string &filename,
|
||||
uint32_t base_addr, uint32_t len);
|
||||
virtual bool protect_flash(uint32_t len) override {
|
||||
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
|
||||
bool protect_flash(uint32_t len) override {
|
||||
(void) len;
|
||||
printError("protect flash not supported"); return false;}
|
||||
virtual bool unprotect_flash() override {
|
||||
bool unprotect_flash() override {
|
||||
printError("unprotect flash not supported"); return false;}
|
||||
bool bulk_erase_flash() override {
|
||||
printError("bulk erase flash not supported"); return false;}
|
||||
/* not supported in SPI Active mode */
|
||||
int idCode() override {return 0;}
|
||||
void reset() override;
|
||||
|
||||
/* spi interface */
|
||||
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||
uint32_t len) override;
|
||||
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||
uint32_t timeout, bool verbose = false) override;
|
||||
|
||||
private:
|
||||
void programSPI(unsigned int offset, uint8_t *data, int length,
|
||||
bool unprotect_flash);
|
||||
void programJTAG(uint8_t *data, int length);
|
||||
/* list of efinix family devices */
|
||||
enum efinix_family_t {
|
||||
TITANIUM_FAMILY = 0,
|
||||
TRION_FAMILY,
|
||||
UNKNOWN_FAMILY = 999
|
||||
};
|
||||
void init_common(const Device::prog_type_t &prg_type);
|
||||
void programSPI(unsigned int offset, const uint8_t *data,
|
||||
const int length, const bool unprotect_flash);
|
||||
void programJTAG(const uint8_t *data, const int length);
|
||||
bool post_flash_access() override;
|
||||
bool prepare_flash_access() override;
|
||||
FtdiSpi *_spi;
|
||||
FtdiJtagMPSSE *_ftdi_jtag;
|
||||
uint16_t _rst_pin;
|
||||
uint16_t _done_pin;
|
||||
uint16_t _cs_pin;
|
||||
uint16_t _oe_pin;
|
||||
efinix_family_t _fpga_family;
|
||||
int _irlen;
|
||||
std::string _device_package;
|
||||
std::string _spiOverJtagPath;
|
||||
};
|
||||
|
||||
#endif // SRC_EFINIX_HPP_
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
EfinixHexParser::EfinixHexParser(const string &filename, bool reverseOrder):
|
||||
EfinixHexParser::EfinixHexParser(const string &filename):
|
||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE,
|
||||
false), _reverseOrder(reverseOrder)
|
||||
false)
|
||||
{}
|
||||
|
||||
int EfinixHexParser::parse()
|
||||
|
|
|
|||
|
|
@ -21,17 +21,13 @@ class EfinixHexParser: public ConfigBitstreamParser {
|
|||
/*!
|
||||
* \brief constructor
|
||||
* \param[in] filename: raw file to read
|
||||
* \param[in] reverseOrder: reverse each byte (LSB -> MSB, MSB -> LSB)
|
||||
*/
|
||||
EfinixHexParser(const std::string &filename, bool reverseOrder);
|
||||
EfinixHexParser(const std::string &filename);
|
||||
/*!
|
||||
* \brief read full content of the file, fill the buffer
|
||||
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwhise
|
||||
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwise
|
||||
*/
|
||||
int parse() override;
|
||||
|
||||
private:
|
||||
bool _reverseOrder; /*!< tail if byte must be reversed */
|
||||
};
|
||||
|
||||
#endif // SRC_EFINIXHEXPARSER_HPP_
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@
|
|||
#ifndef SRC_EPCQ_HPP_
|
||||
#define SRC_EPCQ_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "spiInterface.hpp"
|
||||
#include "spiFlash.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ int EPCQ::erase_sector(char start_sector, char nb_sectors)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* write must be do by 256bytes. Before writting next 256bytes we must
|
||||
/* write must be do by 256bytes. Before writing next 256bytes we must
|
||||
* wait for WIP goes low
|
||||
*/
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ void EPCQ::program(unsigned int start_offset, string filename, bool reverse)
|
|||
|
||||
nb_read = fread(rd_buffer, 1, 256, fd);
|
||||
if (nb_read == 0) {
|
||||
printf("problem dans le read du fichier source\n");
|
||||
printf("problem reading the source file\n");
|
||||
break;
|
||||
}
|
||||
buffer[1] = (offset >> 16) & 0xff;
|
||||
|
|
@ -262,14 +262,14 @@ void EPCQ::read_id()
|
|||
_spi->spi_put(0x9F, NULL, rx_buf, 3);
|
||||
_device_id = rx_buf[2];
|
||||
if (_verbose)
|
||||
printf("device id 0x%x attendu 0x15\n", _device_id);
|
||||
printf("device id 0x%x expected 0x15\n", _device_id);
|
||||
/* read EPCQ silicon id */
|
||||
//tx_buf[0] = 0xAB;
|
||||
/* 3 dummy_byte + 1 byte*/
|
||||
_spi->spi_put(0xAB, NULL, rx_buf, 4);
|
||||
_silicon_id = rx_buf[3];
|
||||
if (_verbose)
|
||||
printf("silicon id 0x%x attendu 0x14\n", _silicon_id);
|
||||
printf("silicon id 0x%x expected 0x14\n", _silicon_id);
|
||||
}
|
||||
|
||||
EPCQ::EPCQ(SPIInterface *spi, int8_t verbose):SPIFlash(spi, verbose)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class EPCQ: public SPIFlash {
|
|||
|
||||
void read_id() override;
|
||||
|
||||
//void program(unsigned int start_offet, string filename, bool reverse=true);
|
||||
//void program(unsigned int start_offset, string filename, bool reverse=true);
|
||||
//int erase_sector(char start_sector, char nb_sectors);
|
||||
//void dumpflash(char *dest_file, int size);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
# 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_PROG_PERSIST (1 << 5) /* PROGRAM 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 */
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
FeaParser::FeaParser(string filename, bool verbose):
|
||||
FeaParser::FeaParser(const string &filename, bool verbose):
|
||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose),
|
||||
_feabits(0), _has_feabits(false)
|
||||
{
|
||||
|
|
@ -73,7 +73,7 @@ FeaParser::FeaParser(string filename, bool verbose):
|
|||
_featuresRow[i] = 0;
|
||||
}
|
||||
|
||||
/* fill a vector with consecutive lines, begining with 0 or 1, until EOF
|
||||
/* fill a vector with consecutive lines, beginning 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
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
class FeaParser: public ConfigBitstreamParser {
|
||||
public:
|
||||
FeaParser(std::string filename, bool verbose = false);
|
||||
FeaParser(const std::string &filename, bool verbose = false);
|
||||
int parse() override;
|
||||
void displayHeader() override;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue