Update to latest openFPGALoader files
This commit is contained in:
commit
f817819b3e
|
|
@ -38,8 +38,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
- 18
|
|
||||||
- 20
|
- 20
|
||||||
|
- 22
|
||||||
name: '🚧🐧 Ubuntu ${{ matrix.os }} | build'
|
name: '🚧🐧 Ubuntu ${{ matrix.os }} | build'
|
||||||
runs-on: ubuntu-${{ matrix.os }}.04
|
runs-on: ubuntu-${{ matrix.os }}.04
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -52,6 +52,7 @@ jobs:
|
||||||
sudo apt update -qq
|
sudo apt update -qq
|
||||||
sudo apt install -y \
|
sudo apt install -y \
|
||||||
cmake \
|
cmake \
|
||||||
|
gzip \
|
||||||
libftdi1-2 \
|
libftdi1-2 \
|
||||||
libftdi1-dev \
|
libftdi1-dev \
|
||||||
libhidapi-hidraw0 \
|
libhidapi-hidraw0 \
|
||||||
|
|
@ -121,8 +122,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
- 18
|
|
||||||
- 20
|
- 20
|
||||||
|
- 22
|
||||||
name: '🚦🐧 Ubuntu ${{ matrix.os }} | test'
|
name: '🚦🐧 Ubuntu ${{ matrix.os }} | test'
|
||||||
runs-on: ubuntu-${{ matrix.os }}.04
|
runs-on: ubuntu-${{ matrix.os }}.04
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,6 @@ build/
|
||||||
/doc/compatibility/boards.inc
|
/doc/compatibility/boards.inc
|
||||||
/doc/compatibility/cable.inc
|
/doc/compatibility/cable.inc
|
||||||
/doc/compatibility/fpga.inc
|
/doc/compatibility/fpga.inc
|
||||||
|
|
||||||
|
# VSCode local settings directory
|
||||||
|
/.vscode/
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
# Copy this file to /etc/udev/rules.d/
|
# Copy this file to /etc/udev/rules.d/
|
||||||
|
|
||||||
ACTION!="add|change", GOTO="openfpgaloader_rules_end"
|
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"
|
SUBSYSTEM!="usb|tty|hidraw", GOTO="openfpgaloader_rules_end"
|
||||||
|
|
||||||
# Original FT232/FT245 VID:PID
|
# Original FT232/FT245 VID:PID
|
||||||
|
|
@ -23,6 +27,8 @@ ATTRS{idVendor}=="0547", ATTRS{idProduct}=="1002", MODE="664", GROUP="plugdev",
|
||||||
|
|
||||||
# altera usb-blaster
|
# altera usb-blaster
|
||||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
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
|
# altera usb-blasterII - uninitialized
|
||||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6810", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
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
|
# dirtyJTAG
|
||||||
ATTRS{idVendor}=="1209", ATTRS{idProduct}=="c0ca", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
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
|
# NXP ARM mbed
|
||||||
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
||||||
|
|
||||||
# icebreaker bitsy
|
# icebreaker bitsy
|
||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6146", MODE="664", GROUP="plugdev", TAG+="uaccess"
|
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"
|
LABEL="openfpgaloader_rules_end"
|
||||||
|
|
|
||||||
164
CMakeLists.txt
164
CMakeLists.txt
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
# set the project name
|
# 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}\")
|
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)
|
option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||||
set(ENABLE_UDEV OFF)
|
set(ENABLE_UDEV OFF)
|
||||||
|
|
@ -12,14 +12,25 @@ 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()
|
endif()
|
||||||
option(ENABLE_CMSISDAP "enable cmsis DAP interface (requires hidapi)" ON)
|
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(USE_PKGCONFIG "Use pkgconfig to find libraries" ON)
|
||||||
option(LINK_CMAKE_THREADS "Use CMake find_package to link the threading library" OFF)
|
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)")
|
set(ISE_PATH "/opt/Xilinx/14.7" CACHE STRING "ise root directory (default: /opt/Xilinx/14.7)")
|
||||||
|
|
||||||
## specify the C++ standard
|
## specify the C++ standard
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
|
if (ENABLE_OPTIM)
|
||||||
|
set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
if (BUILD_STATIC)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static ${CMAKE_EXE_LINKER_FLAGS}")
|
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(-DDATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}\")
|
||||||
|
|
||||||
add_definitions(-DISE_DIR=\"${ISE_PATH}\")
|
add_definitions(-DISE_DIR=\"${ISE_PATH}\")
|
||||||
|
add_definitions(-DBLASTERII_DIR=\"${BLASTERII_PATH}\")
|
||||||
|
|
||||||
if(USE_PKGCONFIG)
|
if (USE_PKGCONFIG)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
|
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
|
||||||
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
|
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
|
||||||
pkg_check_modules(HIDAPI hidapi-hidraw)
|
pkg_check_modules(HIDAPI hidapi-hidraw)
|
||||||
# if hidraw not found try with libusb
|
# if hidraw not found try with libusb
|
||||||
if(NOT HIDAPI_FOUND)
|
if (NOT HIDAPI_FOUND)
|
||||||
pkg_check_modules(HIDAPI hidapi-libusb)
|
pkg_check_modules(HIDAPI hidapi-libusb)
|
||||||
endif()
|
endif()
|
||||||
|
if (NOT HIDAPI_FOUND)
|
||||||
|
pkg_check_modules(HIDAPI hidapi)
|
||||||
|
endif()
|
||||||
# zlib support (gzip)
|
# zlib support (gzip)
|
||||||
pkg_check_modules(ZLIB zlib)
|
pkg_check_modules(ZLIB zlib)
|
||||||
if (NOT ZLIB_FOUND)
|
if (NOT ZLIB_FOUND)
|
||||||
|
|
@ -53,7 +68,7 @@ if(USE_PKGCONFIG)
|
||||||
endif()
|
endif()
|
||||||
endif(NOT ZLIB_FOUND)
|
endif(NOT ZLIB_FOUND)
|
||||||
|
|
||||||
if(ENABLE_UDEV)
|
if (ENABLE_UDEV)
|
||||||
pkg_check_modules(LIBUDEV libudev)
|
pkg_check_modules(LIBUDEV libudev)
|
||||||
if (LIBUDEV_FOUND)
|
if (LIBUDEV_FOUND)
|
||||||
add_definitions(-DUSE_UDEV)
|
add_definitions(-DUSE_UDEV)
|
||||||
|
|
@ -62,6 +77,14 @@ if(USE_PKGCONFIG)
|
||||||
set(ENABLE_UDEV OFF)
|
set(ENABLE_UDEV OFF)
|
||||||
endif()
|
endif()
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
set(OPENFPGALOADER_SOURCE
|
set(OPENFPGALOADER_SOURCE
|
||||||
|
|
@ -69,6 +92,7 @@ set(OPENFPGALOADER_SOURCE
|
||||||
src/anlogicBitParser.cpp
|
src/anlogicBitParser.cpp
|
||||||
src/anlogicCable.cpp
|
src/anlogicCable.cpp
|
||||||
src/ch552_jtag.cpp
|
src/ch552_jtag.cpp
|
||||||
|
src/common.cpp
|
||||||
src/dfu.cpp
|
src/dfu.cpp
|
||||||
src/dfuFileParser.cpp
|
src/dfuFileParser.cpp
|
||||||
src/dirtyJtag.cpp
|
src/dirtyJtag.cpp
|
||||||
|
|
@ -77,9 +101,10 @@ set(OPENFPGALOADER_SOURCE
|
||||||
src/fx2_ll.cpp
|
src/fx2_ll.cpp
|
||||||
src/ice40.cpp
|
src/ice40.cpp
|
||||||
src/ihexParser.cpp
|
src/ihexParser.cpp
|
||||||
|
src/pofParser.cpp
|
||||||
|
src/rawParser.cpp
|
||||||
src/spiFlash.cpp
|
src/spiFlash.cpp
|
||||||
src/spiInterface.cpp
|
src/spiInterface.cpp
|
||||||
src/rawParser.cpp
|
|
||||||
src/usbBlaster.cpp
|
src/usbBlaster.cpp
|
||||||
src/epcq.cpp
|
src/epcq.cpp
|
||||||
src/svf_jtag.cpp
|
src/svf_jtag.cpp
|
||||||
|
|
@ -93,8 +118,10 @@ set(OPENFPGALOADER_SOURCE
|
||||||
src/ftdipp_mpsse.cpp
|
src/ftdipp_mpsse.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/latticeBitParser.cpp
|
src/latticeBitParser.cpp
|
||||||
|
src/libusb_ll.cpp
|
||||||
src/gowin.cpp
|
src/gowin.cpp
|
||||||
src/device.cpp
|
src/device.cpp
|
||||||
|
src/jlink.cpp
|
||||||
src/lattice.cpp
|
src/lattice.cpp
|
||||||
src/progressBar.cpp
|
src/progressBar.cpp
|
||||||
src/fsparser.cpp
|
src/fsparser.cpp
|
||||||
|
|
@ -114,6 +141,7 @@ set(OPENFPGALOADER_HEADERS
|
||||||
src/anlogicBitParser.hpp
|
src/anlogicBitParser.hpp
|
||||||
src/anlogicCable.hpp
|
src/anlogicCable.hpp
|
||||||
src/ch552_jtag.hpp
|
src/ch552_jtag.hpp
|
||||||
|
src/common.hpp
|
||||||
src/cxxopts.hpp
|
src/cxxopts.hpp
|
||||||
src/dfu.hpp
|
src/dfu.hpp
|
||||||
src/dfuFileParser.hpp
|
src/dfuFileParser.hpp
|
||||||
|
|
@ -123,14 +151,17 @@ set(OPENFPGALOADER_HEADERS
|
||||||
src/fx2_ll.hpp
|
src/fx2_ll.hpp
|
||||||
src/ice40.hpp
|
src/ice40.hpp
|
||||||
src/ihexParser.hpp
|
src/ihexParser.hpp
|
||||||
|
src/pofParser.hpp
|
||||||
src/progressBar.hpp
|
src/progressBar.hpp
|
||||||
src/rawParser.hpp
|
src/rawParser.hpp
|
||||||
src/usbBlaster.hpp
|
src/usbBlaster.hpp
|
||||||
src/bitparser.hpp
|
src/bitparser.hpp
|
||||||
src/ftdiJtagBitbang.hpp
|
src/ftdiJtagBitbang.hpp
|
||||||
src/ftdiJtagMPSSE.hpp
|
src/ftdiJtagMPSSE.hpp
|
||||||
|
src/jlink.hpp
|
||||||
src/jtag.hpp
|
src/jtag.hpp
|
||||||
src/jtagInterface.hpp
|
src/jtagInterface.hpp
|
||||||
|
src/libusb_ll.hpp
|
||||||
src/fsparser.hpp
|
src/fsparser.hpp
|
||||||
src/part.hpp
|
src/part.hpp
|
||||||
src/board.hpp
|
src/board.hpp
|
||||||
|
|
@ -157,6 +188,19 @@ set(OPENFPGALOADER_HEADERS
|
||||||
src/colognechipCfgParser.hpp
|
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
|
add_executable(openFPGALoader
|
||||||
${OPENFPGALOADER_SOURCE}
|
${OPENFPGALOADER_SOURCE}
|
||||||
${OPENFPGALOADER_HEADERS}
|
${OPENFPGALOADER_HEADERS}
|
||||||
|
|
@ -167,16 +211,6 @@ include_directories(
|
||||||
${LIBFTDI_INCLUDE_DIRS}
|
${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
|
target_link_libraries(openFPGALoader
|
||||||
${LIBUSB_LIBRARIES}
|
${LIBUSB_LIBRARIES}
|
||||||
${LIBFTDI_LIBRARIES}
|
${LIBFTDI_LIBRARIES}
|
||||||
|
|
@ -185,6 +219,9 @@ target_link_libraries(openFPGALoader
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||||
# winsock provides ntohs
|
# winsock provides ntohs
|
||||||
target_link_libraries(openFPGALoader ws2_32)
|
target_link_libraries(openFPGALoader ws2_32)
|
||||||
|
|
||||||
|
target_sources(openFPGALoader PRIVATE src/pathHelper.cpp)
|
||||||
|
list(APPEND OPENFPGALOADER_HEADERS src/pathHelper.hpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# libusb_attach_kernel_driver is only available on Linux.
|
# libusb_attach_kernel_driver is only available on Linux.
|
||||||
|
|
@ -192,28 +229,72 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
add_definitions(-DATTACH_KERNEL)
|
add_definitions(-DATTACH_KERNEL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_UDEV)
|
if (ENABLE_UDEV)
|
||||||
include_directories(${LIBUDEV_INCLUDE_DIRS})
|
include_directories(${LIBUDEV_INCLUDE_DIRS})
|
||||||
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
|
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
|
||||||
endif()
|
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)
|
if (BUILD_STATIC)
|
||||||
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
|
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_CMSISDAP)
|
if (ENABLE_CMSISDAP)
|
||||||
if (HIDAPI_FOUND)
|
if (HIDAPI_FOUND)
|
||||||
include_directories(${HIDAPI_INCLUDE_DIRS})
|
include_directories(${HIDAPI_INCLUDE_DIRS})
|
||||||
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
|
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
|
||||||
add_definitions(-DENABLE_CMSISDAP=1)
|
add_definitions(-DENABLE_CMSISDAP=1)
|
||||||
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
|
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
|
||||||
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
|
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
|
||||||
message("cmsis_dap support enabled")
|
message("cmsis_dap support enabled")
|
||||||
else()
|
else()
|
||||||
message("hidapi-libusb not found: cmsis_dap support disabled")
|
message("hidapi-libusb not found: cmsis_dap support disabled")
|
||||||
endif()
|
endif()
|
||||||
endif(ENABLE_CMSISDAP)
|
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)
|
if (ZLIB_FOUND)
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
target_link_libraries(openFPGALoader ${ZLIB_LIBRARIES})
|
target_link_libraries(openFPGALoader ${ZLIB_LIBRARIES})
|
||||||
|
|
@ -221,7 +302,6 @@ if (ZLIB_FOUND)
|
||||||
else()
|
else()
|
||||||
message("zlib library not found: can't flash intel/altera devices")
|
message("zlib library not found: can't flash intel/altera devices")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
if (LINK_CMAKE_THREADS)
|
if (LINK_CMAKE_THREADS)
|
||||||
find_package(Threads REQUIRED)
|
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})
|
add_definitions(-DFTDI_VERSION=${FTDI_VAL})
|
||||||
|
|
||||||
install(TARGETS openFPGALoader DESTINATION bin)
|
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)
|
file(GLOB GZ_FILES spiOverJtag/spiOverJtag_*.*.gz)
|
||||||
install(FILES
|
|
||||||
test_sfl.svf
|
# 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}
|
${BITS_FILES}
|
||||||
${RBF_FILES}
|
${RBF_FILES}
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(FILES
|
||||||
${GZ_FILES}
|
${GZ_FILES}
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
|
||||||
)
|
)
|
||||||
|
|
|
||||||
68
README.md
68
README.md
|
|
@ -3,7 +3,7 @@
|
||||||
<p align="right">
|
<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="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>
|
<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>
|
</p>
|
||||||
|
|
@ -29,6 +29,8 @@ Also checkout the vendor-specific documentation:
|
||||||
[Lattice](https://trabucayre.github.io/openFPGALoader/vendors/lattice.html),
|
[Lattice](https://trabucayre.github.io/openFPGALoader/vendors/lattice.html),
|
||||||
[Xilinx](https://trabucayre.github.io/openFPGALoader/vendors/xilinx.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
|
## 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).
|
`arty` in the example below is one of the many FPGA board configurations listed [here](https://trabucayre.github.io/openFPGALoader/compatibility/board.html).
|
||||||
|
|
@ -47,52 +49,74 @@ openFPGALoader -c cmsisdap fpga_bitstream.bit
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage: ./openFPGALoader [OPTION...] BIT_FILE
|
Usage: openFPGALoader [OPTION...] BIT_FILE
|
||||||
openFPGALoader -- a program to flash FPGA
|
openFPGALoader -- a program to flash FPGA
|
||||||
|
|
||||||
--altsetting arg DFU interface altsetting (only for DFU mode)
|
--altsetting arg DFU interface altsetting (only for DFU mode)
|
||||||
--bitstream arg bitstream
|
--bitstream arg bitstream
|
||||||
|
--secondary-bitstream arg
|
||||||
|
secondary bitstream (some Xilinx UltraScale
|
||||||
|
boards)
|
||||||
-b, --board arg board name, may be used instead of cable
|
-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
|
-c, --cable arg jtag interface
|
||||||
--invert-read-edge JTAG mode / FTDI: read on negative edge instead
|
--invert-read-edge JTAG mode / FTDI: read on negative edge
|
||||||
of positive
|
instead of positive
|
||||||
--vid arg probe Vendor ID
|
--vid arg probe Vendor ID
|
||||||
--pid arg probe Product 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-serial arg FTDI chip serial number
|
||||||
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
|
||||||
A-D)
|
A-D)
|
||||||
-d, --device arg device to use (/dev/ttyUSBx)
|
|
||||||
--detect detect FPGA
|
--detect detect FPGA
|
||||||
--dfu DFU mode
|
--dfu DFU mode
|
||||||
--dump-flash Dump flash 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-flash select ext flash for device with internal and
|
||||||
external storage
|
external storage
|
||||||
--file-size arg provides size in Byte to dump, must be used with
|
--file-size arg provides size in Byte to dump, must be used
|
||||||
dump-flash
|
with dump-flash
|
||||||
--file-type arg provides file type instead of let's deduced by
|
--file-type arg provides file type instead of let's deduced
|
||||||
using extension
|
by using extension
|
||||||
--flash-sector arg flash sector (Lattice parts only)
|
--flash-sector arg flash sector (Lattice parts only)
|
||||||
--fpga-part arg fpga model flavor + package
|
--fpga-part arg fpga model flavor + package
|
||||||
--freq arg jtag frequency (Hz)
|
--freq arg jtag frequency (Hz)
|
||||||
-f, --write-flash write bitstream in flash (default: false)
|
-f, --write-flash write bitstream in flash (default: false)
|
||||||
--index-chain arg device index in JTAG-chain
|
--index-chain arg device index in JTAG-chain
|
||||||
|
--ip arg IP address (XVC and remote bitbang client)
|
||||||
--list-boards list all supported boards
|
--list-boards list all supported boards
|
||||||
--list-cables list all supported cables
|
--list-cables list all supported cables
|
||||||
--list-fpga list all supported FPGA
|
--list-fpga list all supported FPGA
|
||||||
-m, --write-sram write bitstream in SRAM (default: true)
|
-m, --write-sram write bitstream in SRAM (default: true)
|
||||||
-o, --offset arg start offset in EEPROM
|
-o, --offset arg Start address (in bytes) for read/write into
|
||||||
--pins arg pin config (only for ft232R) TDI:TDO:TCK:TMS
|
non volatile memory (default: 0)
|
||||||
|
--pins arg pin config TDI:TDO:TCK:TMS
|
||||||
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
|
||||||
--protect-flash arg protect SPI flash area
|
--protect-flash arg protect SPI flash area
|
||||||
--quiet Produce quiet output (no progress bar)
|
--quiet Produce quiet output (no progress bar)
|
||||||
-r, --reset reset FPGA after operations
|
-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)
|
--spi SPI mode (only for FTDI in serial mode)
|
||||||
--unprotect-flash Unprotect flash blocks
|
--unprotect-flash Unprotect flash blocks
|
||||||
-v, --verbose Produce verbose output
|
-v, --verbose Produce verbose output
|
||||||
--verbose-level arg verbose level -1: quiet, 0: normal, 1:verbose,
|
--verbose-level arg verbose level -1: quiet, 0: normal,
|
||||||
2:debug
|
1:verbose, 2:debug
|
||||||
-h, --help Give this help list
|
-h, --help Give this help list
|
||||||
--verify Verify write operation (SPI Flash only)
|
--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
|
-V, --Version Print program version
|
||||||
|
|
||||||
Mandatory or optional arguments to long options are also mandatory or optional
|
Mandatory or optional arguments to long options are also mandatory or optional
|
||||||
|
|
@ -100,3 +124,21 @@ for any corresponding short options.
|
||||||
|
|
||||||
Report bugs to <gwenhael.goavec-merou@trabucayre.com>.
|
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
|
- GW1NS-2C
|
||||||
- GW1NSR-4C
|
- GW1NSR-4C
|
||||||
- GW1NZ-1
|
- GW1NZ-1
|
||||||
|
- GW2A-18C
|
||||||
URL: https://www.gowinsemi.com/en/product/detail/2/
|
URL: https://www.gowinsemi.com/en/product/detail/2/
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: IF
|
Flash: IF / EF
|
||||||
|
|
||||||
|
|
||||||
Intel:
|
Intel:
|
||||||
|
|
@ -68,7 +69,9 @@ Intel:
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
||||||
- Description: Cyclone IV CE
|
- 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
|
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-iv/features.html
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
@ -76,7 +79,9 @@ Intel:
|
||||||
- Description: Cyclone V E
|
- Description: Cyclone V E
|
||||||
Model:
|
Model:
|
||||||
- 5CEA2
|
- 5CEA2
|
||||||
|
- 5CEA5
|
||||||
- 5CEBA4
|
- 5CEBA4
|
||||||
|
- 5CEBA9
|
||||||
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-v.html
|
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-v.html
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
@ -96,6 +101,12 @@ Intel:
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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:
|
Lattice:
|
||||||
|
|
||||||
|
|
@ -107,8 +118,16 @@ Lattice:
|
||||||
|
|
||||||
- Description: ECP5
|
- Description: ECP5
|
||||||
Model:
|
Model:
|
||||||
- 25F
|
- LFE5U-12
|
||||||
- 5G 85F
|
- 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
|
URL: http://www.latticesemi.com/Products/FPGAandCPLD/ECP5
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
@ -163,6 +182,7 @@ Xilinx:
|
||||||
|
|
||||||
- Description: Artix 7
|
- Description: Artix 7
|
||||||
Model:
|
Model:
|
||||||
|
- xc7a25t
|
||||||
- xc7a35ti
|
- xc7a35ti
|
||||||
- xc7a50t
|
- xc7a50t
|
||||||
- xc7a75t
|
- xc7a75t
|
||||||
|
|
@ -176,16 +196,42 @@ Xilinx:
|
||||||
Model:
|
Model:
|
||||||
- xc7k160t
|
- xc7k160t
|
||||||
- xc7k325t
|
- xc7k325t
|
||||||
|
- xc7k410t
|
||||||
|
- xc7k420t
|
||||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-7.html#productTable
|
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-7.html#productTable
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
||||||
- Description: Spartan 3
|
- Description: Artix UltraScale+
|
||||||
Model: xc3s200
|
Model:
|
||||||
URL: https://www.xilinx.com/products/silicon-devices/fpga/spartan-3.html
|
- 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
|
Memory: OK
|
||||||
Flash: NA
|
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
|
- Description: Spartan 6
|
||||||
Model:
|
Model:
|
||||||
- xc6slx9
|
- xc6slx9
|
||||||
|
|
@ -216,8 +262,10 @@ Xilinx:
|
||||||
Memory: NA
|
Memory: NA
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
||||||
- Description: XC2C (coolrunner II)
|
- Description: XC2C/XA2C (coolrunner II)
|
||||||
Model: xc2c32a
|
Model:
|
||||||
|
- xc2c32a
|
||||||
|
- xa2c64a
|
||||||
URL: https://www.xilinx.com/support/documentation/data_sheets/ds090.pdf
|
URL: https://www.xilinx.com/support/documentation/data_sheets/ds090.pdf
|
||||||
Memory: TBD
|
Memory: TBD
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
@ -240,7 +288,10 @@ Xilinx:
|
||||||
Flash: NA
|
Flash: NA
|
||||||
|
|
||||||
- Description: ZynqMPSoC
|
- Description: ZynqMPSoC
|
||||||
Model: xczu2cg
|
Model:
|
||||||
|
- xczu2cg
|
||||||
|
- xczu9eg
|
||||||
|
- xczu11eg
|
||||||
URL: https://www.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html
|
URL: https://www.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: NA
|
Flash: NA
|
||||||
|
|
|
||||||
249
doc/boards.yml
249
doc/boards.yml
|
|
@ -13,6 +13,13 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: alchitry_au
|
||||||
Description: Alchitry Au
|
Description: Alchitry Au
|
||||||
URL: https://alchitry.com/products/alchitry-au-fpga-development-board
|
URL: https://alchitry.com/products/alchitry-au-fpga-development-board
|
||||||
|
|
@ -20,6 +27,27 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: arty_a7_35t
|
||||||
Description: Digilent Arty A7
|
Description: Digilent Arty A7
|
||||||
URL: https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start
|
URL: https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start
|
||||||
|
|
@ -94,16 +122,23 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: gatemate_evb_jtag
|
||||||
Description: Cologne Chip GateMate FPGA Evaluation Board (JTAG mode)
|
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
|
FPGA: Cologne Chip GateMate Series
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
||||||
- ID: gatemate_evb_spi
|
- ID: gatemate_evb_spi
|
||||||
Description: Cologne Chip GateMate FPGA Evaluation Board (SPI mode)
|
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
|
FPGA: Cologne Chip GateMate Series
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: OK
|
Flash: OK
|
||||||
|
|
@ -115,6 +150,14 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: colorlight
|
||||||
Description: Colorlight 5A-75B (version 7)
|
Description: Colorlight 5A-75B (version 7)
|
||||||
URL: https://fr.aliexpress.com/item/32281130824.html
|
URL: https://fr.aliexpress.com/item/32281130824.html
|
||||||
|
|
@ -152,6 +195,20 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: de0
|
||||||
Description: Terasic DE0
|
Description: Terasic DE0
|
||||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=364
|
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=364
|
||||||
|
|
@ -172,6 +229,12 @@
|
||||||
FPGA: Cyclone V SoC 5CSEMA4U23C6
|
FPGA: Cyclone V SoC 5CSEMA4U23C6
|
||||||
Memory: OK
|
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
|
- ID: de10nano
|
||||||
Description: Terasic de10Nano
|
Description: Terasic de10Nano
|
||||||
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=205&No=1046
|
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
|
FPGA: Cyclone V SoC 5CSEMA5F31C6
|
||||||
Memory: OK
|
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
|
- ID: ecp5_evn
|
||||||
Description: Lattice ECP5 5G Evaluation Board
|
Description: Lattice ECP5 5G Evaluation Board
|
||||||
URL: https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP5EvaluationBoard
|
URL: https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP5EvaluationBoard
|
||||||
|
|
@ -224,6 +293,13 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: IF
|
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
|
- ID: ice40_generic
|
||||||
Description: iCEBreaker
|
Description: iCEBreaker
|
||||||
URL: https://1bitsquared.com/collections/fpga/products/icebreaker
|
URL: https://1bitsquared.com/collections/fpga/products/icebreaker
|
||||||
|
|
@ -254,7 +330,7 @@
|
||||||
Description: iCE40-HX8K
|
Description: iCE40-HX8K
|
||||||
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx
|
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx
|
||||||
FPGA: iCE40 HX8k
|
FPGA: iCE40 HX8k
|
||||||
Memory: NT
|
Memory: OK
|
||||||
Flash: AS
|
Flash: AS
|
||||||
Constraints: iCE40-HX8K
|
Constraints: iCE40-HX8K
|
||||||
|
|
||||||
|
|
@ -274,6 +350,14 @@
|
||||||
Flash: AS
|
Flash: AS
|
||||||
Constraints: iCE40HX8K-EVB
|
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
|
- ID: ice40_generic
|
||||||
Description: Icezum Alhambra II
|
Description: Icezum Alhambra II
|
||||||
URL: https://alhambrabits.com/alhambra
|
URL: https://alhambrabits.com/alhambra
|
||||||
|
|
@ -290,6 +374,20 @@
|
||||||
Flash: NT
|
Flash: NT
|
||||||
Constraints: KC705
|
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
|
- ID: licheeTang
|
||||||
Description: Sipeed Lichee Tang
|
Description: Sipeed Lichee Tang
|
||||||
URL: https://tang.sipeed.com/en/hardware-overview/lichee-tang/
|
URL: https://tang.sipeed.com/en/hardware-overview/lichee-tang/
|
||||||
|
|
@ -318,6 +416,22 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: nexysVideo
|
||||||
Description: Digilent Nexys Video
|
Description: Digilent Nexys Video
|
||||||
URL: https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start
|
URL: https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start
|
||||||
|
|
@ -325,6 +439,20 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: orangeCrab
|
||||||
Description: Orange Crab
|
Description: Orange Crab
|
||||||
URL: https://github.com/gregdavill/OrangeCrab
|
URL: https://github.com/gregdavill/OrangeCrab
|
||||||
|
|
@ -333,6 +461,13 @@
|
||||||
Flash: OK (DFU)
|
Flash: OK (DFU)
|
||||||
Constraints: OrangeCrab-r0.2
|
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
|
- ID: pipistrello
|
||||||
Description: Saanlima Pipistrello LX45
|
Description: Saanlima Pipistrello LX45
|
||||||
URL: http://pipistrello.saanlima.com/index.php?title=Welcome_to_Pipistrello
|
URL: http://pipistrello.saanlima.com/index.php?title=Welcome_to_Pipistrello
|
||||||
|
|
@ -340,6 +475,13 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: qmtechCycloneIV
|
||||||
Description: QMTech CycloneIV Core Board
|
Description: QMTech CycloneIV Core Board
|
||||||
URL: https://fr.aliexpress.com/item/32949281189.html
|
URL: https://fr.aliexpress.com/item/32949281189.html
|
||||||
|
|
@ -354,6 +496,13 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: qmtechKintex7
|
||||||
Description: QMTech Kintex7 Core Board
|
Description: QMTech Kintex7 Core Board
|
||||||
URL: https://www.aliexpress.com/item/1005003668804223.html
|
URL: https://www.aliexpress.com/item/1005003668804223.html
|
||||||
|
|
@ -396,6 +545,13 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: 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
|
- ID: tangnano
|
||||||
Description: Sipeed Tang Nano
|
Description: Sipeed Tang Nano
|
||||||
URL: https://tangnano.sipeed.com/en/
|
URL: https://tangnano.sipeed.com/en/
|
||||||
|
|
@ -423,6 +579,20 @@
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: IF/EF
|
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
|
- ID: tec0117
|
||||||
Description: Trenz Gowin LittleBee (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
|
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
|
Memory: OK
|
||||||
Flash: IF
|
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
|
- ID: ulx3s
|
||||||
Description: Radiona ULX3S
|
Description: Radiona ULX3S
|
||||||
URL: https://radiona.org/ulx3s/
|
URL: https://radiona.org/ulx3s/
|
||||||
|
|
@ -463,19 +647,19 @@
|
||||||
Memory: NA
|
Memory: NA
|
||||||
Flash: AS
|
Flash: AS
|
||||||
|
|
||||||
- ID: trion_t120_bga576_spi
|
- ID: usrpx300
|
||||||
Description: Efinix Trion T120 BGA576 Dev Kit
|
Description: Ettus Research USRP X300
|
||||||
URL: https://www.efinixinc.com/products-devkits-triont120bga576.html
|
URL: https://www.ettus.com/all-products/x300-kit/
|
||||||
FPGA: Trion T120BGA576
|
FPGA: Kintex xc7k325tffg900
|
||||||
Memory: NA
|
Memory: OK
|
||||||
Flash: AS
|
Flash: NA
|
||||||
|
|
||||||
- ID: trion_ti60_f225_spi
|
- ID: usrpx310
|
||||||
Description: Efinix Titanium F225 Dev Kit
|
Description: Ettus Research USRP X300
|
||||||
URL: https://www.efinixinc.com/products-devkits-titaniumti60f225.html
|
URL: https://www.ettus.com/all-products/x310-kit/
|
||||||
FPGA: Titanium Ti60F225
|
FPGA: Kintex xc7k410tffg900
|
||||||
Memory: NA
|
Memory: OK
|
||||||
Flash: AS
|
Flash: NA
|
||||||
|
|
||||||
- ID: xmf3
|
- ID: xmf3
|
||||||
Description: PLDkit XMF3
|
Description: PLDkit XMF3
|
||||||
|
|
@ -499,6 +683,20 @@
|
||||||
Flash: NA
|
Flash: NA
|
||||||
Constraints: ZC706
|
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
|
- ID: zedboard
|
||||||
Description: Avnet ZedBoard
|
Description: Avnet ZedBoard
|
||||||
URL: https://www.avnet.com/wps/portal/us/products/avnet-boards/avnet-board-families/zedboard/
|
URL: https://www.avnet.com/wps/portal/us/products/avnet-boards/avnet-board-families/zedboard/
|
||||||
|
|
@ -520,3 +718,24 @@
|
||||||
FPGA: zynq7000 xc7z020clg400
|
FPGA: zynq7000 xc7z020clg400
|
||||||
Memory: OK
|
Memory: OK
|
||||||
Flash: NA
|
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.
|
Description: USB-JTAG/UART debugger based on BL702 microcontroler.
|
||||||
URL: https://github.com/sipeed/RV-Debugger-BL702
|
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.
|
- Name: honeycomb USB-JTAG interface.
|
||||||
Description: FT2232C clone based on STM32F042 microcontroler
|
Description: FT2232C clone based on STM32F042 microcontroler
|
||||||
URL: https://github.com/Disasm/f042-ftdi
|
URL: https://github.com/Disasm/f042-ftdi
|
||||||
|
|
@ -172,6 +176,19 @@ ecpix5-debug:
|
||||||
URL: https://shop.lambdaconcept.com/home/46-ecpix-5.html
|
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:
|
jtag-smt2-nc:
|
||||||
|
|
||||||
- Name: 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
|
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:
|
orbtrace:
|
||||||
|
|
||||||
- Name: orbtrace interface
|
- Name: orbtrace interface
|
||||||
|
|
@ -186,6 +210,27 @@ orbtrace:
|
||||||
URL: https://github.com/orbcode/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:
|
tigard:
|
||||||
|
|
||||||
- Name: tigard
|
- Name: tigard
|
||||||
|
|
@ -204,3 +249,30 @@ usb-blasterII:
|
||||||
- Name: intel USB Blaster II interface
|
- Name: intel USB Blaster II interface
|
||||||
Description: JTAG programmer cable from intel/altera (EZ-USB FX2 + EPM570)
|
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
|
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
|
openFPGALoader [options] -r
|
||||||
|
|
||||||
Using negative edge for TDO's sampling
|
Using negative edge for TDO's sampling
|
||||||
====================================
|
======================================
|
||||||
|
|
||||||
If transaction are unstable you can try to change read edge by using
|
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.
|
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
|
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
|
With FPGA using an external SPI flash (*xilinx*, *lattice ECP5/nexus/ice40*, *anlogic*, *efinix*) option ``-o`` allows
|
||||||
one to write raw binary file to an arbitrary adress in FLASH.
|
one to write raw binary file to an arbitrary adress in FLASH.
|
||||||
|
|
||||||
|
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
|
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``
|
* *Arch Linux*: ``sudo pacman -S openfpgaloader``
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Alternatively, you could build from source. First: install required libraries:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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
|
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
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
|
git \
|
||||||
|
gzip \
|
||||||
libftdi1-2 \
|
libftdi1-2 \
|
||||||
libftdi1-dev \
|
libftdi1-dev \
|
||||||
libhidapi-hidraw0 \
|
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
|
-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:
|
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.
|
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
|
macOS
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|
@ -134,6 +152,19 @@ openFPGALoader is available as a `Homebrew <https://brew.sh>`__ formula:
|
||||||
|
|
||||||
brew install openfpgaloader
|
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
|
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.
|
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.
|
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
|
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:
|
1. Program using Evaluation Board:
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ Performs an active hardware reset and writes the configuration into the FPGA lat
|
||||||
SPI Configuration
|
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:
|
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
|
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:
|
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
|
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:
|
1. Write to flash using Evaluation Board:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
Since openFPGALoader access the flash directly in SPI mode the ``-b fireant``, ``-b xyloni_spi`` is required (no
|
||||||
autodetection possible).
|
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``
|
* ``tec0117``
|
||||||
* ``tangnano``
|
* ``tangnano``
|
||||||
|
* ``tangnano1k``
|
||||||
* ``tangnano4k``
|
* ``tangnano4k``
|
||||||
|
* ``tangnano9k``
|
||||||
|
* ``tangnano20k``
|
||||||
|
* ``tangprimer20k``
|
||||||
* ``runber``
|
* ``runber``
|
||||||
|
|
||||||
Flash
|
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
|
It's possible to flash external SPI Flash (connected to MSPI) in bscan mode by using ``--external-flash`` instead of
|
||||||
``-f``.
|
``-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::
|
.. NOTE::
|
||||||
|
|
||||||
* CYC1000
|
* CYC1000
|
||||||
|
* C10LP-RefKit
|
||||||
* DE0
|
* DE0
|
||||||
* de0nano
|
* de0nano
|
||||||
|
|
||||||
|
|
@ -21,7 +22,7 @@ SVF and RBF files are supported.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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:
|
``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
|
quartus_cpf --option=bitstream_compression=off -c project_name.sof project_name.rbf
|
||||||
|
|
||||||
.. WARNING::
|
.. 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.
|
Keep in mind to disable this option.
|
||||||
|
|
||||||
file load:
|
file load:
|
||||||
|
|
@ -41,7 +42,7 @@ file load:
|
||||||
# or
|
# or
|
||||||
openFPGALoader -b boardname project_name.rbf
|
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
|
SPI flash
|
||||||
---------
|
---------
|
||||||
|
|
@ -52,12 +53,17 @@ RPD and RBF are supported.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# CYC1000
|
||||||
quartus_cpf -o auto_create_rpd=on -c -d EPCQ16A -s 10CL025YU256C8G project_name.svf project_name.jic
|
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:
|
file load:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
openFPGALoader -b cyc1000 -r project_name_auto.rpd
|
openFPGALoader -b boardname -r project_name_auto.rpd
|
||||||
# or
|
# 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
|
.. code-block:: bash
|
||||||
|
|
||||||
openFPGALoader [-b yourboard] impl1/*.jed
|
openFPGALoader [-b yourboard] [--flash-sector CFG0] impl1/*.jed
|
||||||
|
|
||||||
where ``yourboard`` may be:
|
where ``yourboard`` may be:
|
||||||
|
|
||||||
* ``machX02EVN``
|
* ``machX02EVN``
|
||||||
|
* ``machX03EVN``
|
||||||
* ``machXO3SK``
|
* ``machXO3SK``
|
||||||
|
|
||||||
|
and where ``--flash-sector CFG0`` is needed for the MachXO3D Breakout Board.
|
||||||
|
|
||||||
|
``.bit`` may also be used for *machXO2*
|
||||||
|
|
||||||
SRAM
|
SRAM
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -37,6 +42,7 @@ File load:
|
||||||
where ``yourboard`` may be:
|
where ``yourboard`` may be:
|
||||||
|
|
||||||
* ``machX02EVN``
|
* ``machX02EVN``
|
||||||
|
* ``machX03EVN``
|
||||||
* ``machXO3SK``
|
* ``machXO3SK``
|
||||||
|
|
||||||
iCE40
|
iCE40
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ SPI flash
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
``.bit``, ``.bin``, and ``.mcs`` are supported for FLASH.
|
``.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
|
.. code-block:: tcl
|
||||||
|
|
||||||
|
|
@ -94,5 +94,24 @@ File load:
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
``--fpga-part`` is only required if this information is not provided at ``board.hpp`` level or if the board is not
|
``--fpga-part`` is only required if this information is not provided at ``board.hpp`` level or if the board is not
|
||||||
officially supported.
|
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.
|
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" \
|
-G "MSYS Makefiles" \
|
||||||
-DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \
|
-DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \
|
||||||
../../../..
|
../../../..
|
||||||
cmake --build .
|
MSYS2_ARG_CONV_EXCL="-DDATA_DIR=" cmake --build .
|
||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
|
|
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
tmp_*
|
tmp_*
|
||||||
|
*.bit
|
||||||
|
*.rbf
|
||||||
|
|
|
||||||
|
|
@ -36,60 +36,115 @@ elif subpart == "xc7a":
|
||||||
family = "Artix"
|
family = "Artix"
|
||||||
tool = "vivado"
|
tool = "vivado"
|
||||||
elif subpart == "xc7k":
|
elif subpart == "xc7k":
|
||||||
|
device_size = int(part.split('k')[1].split('t')[0])
|
||||||
|
if device_size <= 160:
|
||||||
family = "Kintex 7"
|
family = "Kintex 7"
|
||||||
tool = "vivado"
|
tool = "vivado"
|
||||||
|
else:
|
||||||
|
family = "Kintex7"
|
||||||
|
tool = "ise"
|
||||||
|
speed = -2
|
||||||
elif subpart == "xc7s":
|
elif subpart == "xc7s":
|
||||||
family = "Spartan 7"
|
family = "Spartan 7"
|
||||||
tool = "vivado"
|
tool = "vivado"
|
||||||
elif subpart == "xc6s":
|
elif subpart == "xc6s":
|
||||||
family = "Spartan6"
|
family = "Spartan6"
|
||||||
tool = "ise"
|
tool = "ise"
|
||||||
|
speed = -3
|
||||||
|
elif subpart == "xc3s":
|
||||||
|
family = "Spartan3E"
|
||||||
|
tool = "ise"
|
||||||
|
speed = -4
|
||||||
|
elif subpart in ["xcvu", "xcku"]:
|
||||||
|
family = "Xilinx UltraScale"
|
||||||
|
tool = "vivado"
|
||||||
else:
|
else:
|
||||||
print("Error: unknown device")
|
print("Error: unknown device")
|
||||||
os.sys.exit()
|
os.sys.exit()
|
||||||
|
|
||||||
if tool in ["ise", "vivado"]:
|
if tool in ["ise", "vivado"]:
|
||||||
pkg_name = {
|
pkg_name = {
|
||||||
|
"xc3s500evq100" : "xc3s_vq100",
|
||||||
|
"xc6slx9tqg144" : "xc6s_tqg144",
|
||||||
|
"xc6slx9csg324" : "xc6s_csg324",
|
||||||
"xc6slx16ftg256" : "xc6s_ftg256",
|
"xc6slx16ftg256" : "xc6s_ftg256",
|
||||||
"xc6slx16csg324" : "xc6s_csg324",
|
"xc6slx16csg324" : "xc6s_csg324",
|
||||||
"xc6slx45csg324" : "xc6s_csg324",
|
"xc6slx45csg324" : "xc6s_csg324",
|
||||||
"xc6slx100fgg484" : "xc6s_fgg484",
|
"xc6slx100fgg484" : "xc6s_fgg484",
|
||||||
|
"xc6slx150tcsg484" : "xc6s_csg484",
|
||||||
"xc6slx150tfgg484" : "xc6s_fgg484",
|
"xc6slx150tfgg484" : "xc6s_fgg484",
|
||||||
|
"xc7a25tcpg238" : "xc7a_cpg238",
|
||||||
|
"xc7a25tcsg325" : "xc7a_csg325",
|
||||||
"xc7a35tcpg236" : "xc7a_cpg236",
|
"xc7a35tcpg236" : "xc7a_cpg236",
|
||||||
"xc7a35tcsg324" : "xc7a_csg324",
|
"xc7a35tcsg324" : "xc7a_csg324",
|
||||||
"xc7a35tftg256" : "xc7a_ftg256",
|
"xc7a35tftg256" : "xc7a_ftg256",
|
||||||
"xc7a50tcpg236" : "xc7a_cpg236",
|
"xc7a50tcpg236" : "xc7a_cpg236",
|
||||||
|
"xc7a50tcsg324" : "xc7a_csg324",
|
||||||
"xc7a50tfgg484" : "xc7a_fgg484",
|
"xc7a50tfgg484" : "xc7a_fgg484",
|
||||||
"xc7a75tfgg484" : "xc7a_fgg484",
|
"xc7a75tfgg484" : "xc7a_fgg484",
|
||||||
"xc7a100tcsg324" : "xc7a_csg324",
|
"xc7a100tcsg324" : "xc7a_csg324",
|
||||||
"xc7a100tfgg484" : "xc7a_fgg484",
|
"xc7a100tfgg484" : "xc7a_fgg484",
|
||||||
|
"xc7a100tfgg676" : "xc7a_fgg676",
|
||||||
"xc7a200tsbg484" : "xc7a_sbg484",
|
"xc7a200tsbg484" : "xc7a_sbg484",
|
||||||
"xc7a200tfbg484" : "xc7a_fbg484",
|
"xc7a200tfbg484" : "xc7a_fbg484",
|
||||||
|
"xc7k160tffg676" : "xc7k_ffg676",
|
||||||
"xc7k325tffg676" : "xc7k_ffg676",
|
"xc7k325tffg676" : "xc7k_ffg676",
|
||||||
"xc7k325tffg900" : "xc7k_ffg900",
|
"xc7k325tffg900" : "xc7k_ffg900",
|
||||||
|
"xc7k420tffg901" : "xc7k_ffg901",
|
||||||
|
"xc7s25csga225" : "xc7s_csga225",
|
||||||
"xc7s25csga324" : "xc7s_csga324",
|
"xc7s25csga324" : "xc7s_csga324",
|
||||||
"xc7s50csga324" : "xc7s_csga324"
|
"xc7s50csga324" : "xc7s_csga324",
|
||||||
|
"xcvu9p-flga2104" : "xcvu9p_flga2104",
|
||||||
|
"xcvu37p-fsvh2892" : "xcvu37p_fsvh2892",
|
||||||
|
"xcku5p-ffvb676" : "xcku5p_ffvb676",
|
||||||
}[part]
|
}[part]
|
||||||
if tool == "ise":
|
if tool == "ise":
|
||||||
cst_type = "UCF"
|
cst_type = "UCF"
|
||||||
tool_options = {'family': family,
|
tool_options = {'family': family,
|
||||||
'device': {
|
'device': {
|
||||||
|
"xc3s500evq100": "xc3s500e",
|
||||||
|
"xc6slx9tqg144": "xc6slx9",
|
||||||
|
"xc6slx9csg324": "xc6slx9",
|
||||||
"xc6slx16ftg256": "xc6slx16",
|
"xc6slx16ftg256": "xc6slx16",
|
||||||
"xc6slx16csg324": "xc6slx16",
|
"xc6slx16csg324": "xc6slx16",
|
||||||
"xc6slx45csg324": "xc6slx45",
|
"xc6slx45csg324": "xc6slx45",
|
||||||
"xc6slx100fgg484": "xc6slx100",
|
"xc6slx100fgg484": "xc6slx100",
|
||||||
"xc6slx150tfgg484": "xc6slx150t"}[part],
|
"xc6slx150tcsg484": "xc6slx150t",
|
||||||
|
"xc6slx150tfgg484": "xc6slx150t",
|
||||||
|
"xc7k325tffg676": "xc7k325t",
|
||||||
|
"xc7k325tffg900": "xc7k325t",
|
||||||
|
"xc7k420tffg901": "xc7k420t",
|
||||||
|
}[part],
|
||||||
'package': {
|
'package': {
|
||||||
|
"xc3s500evq100": "vq100",
|
||||||
|
"xc6slx9tqg144": "tqg144",
|
||||||
|
"xc6slx9csg324": "csg324",
|
||||||
"xc6slx16ftg256": "ftg256",
|
"xc6slx16ftg256": "ftg256",
|
||||||
"xc6slx16csg324": "csg324",
|
"xc6slx16csg324": "csg324",
|
||||||
"xc6slx45csg324": "csg324",
|
"xc6slx45csg324": "csg324",
|
||||||
"xc6slx100fgg484": "fgg384",
|
"xc6slx100fgg484": "fgg384",
|
||||||
"xc6slx150tfgg484": "fgg484"}[part],
|
"xc6slx150tcsg484": "csg484",
|
||||||
'speed' : -3
|
"xc6slx150tfgg484": "fgg484",
|
||||||
|
"xc7k325tffg676": "ffg676",
|
||||||
|
"xc7k325tffg900": "ffg900",
|
||||||
|
"xc7k420tffg901": "ffg901",
|
||||||
|
}[part],
|
||||||
|
'speed' : speed
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
cst_type = "xdc"
|
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()
|
cst_file = currDir + "constr_" + pkg_name + "." + cst_type.lower()
|
||||||
files.append({'name': currDir + 'xilinx_spiOverJtag.v',
|
files.append({'name': currDir + 'xilinx_spiOverJtag.v',
|
||||||
'file_type': 'verilogSource'})
|
'file_type': 'verilogSource'})
|
||||||
|
|
@ -97,10 +152,14 @@ if tool in ["ise", "vivado"]:
|
||||||
else:
|
else:
|
||||||
full_part = {
|
full_part = {
|
||||||
"10cl025256": "10CL025YU256C8G",
|
"10cl025256": "10CL025YU256C8G",
|
||||||
|
"10cl055484": "10CL055YU484C8G",
|
||||||
|
"ep4ce11523": "EP4CE115F23C7",
|
||||||
"ep4ce2217" : "EP4CE22F17C6",
|
"ep4ce2217" : "EP4CE22F17C6",
|
||||||
"ep4ce1523" : "EP4CE15F23C8",
|
"ep4ce1523" : "EP4CE15F23C8",
|
||||||
"5ce223" : "5CEFA2F23I7",
|
"5ce223" : "5CEFA2F23I7",
|
||||||
|
"5ce523" : "5CEFA5F23I7",
|
||||||
"5ce423" : "5CEBA4F23C8",
|
"5ce423" : "5CEBA4F23C8",
|
||||||
|
"5ce927" : "5CEBA9F27C7",
|
||||||
"5cse423" : "5CSEMA4U23C6",
|
"5cse423" : "5CSEMA4U23C6",
|
||||||
"5cse623" : "5CSEBA6U23I7"}[part]
|
"5cse623" : "5CSEBA6U23I7"}[part]
|
||||||
files.append({'name': currDir + 'altera_spiOverJtag.v',
|
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 STRATIXV_CONFIGURATION_SCHEME "ACTIVE SERIAL X4"
|
||||||
set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION ON
|
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
|
# Project creation
|
||||||
set grade [dict create \
|
set grade [dict create \
|
||||||
|
xc7a25tcpg238 -1 \
|
||||||
|
xc7a25tcsg325 -1 \
|
||||||
xc7a35tcpg236 -1 \
|
xc7a35tcpg236 -1 \
|
||||||
xc7a35tcsg324 -1 \
|
xc7a35tcsg324 -1 \
|
||||||
xc7a35tftg256 -1 \
|
xc7a35tftg256 -1 \
|
||||||
|
|
@ -16,10 +18,13 @@ set grade [dict create \
|
||||||
xc7a200tsbg484 -1 \
|
xc7a200tsbg484 -1 \
|
||||||
xc7k325tffg676 -1 \
|
xc7k325tffg676 -1 \
|
||||||
xc7k325tffg900 -2 \
|
xc7k325tffg900 -2 \
|
||||||
|
xc7s25csga225 -1 \
|
||||||
xc7s50csga324 -1 \
|
xc7s50csga324 -1 \
|
||||||
]
|
]
|
||||||
|
|
||||||
set pkg_name [dict create \
|
set pkg_name [dict create \
|
||||||
|
xc7a25tcpg238 xc7a_cpg238 \
|
||||||
|
xc7a25tcsg325 xc7a_csg325 \
|
||||||
xc7a35tcpg236 xc7a_cpg236 \
|
xc7a35tcpg236 xc7a_cpg236 \
|
||||||
xc7a35tcsg324 xc7a_csg324 \
|
xc7a35tcsg324 xc7a_csg324 \
|
||||||
xc7a35tftg256 xc7a_ftg256 \
|
xc7a35tftg256 xc7a_ftg256 \
|
||||||
|
|
@ -30,6 +35,7 @@ set pkg_name [dict create \
|
||||||
xc7a200tfbg484 xc7a_fbg484 \
|
xc7a200tfbg484 xc7a_fbg484 \
|
||||||
xc7k325tffg676 xc7k_ffg676 \
|
xc7k325tffg676 xc7k_ffg676 \
|
||||||
xc7k325tffg900 xc7k_ffg900 \
|
xc7k325tffg900 xc7k_ffg900 \
|
||||||
|
xc7s25csga225 xc7s_csga225 \
|
||||||
xc7s50csga324 xc7s_csga324 \
|
xc7s50csga324 xc7s_csga324 \
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,27 @@
|
||||||
module spiOverJtag
|
module spiOverJtag
|
||||||
(
|
(
|
||||||
|
`ifndef virtexultrascale
|
||||||
output csn,
|
output csn,
|
||||||
|
|
||||||
`ifdef spartan6
|
`ifdef spartan6
|
||||||
output sck,
|
output sck,
|
||||||
|
`endif
|
||||||
|
`ifdef spartan3e
|
||||||
|
output sck,
|
||||||
`endif
|
`endif
|
||||||
output sdi_dq0,
|
output sdi_dq0,
|
||||||
input sdo_dq1,
|
input sdo_dq1,
|
||||||
output wpn_dq2,
|
output wpn_dq2,
|
||||||
output hldn_dq3
|
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;
|
wire capture, drck, sel, update;
|
||||||
|
|
@ -41,7 +55,44 @@ module spiOverJtag
|
||||||
|
|
||||||
`ifdef spartan6
|
`ifdef spartan6
|
||||||
assign sck = drck;
|
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 #(
|
STARTUPE2 #(
|
||||||
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
|
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
|
||||||
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation.
|
.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
|
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output
|
||||||
);
|
);
|
||||||
`endif
|
`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
|
`ifdef spartan6
|
||||||
BSCAN_SPARTAN6 #(
|
BSCAN_SPARTAN6 #(
|
||||||
`else
|
`else
|
||||||
|
|
@ -88,5 +160,60 @@ module spiOverJtag
|
||||||
.TDO (tdo) // 1-bit input: Test Data Output (TDO) input
|
.TDO (tdo) // 1-bit input: Test Data Output (TDO) input
|
||||||
// for USER function.
|
// 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
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -9,26 +9,31 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "epcq.hpp"
|
#include "epcq.hpp"
|
||||||
#include "progressBar.hpp"
|
#include "progressBar.hpp"
|
||||||
#include "rawParser.hpp"
|
#include "rawParser.hpp"
|
||||||
|
#if defined (_WIN64) || defined (_WIN32)
|
||||||
|
#include "pathHelper.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IDCODE 6
|
#define IDCODE 6
|
||||||
#define USER0 0x0C
|
#define USER0 0x0C
|
||||||
#define USER1 0x0E
|
#define USER1 0x0E
|
||||||
#define BYPASS 0x3FF
|
#define BYPASS 0x3FF
|
||||||
#define IRLENGTH 10
|
#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,
|
Altera::Altera(Jtag *jtag, const std::string &filename,
|
||||||
const std::string &file_type, Device::prog_type_t prg_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
const std::string &device_package, 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),
|
Device(jtag, filename, file_type, verify, verbose),
|
||||||
SPIInterface(filename, verbose, 256, verify),
|
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
|
||||||
_svf(_jtag, _verbose), _device_package(device_package),
|
skip_reset),
|
||||||
|
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
|
||||||
_vir_addr(0x1000), _vir_length(14)
|
_vir_addr(0x1000), _vir_length(14)
|
||||||
{
|
{
|
||||||
if (prg_type == Device::RD_FLASH) {
|
if (prg_type == Device::RD_FLASH) {
|
||||||
|
|
@ -148,19 +153,46 @@ void Altera::programMem(RawParser &_bit)
|
||||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
_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()
|
bool Altera::load_bridge()
|
||||||
{
|
{
|
||||||
|
std::string bitname;
|
||||||
|
if (!_spiOverJtagPath.empty()) {
|
||||||
|
bitname = _spiOverJtagPath;
|
||||||
|
} else {
|
||||||
if (_device_package.empty()) {
|
if (_device_package.empty()) {
|
||||||
printError("Can't program SPI flash: missing device-package information");
|
printError("Can't program SPI flash: missing device-package information");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DATA_DIR is defined at compile time.
|
bitname = get_shell_env_var("OPENFPGALOADER_SOJ_DIR", DATA_DIR "/openFPGALoader");
|
||||||
std::string bitname = DATA_DIR "/openFPGALoader/spiOverJtag_";
|
|
||||||
#ifdef HAS_ZLIB
|
#ifdef HAS_ZLIB
|
||||||
bitname += _device_package + ".rbf.gz";
|
bitname += "/spiOverJtag_" + _device_package + ".rbf.gz";
|
||||||
#else
|
#else
|
||||||
bitname += _device_package + ".rbf";
|
bitname += "/spiOverJtag_" + _device_package + ".rbf";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (_WIN64) || defined (_WIN32)
|
||||||
|
/* Convert relative path embedded at compile time to an absolute path */
|
||||||
|
bitname = PathHelper::absolutePath(bitname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::cout << "use: " << bitname << std::endl;
|
std::cout << "use: " << bitname << std::endl;
|
||||||
|
|
@ -190,13 +222,9 @@ void Altera::program(unsigned int offset, bool unprotect_flash)
|
||||||
*/
|
*/
|
||||||
/* mem mode -> svf */
|
/* mem mode -> svf */
|
||||||
if (_mode == Device::MEM_MODE) {
|
if (_mode == Device::MEM_MODE) {
|
||||||
if (_file_extension == "svf") {
|
|
||||||
_svf.parse(_filename);
|
|
||||||
} else {
|
|
||||||
RawParser _bit(_filename, false);
|
RawParser _bit(_filename, false);
|
||||||
_bit.parse();
|
_bit.parse();
|
||||||
programMem(_bit);
|
programMem(_bit);
|
||||||
}
|
|
||||||
} else if (_mode == Device::SPI_MODE) {
|
} else if (_mode == Device::SPI_MODE) {
|
||||||
// reverse only bitstream raw binaries data no
|
// reverse only bitstream raw binaries data no
|
||||||
bool reverseOrder = false;
|
bool reverseOrder = false;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ class Altera: public Device, SPIInterface {
|
||||||
const std::string &file_type,
|
const std::string &file_type,
|
||||||
Device::prog_type_t prg_type,
|
Device::prog_type_t prg_type,
|
||||||
const std::string &device_package,
|
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();
|
~Altera();
|
||||||
|
|
||||||
void programMem(RawParser &_bit);
|
void programMem(RawParser &_bit);
|
||||||
|
|
@ -56,6 +58,12 @@ class Altera: public Device, SPIInterface {
|
||||||
bool unprotect_flash() override {
|
bool unprotect_flash() override {
|
||||||
return SPIInterface::unprotect_flash();
|
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,
|
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||||
uint32_t len) override;
|
uint32_t len) override;
|
||||||
|
|
@ -64,8 +72,8 @@ class Altera: public Device, SPIInterface {
|
||||||
uint32_t timeout, bool verbose = false) override;
|
uint32_t timeout, bool verbose = false) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool prepare_flash_access() override {return load_bridge();}
|
bool prepare_flash_access() override;
|
||||||
bool post_flash_access() override {reset(); return true;}
|
bool post_flash_access() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -92,8 +100,8 @@ class Altera: public Device, SPIInterface {
|
||||||
void shiftVDR(uint8_t * tx, uint8_t * rx, uint32_t len,
|
void shiftVDR(uint8_t * tx, uint8_t * rx, uint32_t len,
|
||||||
int end_state = Jtag::UPDATE_DR, bool debug = false);
|
int end_state = Jtag::UPDATE_DR, bool debug = false);
|
||||||
|
|
||||||
SVF_jtag _svf;
|
|
||||||
std::string _device_package;
|
std::string _device_package;
|
||||||
|
std::string _spiOverJtagPath; /**< spiOverJtag explicit path */
|
||||||
uint32_t _vir_addr; /**< addr affected to virtual jtag */
|
uint32_t _vir_addr; /**< addr affected to virtual jtag */
|
||||||
uint32_t _vir_length; /**< length of virtual jtag IR */
|
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,
|
const std::string &file_type,
|
||||||
Device::prog_type_t prg_type, bool verify, int8_t verbose):
|
Device::prog_type_t prg_type, bool verify, int8_t verbose):
|
||||||
Device(jtag, filename, file_type, verify, 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) {
|
if (prg_type == Device::RD_FLASH) {
|
||||||
_mode = Device::READ_MODE;
|
_mode = Device::READ_MODE;
|
||||||
|
|
@ -64,11 +64,6 @@ void Anlogic::program(unsigned int offset, bool unprotect_flash)
|
||||||
if (_mode == Device::NONE_MODE)
|
if (_mode == Device::NONE_MODE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_file_extension == "svf") {
|
|
||||||
_svf.parse(_filename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnlogicBitParser bit(_filename, (_mode == Device::MEM_MODE), _verbose);
|
AnlogicBitParser bit(_filename, (_mode == Device::MEM_MODE), _verbose);
|
||||||
|
|
||||||
printInfo("Parse file ", false);
|
printInfo("Parse file ", false);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,13 @@ class Anlogic: public Device, SPIInterface {
|
||||||
return SPIInterface::unprotect_flash();
|
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
|
* \brief dump len byte from base_addr from SPI flash
|
||||||
* \param[in] base_addr: start offset
|
* \param[in] base_addr: start offset
|
||||||
|
|
@ -66,8 +73,6 @@ class Anlogic: public Device, SPIInterface {
|
||||||
*/
|
*/
|
||||||
virtual bool post_flash_access() override {reset(); return true;}
|
virtual bool post_flash_access() override {reset(); return true;}
|
||||||
|
|
||||||
private:
|
|
||||||
SVF_jtag _svf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_ANLOGIC_HPP_
|
#endif // SRC_ANLOGIC_HPP_
|
||||||
|
|
|
||||||
|
|
@ -107,11 +107,11 @@ int AnlogicBitParser::parse()
|
||||||
|
|
||||||
_bit_data.clear();
|
_bit_data.clear();
|
||||||
for (auto it = blocks.begin(); it != blocks.end(); it++) {
|
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)
|
if (_reverseOrder == true)
|
||||||
_bit_data += reverseByte(((*it)[pos]));
|
_bit_data += reverseByte(((*it)[xpos]));
|
||||||
else
|
else
|
||||||
_bit_data += ((*it)[pos]);
|
_bit_data += ((*it)[xpos]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_bit_length = _bit_data.size() * 8;
|
_bit_length = _bit_data.size() * 8;
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,8 @@ enum analogicCableFreq {
|
||||||
ANLOGICCABLE_FREQ_90K = 0xff
|
ANLOGICCABLE_FREQ_90K = 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
AnlogicCable::AnlogicCable(uint32_t clkHZ, uint8_t verbose):
|
AnlogicCable::AnlogicCable(uint32_t clkHZ):
|
||||||
_verbose(verbose),
|
dev_handle(NULL), usb_ctx(NULL)
|
||||||
dev_handle(NULL), usb_ctx(NULL), _tdi(0), _tms(0)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
class AnlogicCable : public JtagInterface {
|
class AnlogicCable : public JtagInterface {
|
||||||
public:
|
public:
|
||||||
AnlogicCable(uint32_t clkHZ, uint8_t verbose);
|
AnlogicCable(uint32_t clkHZ);
|
||||||
virtual ~AnlogicCable();
|
virtual ~AnlogicCable();
|
||||||
|
|
||||||
int setClkFreq(uint32_t clkHZ) override;
|
int setClkFreq(uint32_t clkHZ) override;
|
||||||
|
|
@ -43,13 +43,9 @@ class AnlogicCable : public JtagInterface {
|
||||||
int flush() override;
|
int flush() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _verbose;
|
|
||||||
|
|
||||||
int write(uint8_t *in_buf, uint8_t *out_buf, int len, int rd_len);
|
int write(uint8_t *in_buf, uint8_t *out_buf, int len, int rd_len);
|
||||||
|
|
||||||
libusb_device_handle *dev_handle;
|
libusb_device_handle *dev_handle;
|
||||||
libusb_context *usb_ctx;
|
libusb_context *usb_ctx;
|
||||||
uint8_t _tdi;
|
|
||||||
uint8_t _tms;
|
|
||||||
};
|
};
|
||||||
#endif // SRC_ANLOGICCABLE_HPP_
|
#endif // SRC_ANLOGICCABLE_HPP_
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ int BitParser::parseHeader()
|
||||||
int pos_data = 0;
|
int pos_data = 0;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
short length;
|
short length;
|
||||||
string tmp(64, ' ');
|
string tmp;
|
||||||
int pos, prev_pos;
|
int pos, prev_pos;
|
||||||
|
|
||||||
/* Field 1 : misc header */
|
/* Field 1 : misc header */
|
||||||
|
|
@ -109,10 +109,21 @@ int BitParser::parse()
|
||||||
/* process all field */
|
/* process all field */
|
||||||
int pos = parseHeader();
|
int pos = parseHeader();
|
||||||
|
|
||||||
/* rest of the file is data to send */
|
/* _bit_length is length of data to send */
|
||||||
_bit_data.resize(_raw_data.size() - pos);
|
int rest_of_file_length = _file_size - pos;
|
||||||
std::move(_raw_data.begin() + pos, _raw_data.end(), _bit_data.begin());
|
if (_bit_length < rest_of_file_length) {
|
||||||
_bit_length = _bit_data.size();
|
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) {
|
if (_reverseOrder) {
|
||||||
for (int i = 0; i < _bit_length; i++) {
|
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", "", "", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("colorlight-i5", "", "cmsisdap", 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", "", "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("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT),
|
JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT),
|
||||||
JTAG_BOARD("c10lp-refkit", "10cl055484", "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>
|
* Copyright (C) 2019 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CABLE_HPP
|
#ifndef SRC_CABLE_HPP_
|
||||||
#define CABLE_HPP
|
#define SRC_CABLE_HPP_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
#include "ftdipp_mpsse.hpp"
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief define type of communication
|
* \brief define type of communication
|
||||||
|
|
@ -19,51 +18,115 @@ enum communication_type {
|
||||||
MODE_CH552_JTAG, /*! ch552_jtag firmware */
|
MODE_CH552_JTAG, /*! ch552_jtag firmware */
|
||||||
MODE_FTDI_BITBANG, /*! used with ft232RL/ft231x */
|
MODE_FTDI_BITBANG, /*! used with ft232RL/ft231x */
|
||||||
MODE_FTDI_SERIAL, /*! ft2232, ft232H */
|
MODE_FTDI_SERIAL, /*! ft2232, ft232H */
|
||||||
|
MODE_JLINK, /*! ft2232, ft232H */
|
||||||
MODE_DIRTYJTAG, /*! JTAG probe firmware for STM32F1 */
|
MODE_DIRTYJTAG, /*! JTAG probe firmware for STM32F1 */
|
||||||
MODE_USBBLASTER, /*! JTAG probe firmware for USBBLASTER */
|
MODE_USBBLASTER, /*! JTAG probe firmware for USBBLASTER */
|
||||||
MODE_CMSISDAP, /*! CMSIS-DAP JTAG probe */
|
MODE_CMSISDAP, /*! CMSIS-DAP JTAG probe */
|
||||||
MODE_DFU, /*! DFU based 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 {
|
typedef struct {
|
||||||
int type;
|
int interface; /*! FTDI interface (A, B, C, D) */
|
||||||
FTDIpp_MPSSE::mpsse_bit_config config;
|
int bit_low_val; /*! xDBUS 0-7 default value */
|
||||||
} cable_t;
|
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 = {
|
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
|
// 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
|
// some cables requires explicit values on some of the I/Os
|
||||||
{"anlogicCable", {MODE_ANLOGICCABLE, {}}},
|
{"anlogicCable", CABLE_DEF(MODE_ANLOGICCABLE, 0x0547, 0x1002)},
|
||||||
{"arm-usb-ocd-h", {MODE_FTDI_SERIAL, {0x15ba, 0x002b, INTERFACE_A, 0x08, 0x1B, 0x09, 0x0B}}},
|
{"arm-usb-ocd-h", FTDI_SER(0x15ba, 0x002b, FTDI_INTF_A, 0x08, 0x1B, 0x09, 0x0B)},
|
||||||
{"bus_blaster", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x1B, 0x08, 0x0B}}},
|
{"bus_blaster", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x1B, 0x08, 0x0B)},
|
||||||
{"bus_blaster_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"bus_blaster_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"ch552_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"ch552_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"cmsisdap", {MODE_CMSISDAP, {0x0d28, 0x0204, 0, 0, 0, 0, 0 }}},
|
{"cmsisdap", CMSIS_CL(0x0d28, 0x0204 )},
|
||||||
{"gatemate_pgm", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x10, 0x9B, 0x14, 0x17}}},
|
{"gatemate_pgm", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x10, 0x9B, 0x14, 0x17)},
|
||||||
{"gatemate_evb_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x10, 0x1B, 0x00, 0x01}}},
|
{"gatemate_evb_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x10, 0x1B, 0x00, 0x01)},
|
||||||
{"gatemate_evb_spi", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x00, 0x1B, 0x00, 0x01}}},
|
{"gatemate_evb_spi", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x00, 0x1B, 0x00, 0x01)},
|
||||||
{"dfu", {MODE_DFU, {}}},
|
{"dfu", CABLE_DEF(MODE_DFU, 0, 0 )},
|
||||||
{"digilent", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
{"digilent", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||||
{"digilent_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0xe8, 0xeb, 0x00, 0x60}}},
|
{"digilent_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0xe8, 0xeb, 0x00, 0x60)},
|
||||||
{"digilent_hs2", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
{"digilent_hs2", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||||
{"digilent_hs3", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x88, 0x8B, 0x20, 0x30}}},
|
{"digilent_hs3", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x88, 0x8B, 0x20, 0x30)},
|
||||||
{"digilent_ad", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x80, 0x80}}},
|
{"digilent_ad", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x80, 0x80)},
|
||||||
{"dirtyJtag", {MODE_DIRTYJTAG, {}}},
|
{"dirtyJtag", CABLE_DEF(MODE_DIRTYJTAG, 0x1209, 0xC0CA )},
|
||||||
{"efinix_spi_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
|
{"efinix_spi_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
|
||||||
{"efinix_jtag_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_B, 0x08, 0x8B, 0x00, 0x00}}},
|
{"efinix_jtag_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_B, 0x08, 0x8B, 0x00, 0x00)},
|
||||||
{"efinix_spi_ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
|
{"efinix_spi_ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
|
||||||
{"ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"ft2232_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x00, 0x00}}},
|
{"ft2232_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x00, 0x00)},
|
||||||
{"ft231X", {MODE_FTDI_BITBANG, {0x0403, 0x6015, INTERFACE_A, 0x00, 0x00, 0x00, 0x00}}},
|
{"ft231X", FTDI_BB (0x0403, 0x6015, FTDI_INTF_A, 0x00, 0x00, 0x00, 0x00)},
|
||||||
{"ft232", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"ft232", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"ft232RL", {MODE_FTDI_BITBANG, {0x0403, 0x6001, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"ft232RL", FTDI_BB( 0x0403, 0x6001, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
|
{"ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
|
||||||
{"ecpix5-debug", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xF8, 0xFB, 0xFF, 0xFF}}},
|
{"ecpix5-debug", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xF8, 0xFB, 0xFF, 0xFF)},
|
||||||
{"jtag-smt2-nc", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
|
{"jlink", CABLE_DEF(MODE_JLINK, 0x1366, 0x0105 )},
|
||||||
{"orbtrace", {MODE_CMSISDAP, {0x1209, 0x3443, 0, 0, 0, 0, 0 }}},
|
{"jlink_base", CABLE_DEF(MODE_JLINK, 0x1366, 0x0101 )},
|
||||||
{"tigard", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x3B, 0x00, 0x00}}},
|
{"jtrace_pro", CABLE_DEF(MODE_JLINK, 0x1366, 0x1020 )},
|
||||||
{"usb-blaster", {MODE_USBBLASTER, {0x09Fb, 0x6001, 0, 0, 0, 0, 0 }}},
|
{"jtag-smt2-nc", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
|
||||||
{"usb-blasterII", {MODE_USBBLASTER, {0x09Fb, 0x6810, 0, 0, 0, 0, 0 }}},
|
{"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)
|
#define display(...) do {}while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CH552_jtag::CH552_jtag(const FTDIpp_MPSSE::mpsse_bit_config &cable,
|
CH552_jtag::CH552_jtag(const cable_t &cable,
|
||||||
string dev, const string &serial, uint32_t clkHZ, uint8_t verbose):
|
const string &dev, const string &serial, uint32_t clkHZ,
|
||||||
|
uint8_t verbose):
|
||||||
FTDIpp_MPSSE(cable, dev, serial, clkHZ, verbose), _to_read(0)
|
FTDIpp_MPSSE(cable, dev, serial, clkHZ, verbose), _to_read(0)
|
||||||
{
|
{
|
||||||
init_internal(cable);
|
init_internal(cable.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
CH552_jtag::~CH552_jtag()
|
CH552_jtag::~CH552_jtag()
|
||||||
|
|
@ -59,7 +60,7 @@ CH552_jtag::~CH552_jtag()
|
||||||
"Loopback failed, expect problems on later runs %d\n", read);
|
"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);
|
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 tx_buff_size = mpsse_get_buffer_size();
|
||||||
int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len
|
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_byte = real_len >> 3; // number of byte to send
|
||||||
int nb_bit = (real_len & 0x07); // residual bits
|
int nb_bit = (real_len & 0x07); // residual bits
|
||||||
int xfer = tx_buff_size - 7; // 2 byte for opcode and size 2 time
|
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;
|
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) {
|
if (nb_bit != 0) {
|
||||||
display("%s read/write %d bit\n", __func__, nb_bit);
|
display("%s read/write %d bit\n", __func__, nb_bit);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "cable.hpp"
|
||||||
#include "jtagInterface.hpp"
|
#include "jtagInterface.hpp"
|
||||||
#include "ftdipp_mpsse.hpp"
|
#include "ftdipp_mpsse.hpp"
|
||||||
|
|
||||||
|
|
@ -22,7 +23,7 @@
|
||||||
|
|
||||||
class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
|
class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
|
||||||
public:
|
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);
|
const std::string &serial, uint32_t clkHZ, uint8_t verbose = false);
|
||||||
virtual ~CH552_jtag();
|
virtual ~CH552_jtag();
|
||||||
|
|
||||||
|
|
@ -48,7 +49,7 @@ class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
|
||||||
int flush() override;
|
int flush() override;
|
||||||
|
|
||||||
private:
|
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 */
|
uint32_t _to_read; /*!< amount of byte to read */
|
||||||
};
|
};
|
||||||
#endif // SRC_CH552_JTAG_HPP_
|
#endif // SRC_CH552_JTAG_HPP_
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ enum cmsisdap_status {
|
||||||
DAP_ERROR = 0xff
|
DAP_ERROR = 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
|
CmsisDAP::CmsisDAP(const cable_t &cable, int index, uint8_t verbose):_verbose(verbose),
|
||||||
_device_idx(0), _vid(vid), _pid(pid),
|
_device_idx(0), _vid(cable.vid), _pid(cable.pid),
|
||||||
_serial_number(L""), _dev(NULL), _num_tms(0), _is_connect(false)
|
_serial_number(L""), _dev(NULL), _num_tms(0), _is_connect(false)
|
||||||
{
|
{
|
||||||
std::vector<struct hid_device_info *> dev_found;
|
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 this function return all;
|
||||||
* if vid/pid are >0 only one (or 0) device returned
|
* 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) {
|
for (cur_dev = devs; NULL != cur_dev; cur_dev = cur_dev->next) {
|
||||||
dev_found.push_back(cur_dev);
|
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");
|
throw std::runtime_error("No device found");
|
||||||
}
|
}
|
||||||
/* more than one device: can't continue without more information */
|
/* more than one device: can't continue without more information */
|
||||||
if (dev_found.size() > 1) {
|
if (dev_found.size() > 1 && index == -1) {
|
||||||
hid_exit();
|
hid_exit();
|
||||||
throw std::runtime_error(
|
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:");
|
printInfo("Found " + std::to_string(dev_found.size()) + " compatible device:");
|
||||||
for (size_t i = 0; i < dev_found.size(); i++) {
|
for (size_t i = 0; i < dev_found.size(); i++) {
|
||||||
char val[256];
|
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]->vendor_id,
|
||||||
dev_found[i]->product_id,
|
dev_found[i]->product_id,
|
||||||
|
dev_found[i]->interface_number,
|
||||||
dev_found[i]->product_string);
|
dev_found[i]->product_string);
|
||||||
printInfo(val);
|
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);
|
_serial_number = wstring(dev_found[_device_idx]->serial_number);
|
||||||
/* open the device */
|
/* open the device */
|
||||||
_dev = hid_open_path(dev_found[_device_idx]->path);
|
_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 */
|
/* cleanup enumeration */
|
||||||
hid_free_enumeration(devs);
|
hid_free_enumeration(devs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "cable.hpp"
|
||||||
#include "jtagInterface.hpp"
|
#include "jtagInterface.hpp"
|
||||||
|
|
||||||
class CmsisDAP: public JtagInterface {
|
class CmsisDAP: public JtagInterface {
|
||||||
public:
|
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
|
* else search for a compatible device
|
||||||
* \param[in] vid: vendor id
|
* \param[in] vid: vendor id
|
||||||
* \param[in] pid: product id
|
* \param[in] pid: product id
|
||||||
|
* \param[in] index: interface number
|
||||||
* \param[in] verbose: verbose level 0 normal, 1 verbose
|
* \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();
|
~CmsisDAP();
|
||||||
|
|
||||||
|
|
@ -77,13 +79,13 @@ class CmsisDAP: public JtagInterface {
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* \brief connect device in JTAG mode
|
* \brief connect device in JTAG mode
|
||||||
* \return 1 if success <= 0 otherwhise
|
* \return 1 if success <= 0 otherwise
|
||||||
*/
|
*/
|
||||||
int dapConnect();
|
int dapConnect();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief disconnect device
|
* \brief disconnect device
|
||||||
* \return 1 if success <= 0 otherwhise
|
* \return 1 if success <= 0 otherwise
|
||||||
*/
|
*/
|
||||||
int dapDisconnect();
|
int dapDisconnect();
|
||||||
int dapResetTarget();
|
int dapResetTarget();
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,15 @@
|
||||||
|
|
||||||
CologneChip::CologneChip(FtdiSpi *spi, const std::string &filename,
|
CologneChip::CologneChip(FtdiSpi *spi, const std::string &filename,
|
||||||
const std::string &file_type, Device::prog_type_t prg_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
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) :
|
bool verify, int8_t verbose) :
|
||||||
Device(NULL, filename, file_type, verify, verbose), _rstn_pin(rstn_pin),
|
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 = 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);
|
_spi->gpio_set_output(_rstn_pin | _oen_pin);
|
||||||
|
_ftdi_jtag = nullptr;
|
||||||
|
|
||||||
if (prg_type == Device::WR_SRAM) {
|
if (prg_type == Device::WR_SRAM) {
|
||||||
_mode = Device::MEM_MODE;
|
_mode = Device::MEM_MODE;
|
||||||
|
|
@ -34,6 +35,7 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
|
||||||
bool verify, int8_t verbose) :
|
bool verify, int8_t verbose) :
|
||||||
Device(jtag, filename, file_type, verify, verbose)
|
Device(jtag, filename, file_type, verify, verbose)
|
||||||
{
|
{
|
||||||
|
_spi = nullptr;
|
||||||
/* check which cable/board we're using in order to select pin definitions */
|
/* check which cable/board we're using in order to select pin definitions */
|
||||||
std::string spi_board_name;
|
std::string spi_board_name;
|
||||||
if (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 */
|
/* pin configurations valid for both evaluation board and programer */
|
||||||
_rstn_pin = spi_board->reset_pin;
|
_rstn_pin = spi_board->reset_pin;
|
||||||
_done_pin = spi_board->done_pin;
|
_done_pin = spi_board->done_pin;
|
||||||
_failn_pin = DBUS6;
|
_fail_pin = DBUS6;
|
||||||
_oen_pin = spi_board->oe_pin;
|
_oen_pin = spi_board->oe_pin;
|
||||||
|
|
||||||
/* cast _jtag->_jtag from JtagInterface to FtdiJtagMPSSE to access GPIO */
|
/* cast _jtag->_jtag from JtagInterface to FtdiJtagMPSSE to access GPIO */
|
||||||
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(_jtag->_jtag);
|
_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);
|
_ftdi_jtag->gpio_set_output(_rstn_pin | _oen_pin);
|
||||||
|
|
||||||
if (prg_type == Device::WR_SRAM) {
|
if (prg_type == Device::WR_SRAM) {
|
||||||
|
|
@ -72,7 +74,7 @@ void CologneChip::reset()
|
||||||
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
||||||
usleep(SLEEP_US);
|
usleep(SLEEP_US);
|
||||||
_spi->gpio_set(_rstn_pin);
|
_spi->gpio_set(_rstn_pin);
|
||||||
} else if (_ftdi_jtag) {
|
} else {
|
||||||
_ftdi_jtag->gpio_clear(_rstn_pin | _oen_pin);
|
_ftdi_jtag->gpio_clear(_rstn_pin | _oen_pin);
|
||||||
usleep(SLEEP_US);
|
usleep(SLEEP_US);
|
||||||
_ftdi_jtag->gpio_set(_rstn_pin);
|
_ftdi_jtag->gpio_set(_rstn_pin);
|
||||||
|
|
@ -80,24 +82,24 @@ void CologneChip::reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain CFG_DONE and ~CFG_FAILED signals. Configuration is successfull iff
|
* Obtain CFG_DONE and CFG_FAILED signals. Configuration is successful if
|
||||||
* CFG_DONE=true and ~CFG_FAILED=false.
|
* CFG_DONE=true and CFG_FAILED=false.
|
||||||
*/
|
*/
|
||||||
bool CologneChip::cfgDone()
|
bool CologneChip::cfgDone()
|
||||||
{
|
{
|
||||||
uint16_t status = 0;
|
uint16_t status = 0;
|
||||||
if (_spi) {
|
if (_spi) {
|
||||||
status = _spi->gpio_get(true);
|
status = _spi->gpio_get(true);
|
||||||
} else if (_ftdi_jtag) {
|
} else {
|
||||||
status = _ftdi_jtag->gpio_get(true);
|
status = _ftdi_jtag->gpio_get(true);
|
||||||
}
|
}
|
||||||
bool done = (status & _done_pin) > 0;
|
bool done = (status & _done_pin) > 0;
|
||||||
bool fail = (status & _failn_pin) == 0;
|
bool fail = (status & _fail_pin) > 0;
|
||||||
return (done && !fail);
|
return (done && !fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints information if configuration was successfull.
|
* Prints information if configuration was successful.
|
||||||
*/
|
*/
|
||||||
void CologneChip::waitCfgDone()
|
void CologneChip::waitCfgDone()
|
||||||
{
|
{
|
||||||
|
|
@ -118,13 +120,12 @@ void CologneChip::waitCfgDone()
|
||||||
/**
|
/**
|
||||||
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
|
* 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,
|
bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||||
uint32_t len)
|
|
||||||
{
|
{
|
||||||
if (_spi) {
|
if (_spi) {
|
||||||
/* enable output and hold reset */
|
/* enable output and hold reset */
|
||||||
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
_spi->gpio_clear(_rstn_pin | _oen_pin);
|
||||||
} else if (_ftdi_jtag) {
|
} else {
|
||||||
/* enable output and disable reset */
|
/* enable output and disable reset */
|
||||||
_ftdi_jtag->gpio_clear(_oen_pin);
|
_ftdi_jtag->gpio_clear(_oen_pin);
|
||||||
_ftdi_jtag->gpio_set(_rstn_pin);
|
_ftdi_jtag->gpio_set(_rstn_pin);
|
||||||
|
|
@ -137,12 +138,12 @@ bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
|
||||||
if (_spi) {
|
if (_spi) {
|
||||||
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false,
|
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false,
|
||||||
_verbose);
|
_verbose);
|
||||||
} else if (_ftdi_jtag) {
|
} else {
|
||||||
flash = new SPIFlash(this, false, _verbose);
|
flash = new SPIFlash(this, false, _verbose);
|
||||||
}
|
}
|
||||||
flash->reset();
|
flash->reset();
|
||||||
flash->power_up();
|
flash->power_up();
|
||||||
flash->dump(filename, base_addr, len);
|
flash->dump(_filename, base_addr, len);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
printError("Fail");
|
printError("Fail");
|
||||||
printError(std::string(e.what()));
|
printError(std::string(e.what()));
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class CologneChip: public Device, SPIInterface {
|
||||||
public:
|
public:
|
||||||
CologneChip(FtdiSpi *spi, const std::string &filename,
|
CologneChip(FtdiSpi *spi, const std::string &filename,
|
||||||
const std::string &file_type, Device::prog_type_t prg_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
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);
|
bool verify, int8_t verbose);
|
||||||
CologneChip(Jtag* jtag, const std::string &filename,
|
CologneChip(Jtag* jtag, const std::string &filename,
|
||||||
const std::string &file_type, Device::prog_type_t prg_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
|
|
@ -34,12 +34,14 @@ class CologneChip: public Device, SPIInterface {
|
||||||
|
|
||||||
bool cfgDone();
|
bool cfgDone();
|
||||||
void waitCfgDone();
|
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 {
|
virtual bool protect_flash(uint32_t len) override {
|
||||||
(void) len;
|
(void) len;
|
||||||
printError("protect flash not supported"); return false;}
|
printError("protect flash not supported"); return false;}
|
||||||
virtual bool unprotect_flash() override {
|
virtual bool unprotect_flash() override {
|
||||||
printError("unprotect flash not supported"); return false;}
|
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;
|
void program(unsigned int offset, bool unprotect_flash) override;
|
||||||
|
|
||||||
int idCode() override {return 0;}
|
int idCode() override {return 0;}
|
||||||
|
|
@ -64,7 +66,7 @@ class CologneChip: public Device, SPIInterface {
|
||||||
FtdiJtagMPSSE *_ftdi_jtag = NULL;
|
FtdiJtagMPSSE *_ftdi_jtag = NULL;
|
||||||
uint16_t _rstn_pin;
|
uint16_t _rstn_pin;
|
||||||
uint16_t _done_pin;
|
uint16_t _done_pin;
|
||||||
uint16_t _failn_pin;
|
uint16_t _fail_pin;
|
||||||
uint16_t _oen_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;
|
(void) mode;
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
uint32_t offset = filename.find_last_of(".");
|
size_t offset = filename.find_last_of(".");
|
||||||
|
|
||||||
FILE *_fd = fopen(filename.c_str(), "rb");
|
FILE *_fd = fopen(filename.c_str(), "rb");
|
||||||
if (!_fd) {
|
if (!_fd) {
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,13 @@ class Device {
|
||||||
printError("dump flash not supported"); return false;}
|
printError("dump flash not supported"); return false;}
|
||||||
virtual bool protect_flash(uint32_t len) = 0;
|
virtual bool protect_flash(uint32_t len) = 0;
|
||||||
virtual bool unprotect_flash() = 0;
|
virtual bool unprotect_flash() = 0;
|
||||||
|
virtual bool bulk_erase_flash() = 0;
|
||||||
|
|
||||||
virtual int idCode() = 0;
|
virtual int idCode() = 0;
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
|
||||||
|
virtual bool connectJtagToMCU() {return false;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Jtag *_jtag;
|
Jtag *_jtag;
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
|
|
|
||||||
87
src/dfu.cpp
87
src/dfu.cpp
|
|
@ -46,8 +46,8 @@ enum dfu_cmd {
|
||||||
* - index as jtag chain (fix issue when more than one device connected)
|
* - index as jtag chain (fix issue when more than one device connected)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
DFU::DFU(const string &filename, bool bypass_bitstream,
|
||||||
int16_t altsetting,
|
uint16_t vid, uint16_t pid, int16_t altsetting,
|
||||||
int verbose_lvl):_verbose(verbose_lvl > 0), _debug(verbose_lvl > 1),
|
int verbose_lvl):_verbose(verbose_lvl > 0), _debug(verbose_lvl > 1),
|
||||||
_quiet(verbose_lvl < 0), dev_idx(0), _vid(0), _pid(0),
|
_quiet(verbose_lvl < 0), dev_idx(0), _vid(0), _pid(0),
|
||||||
_altsetting(altsetting),
|
_altsetting(altsetting),
|
||||||
|
|
@ -55,10 +55,14 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
||||||
_bit(NULL)
|
_bit(NULL)
|
||||||
{
|
{
|
||||||
struct dfu_status status;
|
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);
|
||||||
|
|
||||||
|
if (bypass_bitstream) {
|
||||||
|
_bit = nullptr;
|
||||||
|
printInfo("bypassed");
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
_bit = new DFUFileParser(filename, _verbose > 0);
|
_bit = new DFUFileParser(filename, _verbose > 0);
|
||||||
printSuccess("DONE");
|
printSuccess("DONE");
|
||||||
|
|
@ -88,6 +92,7 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
printWarn(e.what());
|
printWarn(e.what());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (libusb_init(&usb_ctx) < 0) {
|
if (libusb_init(&usb_ctx) < 0) {
|
||||||
delete _bit;
|
delete _bit;
|
||||||
|
|
@ -128,12 +133,16 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
|
||||||
displayDFU();
|
displayDFU();
|
||||||
|
|
||||||
/* don't try device without vid/pid */
|
/* don't try device without vid/pid */
|
||||||
if (_vid == 0 || _pid == 0) {
|
if ((_vid == 0 || _pid == 0) && _bit) {
|
||||||
libusb_exit(usb_ctx);
|
libusb_exit(usb_ctx);
|
||||||
delete _bit;
|
delete _bit;
|
||||||
throw std::runtime_error("Can't open device vid/pid == 0");
|
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 */
|
/* open the first */
|
||||||
if (open_DFU(0) == EXIT_FAILURE) {
|
if (open_DFU(0) == EXIT_FAILURE) {
|
||||||
libusb_exit(usb_ctx);
|
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);
|
printf("%02x %02x\n", _vid, _pid);
|
||||||
|
|
||||||
char state = get_state();
|
|
||||||
if (_verbose > 0) {
|
if (_verbose > 0) {
|
||||||
printInfo("Default DFU status " + dfu_dev_state_val[state]);
|
if ((ret = get_status(&status)) < 0) {
|
||||||
get_status(&status);
|
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,6 +167,7 @@ DFU::~DFU()
|
||||||
{
|
{
|
||||||
close_DFU();
|
close_DFU();
|
||||||
libusb_exit(usb_ctx);
|
libusb_exit(usb_ctx);
|
||||||
|
if (_bit)
|
||||||
delete _bit;
|
delete _bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,6 +176,7 @@ DFU::~DFU()
|
||||||
int DFU::open_DFU(int index)
|
int DFU::open_DFU(int index)
|
||||||
{
|
{
|
||||||
struct dfu_dev curr_dfu;
|
struct dfu_dev curr_dfu;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (_vid == 0 || _pid == 0) {
|
if (_vid == 0 || _pid == 0) {
|
||||||
printError("Error: Can't open device without VID/PID");
|
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");
|
printError("Error: fail to open device");
|
||||||
return EXIT_FAILURE;
|
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);
|
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;
|
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_release_interface(dev_handle, curr_intf);
|
||||||
libusb_close(dev_handle);
|
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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,10 +319,11 @@ int DFU::searchDFUDevices()
|
||||||
|
|
||||||
int ret = libusb_open(usb_dev, &handle);
|
int ret = libusb_open(usb_dev, &handle);
|
||||||
if (ret == 0) {
|
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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
libusb_close(handle);
|
|
||||||
} else if (_debug) {
|
} else if (_debug) {
|
||||||
char mess[256];
|
char mess[256];
|
||||||
sprintf(mess,"Unable to open device: "
|
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.device = libusb_get_device_address(dev);
|
||||||
my_dev.bMaxPacketSize0 = desc->bMaxPacketSize0;
|
my_dev.bMaxPacketSize0 = desc->bMaxPacketSize0;
|
||||||
|
|
||||||
|
memset(my_dev.iProduct, 0, 128);
|
||||||
libusb_get_string_descriptor_ascii(handle, desc->iProduct,
|
libusb_get_string_descriptor_ascii(handle, desc->iProduct,
|
||||||
my_dev.iProduct, 128);
|
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,
|
libusb_get_string_descriptor_ascii(handle, intf->iInterface,
|
||||||
my_dev.iInterface, 128);
|
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));
|
int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path));
|
||||||
my_dev.path[r] = '\0';
|
my_dev.path[r] = '\0';
|
||||||
|
|
@ -433,9 +457,11 @@ int DFU::set_state(char newState)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct dfu_status status;
|
struct dfu_status status;
|
||||||
char curr_state = get_state();
|
if (get_status(&status) < 0)
|
||||||
while (curr_state != newState) {
|
return -1;
|
||||||
switch (curr_state) {
|
|
||||||
|
while (status.bState != newState) {
|
||||||
|
switch (status.bState) {
|
||||||
case STATE_appIDLE:
|
case STATE_appIDLE:
|
||||||
if (dfu_detach() == EXIT_FAILURE)
|
if (dfu_detach() == EXIT_FAILURE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -446,7 +472,6 @@ int DFU::set_state(char newState)
|
||||||
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
curr_state = status.bState;
|
|
||||||
break;
|
break;
|
||||||
case STATE_appDETACH:
|
case STATE_appDETACH:
|
||||||
if (newState == STATE_appIDLE) {
|
if (newState == STATE_appIDLE) {
|
||||||
|
|
@ -484,15 +509,14 @@ int DFU::set_state(char newState)
|
||||||
printError("Fails to send packet\n");
|
printError("Fails to send packet\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((ret = get_state()) < 0)
|
if (get_status(&status) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
/* not always true:
|
/* not always true:
|
||||||
* the newState may be the next one or another */
|
* the newState may be the next one or another */
|
||||||
if (ret != newState) {
|
if (status.bState != newState) {
|
||||||
printError(dfu_dev_state_val[ret]);
|
printError(dfu_dev_state_val[status.bState]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
curr_state = ret;
|
|
||||||
break;
|
break;
|
||||||
case STATE_dfuERROR:
|
case STATE_dfuERROR:
|
||||||
if (newState == STATE_appIDLE) {
|
if (newState == STATE_appIDLE) {
|
||||||
|
|
@ -520,7 +544,6 @@ int DFU::set_state(char newState)
|
||||||
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
cerr << dfu_dev_status_val[status.bStatus] << endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
curr_state = status.bState;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -550,6 +573,10 @@ int DFU::get_status(struct dfu_status *status)
|
||||||
(((uint32_t)buffer[1] & 0xff) << 0);
|
(((uint32_t)buffer[1] & 0xff) << 0);
|
||||||
status->bState = buffer[4];
|
status->bState = buffer[4];
|
||||||
status->iString = buffer[5];
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -657,6 +684,10 @@ int DFU::download()
|
||||||
printError("Error: No device. Can't download file");
|
printError("Error: No device. Can't download file");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!_bit) {
|
||||||
|
printError("Error: No bitstream. Stop");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ret, ret_val = EXIT_SUCCESS;
|
int ret, ret_val = EXIT_SUCCESS;
|
||||||
uint8_t *buffer, *ptr;
|
uint8_t *buffer, *ptr;
|
||||||
|
|
@ -673,7 +704,9 @@ int DFU::download()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* download must start in dfu IDLE state */
|
/* 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);
|
set_state(STATE_dfuIDLE);
|
||||||
|
|
||||||
xfer_len = libusb_le16_to_cpu(curr_dev.dfu_desc.wTransferSize);
|
xfer_len = libusb_le16_to_cpu(curr_dev.dfu_desc.wTransferSize);
|
||||||
|
|
@ -733,12 +766,16 @@ int DFU::download()
|
||||||
/* send the zero sized download request
|
/* send the zero sized download request
|
||||||
* dfuDNLOAD_IDLE -> dfuMANITEST-SYNC
|
* 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) {
|
if (ret < 0) {
|
||||||
printError("Error: fail to change state " + to_string(ret));
|
printError("Error: fail to change state " + to_string(ret));
|
||||||
return -6;
|
return -6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printSuccess("DONE");
|
||||||
|
|
||||||
/* Now FSM must be in dfuMANITEST-SYNC */
|
/* Now FSM must be in dfuMANITEST-SYNC */
|
||||||
bool must_continue = true;
|
bool must_continue = true;
|
||||||
do {
|
do {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ class DFU {
|
||||||
* \param[in] altsetting: device altsetting to use
|
* \param[in] altsetting: device altsetting to use
|
||||||
* \param[in] verbose_lvl: verbose level 0 normal, -1 quiet, 1 verbose
|
* \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);
|
int16_t altsetting, int verbose_lvl);
|
||||||
|
|
||||||
~DFU();
|
~DFU();
|
||||||
|
|
@ -234,7 +235,7 @@ class DFU {
|
||||||
int dev_idx; /**< device index in dfu_dev */
|
int dev_idx; /**< device index in dfu_dev */
|
||||||
uint16_t _vid; /**< device Vendor ID */
|
uint16_t _vid; /**< device Vendor ID */
|
||||||
uint16_t _pid; /**< device Product ID */
|
uint16_t _pid; /**< device Product ID */
|
||||||
int16_t _altsetting; /**< device altesetting */
|
int16_t _altsetting; /**< device altsetting */
|
||||||
struct libusb_context *usb_ctx; /**< usb context */
|
struct libusb_context *usb_ctx; /**< usb context */
|
||||||
libusb_device_handle * dev_handle; /**< current device handle */
|
libusb_device_handle * dev_handle; /**< current device handle */
|
||||||
int curr_intf; /**< device interface to use */
|
int curr_intf; /**< device interface to use */
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ class DFUFileParser: public ConfigBitstreamParser {
|
||||||
DFUFileParser(const std::string &filename, bool verbose);
|
DFUFileParser(const std::string &filename, bool verbose);
|
||||||
/*!
|
/*!
|
||||||
* \brief read full content of the file, fill the buffer
|
* \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;
|
int parse() override;
|
||||||
/*!
|
/*!
|
||||||
* \brief read DFU suffix content of the file, fill _hdr structure
|
* \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();
|
int parseHeader();
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ using namespace std;
|
||||||
#define DIRTYJTAG_WRITE_EP 0x01
|
#define DIRTYJTAG_WRITE_EP 0x01
|
||||||
#define DIRTYJTAG_READ_EP 0x82
|
#define DIRTYJTAG_READ_EP 0x82
|
||||||
|
|
||||||
|
#define DIRTYJTAG_TIMEOUT 1000
|
||||||
|
|
||||||
enum dirtyJtagCmd {
|
enum dirtyJtagCmd {
|
||||||
CMD_STOP = 0x00,
|
CMD_STOP = 0x00,
|
||||||
|
|
@ -44,7 +45,7 @@ enum CommandModifier {
|
||||||
|
|
||||||
struct version_specific
|
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
|
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;
|
_version = 0;
|
||||||
getVersion();
|
if (!getVersion())
|
||||||
|
throw std::runtime_error("Fail to get version");
|
||||||
|
|
||||||
if (setClkFreq(clkHZ) < 0) {
|
if (setClkFreq(clkHZ) < 0) {
|
||||||
cerr << "Fail to set frequency" << endl;
|
cerr << "Fail to set frequency" << endl;
|
||||||
|
|
@ -103,7 +105,7 @@ DirtyJtag::~DirtyJtag()
|
||||||
libusb_exit(usb_ctx);
|
libusb_exit(usb_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirtyJtag::getVersion()
|
bool DirtyJtag::getVersion()
|
||||||
{
|
{
|
||||||
int actual_length;
|
int actual_length;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -111,17 +113,17 @@ void DirtyJtag::getVersion()
|
||||||
CMD_STOP};
|
CMD_STOP};
|
||||||
uint8_t rx_buf[64];
|
uint8_t rx_buf[64];
|
||||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||||
buf, 2, &actual_length, 1000);
|
buf, 2, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cerr << "getVersion: usb bulk write failed " << ret << endl;
|
cerr << "getVersion: usb bulk write failed " << ret << endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
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) {
|
if (ret < 0) {
|
||||||
cerr << "getVersion: read: usb bulk read failed " << ret << endl;
|
cerr << "getVersion: read: usb bulk read failed " << ret << endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
} while (actual_length == 0);
|
} while (actual_length == 0);
|
||||||
if (!strncmp("DJTAG1\n", (char*)rx_buf, 7)) {
|
if (!strncmp("DJTAG1\n", (char*)rx_buf, 7)) {
|
||||||
|
|
@ -134,6 +136,8 @@ void DirtyJtag::getVersion()
|
||||||
cerr << "dirtyJtag version unknown" << endl;
|
cerr << "dirtyJtag version unknown" << endl;
|
||||||
_version = 0;
|
_version = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -158,7 +162,7 @@ int DirtyJtag::setClkFreq(uint32_t clkHZ)
|
||||||
static_cast<uint8_t>(0xff & ((clkHZ / 1000) )),
|
static_cast<uint8_t>(0xff & ((clkHZ / 1000) )),
|
||||||
CMD_STOP};
|
CMD_STOP};
|
||||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||||
buf, 4, &actual_length, 1000);
|
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cerr << "setClkFreq: usb bulk write failed " << ret << endl;
|
cerr << "setClkFreq: usb bulk write failed " << ret << endl;
|
||||||
return -EXIT_FAILURE;
|
return -EXIT_FAILURE;
|
||||||
|
|
@ -197,7 +201,8 @@ int DirtyJtag::writeTMS(uint8_t *tms, uint32_t len, bool flush_buffer)
|
||||||
}
|
}
|
||||||
buf[buffer_idx++] = CMD_STOP;
|
buf[buffer_idx++] = CMD_STOP;
|
||||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
cerr << "writeTMS: usb bulk write failed " << ret << endl;
|
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;
|
buf[2] = (clk_len > 64) ? 64 : (uint8_t)clk_len;
|
||||||
|
|
||||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||||
buf, 4, &actual_length, 1000);
|
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cerr << "toggleClk: usb bulk write failed " << ret << endl;
|
cerr << "toggleClk: usb bulk write failed " << ret << endl;
|
||||||
return -EXIT_FAILURE;
|
return -EXIT_FAILURE;
|
||||||
|
|
@ -240,16 +245,16 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
||||||
{
|
{
|
||||||
int actual_length;
|
int actual_length;
|
||||||
uint32_t real_bit_len = len - (end ? 1 : 0);
|
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_buf[512], rx_buf[512];
|
||||||
uint8_t *tx_ptr, *rx_ptr = rx;
|
uint8_t *tx_ptr, *rx_ptr = rx;
|
||||||
|
|
||||||
if (tx)
|
if (tx)
|
||||||
memcpy(tx_cpy, tx, real_byte_len);
|
memcpy(tx_cpy, tx, kRealByteLen);
|
||||||
else
|
else
|
||||||
memset(tx_cpy, 0, real_byte_len);
|
memset(tx_cpy, 0, kRealByteLen);
|
||||||
tx_ptr = tx_cpy;
|
tx_ptr = tx_cpy;
|
||||||
|
|
||||||
tx_buf[0] = CMD_XFER | (rx ? 0 : v_options[_version].no_read);
|
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;
|
actual_length = 0;
|
||||||
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
||||||
(unsigned char *)tx_buf, (byte_to_send + header_offset),
|
(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))) {
|
if ((ret < 0) || (actual_length != (int)(byte_to_send + header_offset))) {
|
||||||
cerr << "writeTDI: fill: usb bulk write failed " << ret <<
|
cerr << "writeTDI: fill: usb bulk write failed " << ret <<
|
||||||
"actual length: " << actual_length << endl;
|
"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;
|
int transfer_length = (bit_to_send > 255) ? byte_to_send :32;
|
||||||
do {
|
do {
|
||||||
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
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) {
|
if (ret < 0) {
|
||||||
cerr << "writeTDI: read: usb bulk read failed " << ret << endl;
|
cerr << "writeTDI: read: usb bulk read failed " << ret << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
@ -338,7 +343,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
||||||
CMD_STOP,
|
CMD_STOP,
|
||||||
};
|
};
|
||||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
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;
|
cerr << "writeTDI: last bit error: usb bulk write failed 1" << endl;
|
||||||
return -EXIT_FAILURE;
|
return -EXIT_FAILURE;
|
||||||
|
|
@ -346,7 +352,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
|
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;
|
cerr << "writeTDI: last bit error: usb bulk read failed" << endl;
|
||||||
return -EXIT_FAILURE;
|
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[2] &= ~SIG_TCK;
|
||||||
buf[3] = CMD_STOP;
|
buf[3] = CMD_STOP;
|
||||||
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
|
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;
|
cerr << "writeTDI: last bit error: usb bulk write failed 2" << endl;
|
||||||
return -EXIT_FAILURE;
|
return -EXIT_FAILURE;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class DirtyJtag : public JtagInterface {
|
||||||
uint8_t _verbose;
|
uint8_t _verbose;
|
||||||
|
|
||||||
int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last);
|
int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last);
|
||||||
void getVersion();
|
bool getVersion();
|
||||||
|
|
||||||
libusb_device_handle *dev_handle;
|
libusb_device_handle *dev_handle;
|
||||||
libusb_context *usb_ctx;
|
libusb_context *usb_ctx;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#define KCYN "\x1B[36m"
|
#define KCYN "\x1B[36m"
|
||||||
#define KWHT "\x1B[37m"
|
#define KWHT "\x1B[37m"
|
||||||
|
|
||||||
void printError(std::string err, bool eol)
|
void printError(const std::string &err, bool eol)
|
||||||
{
|
{
|
||||||
if (isatty(STDERR_FILENO))
|
if (isatty(STDERR_FILENO))
|
||||||
std::cerr << KRED << err << "\e[0m";
|
std::cerr << KRED << err << "\e[0m";
|
||||||
|
|
@ -31,7 +31,7 @@ void printError(std::string err, bool eol)
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printWarn(std::string warn, bool eol)
|
void printWarn(const std::string &warn, bool eol)
|
||||||
{
|
{
|
||||||
if (isatty(STDOUT_FILENO))
|
if (isatty(STDOUT_FILENO))
|
||||||
std::cout << KYEL << warn << "\e[0m" << std::flush;
|
std::cout << KYEL << warn << "\e[0m" << std::flush;
|
||||||
|
|
@ -42,7 +42,7 @@ void printWarn(std::string warn, bool eol)
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printInfo(std::string info, bool eol)
|
void printInfo(const std::string &info, bool eol)
|
||||||
{
|
{
|
||||||
if (isatty(STDOUT_FILENO))
|
if (isatty(STDOUT_FILENO))
|
||||||
std::cout << KBLUL << info << "\e[0m" << std::flush;
|
std::cout << KBLUL << info << "\e[0m" << std::flush;
|
||||||
|
|
@ -53,7 +53,7 @@ void printInfo(std::string info, bool eol)
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSuccess(std::string success, bool eol)
|
void printSuccess(const std::string &success, bool eol)
|
||||||
{
|
{
|
||||||
if (isatty(STDOUT_FILENO))
|
if (isatty(STDOUT_FILENO))
|
||||||
std::cout << KGRN << success << "\e[0m" << std::flush;
|
std::cout << KGRN << success << "\e[0m" << std::flush;
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
void printError(std::string err, bool eol = true);
|
void printError(const std::string &err, bool eol = true);
|
||||||
void printWarn(std::string warn, bool eol = true);
|
void printWarn(const std::string &warn, bool eol = true);
|
||||||
void printInfo(std::string info, bool eol = true);
|
void printInfo(const std::string &info, bool eol = true);
|
||||||
void printSuccess(std::string success, bool eol = true);
|
void printSuccess(const std::string &success, bool eol = true);
|
||||||
|
|
||||||
#endif // DISPLAY_HPP_
|
#endif // DISPLAY_HPP_
|
||||||
|
|
|
||||||
326
src/efinix.cpp
326
src/efinix.cpp
|
|
@ -9,16 +9,22 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "device.hpp"
|
||||||
#include "display.hpp"
|
#include "display.hpp"
|
||||||
#include "efinixHexParser.hpp"
|
#include "efinixHexParser.hpp"
|
||||||
#include "ftdispi.hpp"
|
|
||||||
#include "device.hpp"
|
|
||||||
#include "ftdiJtagMPSSE.hpp"
|
#include "ftdiJtagMPSSE.hpp"
|
||||||
|
#include "ftdispi.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
|
#include "part.hpp"
|
||||||
#include "progressBar.hpp"
|
#include "progressBar.hpp"
|
||||||
#include "rawParser.hpp"
|
#include "rawParser.hpp"
|
||||||
|
#if defined (_WIN64) || defined (_WIN32)
|
||||||
|
#include "pathHelper.hpp"
|
||||||
|
#endif
|
||||||
#include "spiFlash.hpp"
|
#include "spiFlash.hpp"
|
||||||
|
|
||||||
Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
|
Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
|
||||||
|
|
@ -27,21 +33,47 @@ Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
|
||||||
uint16_t oe_pin,
|
uint16_t oe_pin,
|
||||||
bool verify, int8_t verbose):
|
bool verify, int8_t verbose):
|
||||||
Device(NULL, filename, file_type, verify, verbose), _ftdi_jtag(NULL),
|
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 = spi;
|
||||||
_spi->gpio_set_input(_done_pin);
|
init_common(Device::WR_FLASH);
|
||||||
_spi->gpio_set_output(_rst_pin | _oe_pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Efinix::Efinix(Jtag* jtag, const std::string &filename,
|
Efinix::Efinix(Jtag* jtag, const std::string &filename,
|
||||||
const std::string &file_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
const std::string &board_name,
|
const std::string &board_name, const std::string &device_package,
|
||||||
bool verify, int8_t verbose):
|
const std::string &spiOverJtagPath, bool verify, int8_t verbose):
|
||||||
Device(jtag, filename, file_type, verify, 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),
|
_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
|
/* WA: before using JTAG, device must restart with cs low
|
||||||
* but cs and rst for xyloni are connected to interfaceA (ie SPI)
|
* but cs and rst for xyloni are connected to interfaceA (ie SPI)
|
||||||
* TODO: some boards have cs, reset and done in both interface
|
* 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") {
|
} else if (board_name == "titanium_ti60_f225_jtag") {
|
||||||
spi_board_name = "titanium_ti60_f225";
|
spi_board_name = "titanium_ti60_f225";
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Error: unknown board name");
|
init_common(prg_type);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2: retrieve spi board */
|
/* 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 */
|
/* 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) */
|
/* 4: get pinout (cs, oe, rst) */
|
||||||
_cs_pin = spi_board->spi_pins_config.cs_pin;
|
_cs_pin = spi_board->spi_pins_config.cs_pin;
|
||||||
_rst_pin = spi_board->reset_pin;
|
_rst_pin = spi_board->reset_pin;
|
||||||
_oe_pin = spi_board->oe_pin;
|
_oe_pin = spi_board->oe_pin;
|
||||||
|
_done_pin = spi_board->done_pin;
|
||||||
|
|
||||||
/* 5: open SPI interface */
|
/* 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);
|
jtag->getClkFreq(), verbose > 0);
|
||||||
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(jtag);
|
|
||||||
|
|
||||||
/* 6: configure pins direction and default state */
|
/* 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()
|
Efinix::~Efinix()
|
||||||
{}
|
{
|
||||||
|
if (_jtag && _spi)
|
||||||
|
delete _spi;
|
||||||
|
}
|
||||||
|
|
||||||
void Efinix::reset()
|
void Efinix::reset()
|
||||||
{
|
{
|
||||||
if (_ftdi_jtag) // not supported
|
if (!_spi) {
|
||||||
|
printError("jtag: reset not supported");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
uint32_t timeout = 1000;
|
uint32_t timeout = 1000;
|
||||||
_spi->gpio_clear(_rst_pin | _oe_pin);
|
_spi->gpio_clear(_rst_pin | _oe_pin);
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
_spi->gpio_set(_rst_pin | _oe_pin);
|
_spi->gpio_set(_rst_pin | _oe_pin);
|
||||||
|
|
||||||
printInfo("Reset ", false);
|
printInfo("Reset ", false);
|
||||||
do {
|
do {
|
||||||
timeout--;
|
timeout--;
|
||||||
usleep(12000);
|
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)
|
if (timeout == 0)
|
||||||
printError("FAIL");
|
printError("FAIL");
|
||||||
else
|
else
|
||||||
|
|
@ -105,13 +168,15 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
|
||||||
{
|
{
|
||||||
if (_file_extension.empty())
|
if (_file_extension.empty())
|
||||||
return;
|
return;
|
||||||
|
if (_mode == Device::NONE_MODE)
|
||||||
|
return;
|
||||||
|
|
||||||
ConfigBitstreamParser *bit;
|
ConfigBitstreamParser *bit;
|
||||||
try {
|
try {
|
||||||
if (_file_extension == "hex") {
|
if (_file_extension == "hex" || _file_extension == "bit") {
|
||||||
bit = new EfinixHexParser(_filename, _verbose);
|
bit = new EfinixHexParser(_filename);
|
||||||
} else {
|
} else {
|
||||||
if (offset == 0) {
|
if (offset == 0 && _spi) {
|
||||||
printError("Error: can't write raw data at the beginning of the flash");
|
printError("Error: can't write raw data at the beginning of the flash");
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
@ -131,21 +196,37 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *data = bit->getData();
|
const uint8_t *data = bit->getData();
|
||||||
int length = bit->getLength() / 8;
|
const int length = bit->getLength() / 8;
|
||||||
|
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
bit->displayHeader();
|
bit->displayHeader();
|
||||||
|
|
||||||
if (_ftdi_jtag)
|
switch (_mode) {
|
||||||
|
case MEM_MODE:
|
||||||
programJTAG(data, length);
|
programJTAG(data, length);
|
||||||
|
break;
|
||||||
|
case FLASH_MODE:
|
||||||
|
if (_jtag)
|
||||||
|
SPIInterface::write(offset, const_cast<uint8_t *>(data),
|
||||||
|
length, unprotect_flash);
|
||||||
else
|
else
|
||||||
programSPI(offset, data, length, unprotect_flash);
|
programSPI(offset, data, length, unprotect_flash);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Efinix::dumpFlash(const std::string &filename,
|
bool Efinix::dumpFlash(uint32_t base_addr, uint32_t len)
|
||||||
uint32_t base_addr, uint32_t len)
|
|
||||||
{
|
{
|
||||||
|
if (!_spi) {
|
||||||
|
printError("jtag: dumpFlash not supported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t timeout = 1000;
|
uint32_t timeout = 1000;
|
||||||
_spi->gpio_clear(_rst_pin);
|
_spi->gpio_clear(_rst_pin);
|
||||||
|
|
||||||
|
|
@ -155,7 +236,7 @@ bool Efinix::dumpFlash(const std::string &filename,
|
||||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
|
||||||
flash.reset();
|
flash.reset();
|
||||||
flash.power_up();
|
flash.power_up();
|
||||||
flash.dump(filename, base_addr, len);
|
flash.dump(_filename, base_addr, len);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
printError("Fail");
|
printError("Fail");
|
||||||
printError(std::string(e.what()));
|
printError(std::string(e.what()));
|
||||||
|
|
@ -179,11 +260,9 @@ bool Efinix::dumpFlash(const std::string &filename,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
void Efinix::programSPI(unsigned int offset, const uint8_t *data,
|
||||||
bool unprotect_flash)
|
const int length, const bool unprotect_flash)
|
||||||
{
|
{
|
||||||
uint32_t timeout = 1000;
|
|
||||||
|
|
||||||
_spi->gpio_clear(_rst_pin | _oe_pin);
|
_spi->gpio_clear(_rst_pin | _oe_pin);
|
||||||
|
|
||||||
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
|
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());
|
printf("%02x\n", flash.read_status_reg());
|
||||||
flash.read_id();
|
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 */
|
/* verify write if required */
|
||||||
if (_verify)
|
if (_verify)
|
||||||
flash.verify(offset, data, length);
|
flash.verify(offset, data, length);
|
||||||
|
|
||||||
_spi->gpio_set(_rst_pin | _oe_pin);
|
reset();
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAMPLE_PRELOAD 0x02
|
#define SAMPLE_PRELOAD 0x02
|
||||||
|
|
@ -219,13 +287,17 @@ void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
|
||||||
#define IDCODE 0x03
|
#define IDCODE 0x03
|
||||||
#define PROGRAM 0x04
|
#define PROGRAM 0x04
|
||||||
#define ENTERUSER 0x07
|
#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;
|
int xfer_len = 512, tx_end;
|
||||||
uint8_t tx[512];
|
uint8_t tx[512];
|
||||||
|
|
||||||
|
if (_fpga_family == TITANIUM_FAMILY)
|
||||||
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
|
|
||||||
|
if(_spi) {
|
||||||
/* trion has to be reseted with cs low */
|
/* trion has to be reseted with cs low */
|
||||||
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
|
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
|
||||||
usleep(30000);
|
usleep(30000);
|
||||||
|
|
@ -233,7 +305,10 @@ void Efinix::programJTAG(uint8_t *data, int length)
|
||||||
usleep(50000);
|
usleep(50000);
|
||||||
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
|
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
|
||||||
usleep(50000);
|
usleep(50000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fpga_family == TITANIUM_FAMILY)
|
||||||
|
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
|
||||||
/* force run_test_idle state */
|
/* force run_test_idle state */
|
||||||
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
_jtag->set_state(Jtag::RUN_TEST_IDLE);
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
|
|
@ -241,8 +316,8 @@ void Efinix::programJTAG(uint8_t *data, int length)
|
||||||
/* send PROGRAM state and stay in SHIFT_DR until
|
/* send PROGRAM state and stay in SHIFT_DR until
|
||||||
* full configuration data has been sent
|
* full configuration data has been sent
|
||||||
*/
|
*/
|
||||||
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR);
|
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR);
|
||||||
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR); // T20 fix
|
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR); // T20 fix
|
||||||
|
|
||||||
ProgressBar progress("Load SRAM", length, 50, _quiet);
|
ProgressBar progress("Load SRAM", length, 50, _quiet);
|
||||||
|
|
||||||
|
|
@ -264,9 +339,160 @@ void Efinix::programJTAG(uint8_t *data, int length)
|
||||||
|
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
|
||||||
_jtag->shiftIR(ENTERUSER, IRLENGTH, Jtag::EXIT1_IR);
|
_jtag->shiftIR(ENTERUSER, _irlen, Jtag::EXIT1_IR);
|
||||||
|
|
||||||
memset(tx, 0, 512);
|
memset(tx, 0, 512);
|
||||||
_jtag->shiftDR(tx, NULL, 100);
|
_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
|
// 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_
|
#ifndef SRC_EFINIX_HPP_
|
||||||
|
|
@ -12,41 +12,64 @@
|
||||||
#include "ftdiJtagMPSSE.hpp"
|
#include "ftdiJtagMPSSE.hpp"
|
||||||
#include "ftdispi.hpp"
|
#include "ftdispi.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
|
#include "spiInterface.hpp"
|
||||||
|
|
||||||
class Efinix: public Device {
|
class Efinix: public Device, SPIInterface {
|
||||||
public:
|
public:
|
||||||
Efinix(FtdiSpi *spi, const std::string &filename,
|
Efinix(FtdiSpi *spi, const std::string &filename,
|
||||||
const std::string &file_type,
|
const std::string &file_type,
|
||||||
uint16_t rst_pin, uint16_t done_pin, uint16_t oe_pin,
|
uint16_t rst_pin, uint16_t done_pin, uint16_t oe_pin,
|
||||||
bool verify, int8_t verbose);
|
bool verify, int8_t verbose);
|
||||||
Efinix(Jtag* jtag, const std::string &filename,
|
Efinix(Jtag* jtag, const std::string &filename,
|
||||||
const std::string &file_type,
|
const std::string &file_type, Device::prog_type_t prg_type,
|
||||||
const std::string &board_name,
|
const std::string &board_name, const std::string &device_package,
|
||||||
|
const std::string &spiOverJtagPath,
|
||||||
bool verify, int8_t verbose);
|
bool verify, int8_t verbose);
|
||||||
~Efinix();
|
~Efinix();
|
||||||
|
|
||||||
void program(unsigned int offset, bool unprotect_flash) override;
|
void program(unsigned int offset, bool unprotect_flash) override;
|
||||||
bool dumpFlash(const std::string &filename,
|
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
|
||||||
uint32_t base_addr, uint32_t len);
|
bool protect_flash(uint32_t len) override {
|
||||||
virtual bool protect_flash(uint32_t len) override {
|
|
||||||
(void) len;
|
(void) len;
|
||||||
printError("protect flash not supported"); return false;}
|
printError("protect flash not supported"); return false;}
|
||||||
virtual bool unprotect_flash() override {
|
bool unprotect_flash() override {
|
||||||
printError("unprotect flash not supported"); return false;}
|
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 */
|
/* not supported in SPI Active mode */
|
||||||
int idCode() override {return 0;}
|
int idCode() override {return 0;}
|
||||||
void reset() override;
|
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:
|
private:
|
||||||
void programSPI(unsigned int offset, uint8_t *data, int length,
|
/* list of efinix family devices */
|
||||||
bool unprotect_flash);
|
enum efinix_family_t {
|
||||||
void programJTAG(uint8_t *data, int length);
|
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;
|
FtdiSpi *_spi;
|
||||||
FtdiJtagMPSSE *_ftdi_jtag;
|
FtdiJtagMPSSE *_ftdi_jtag;
|
||||||
uint16_t _rst_pin;
|
uint16_t _rst_pin;
|
||||||
uint16_t _done_pin;
|
uint16_t _done_pin;
|
||||||
uint16_t _cs_pin;
|
uint16_t _cs_pin;
|
||||||
uint16_t _oe_pin;
|
uint16_t _oe_pin;
|
||||||
|
efinix_family_t _fpga_family;
|
||||||
|
int _irlen;
|
||||||
|
std::string _device_package;
|
||||||
|
std::string _spiOverJtagPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_EFINIX_HPP_
|
#endif // SRC_EFINIX_HPP_
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
EfinixHexParser::EfinixHexParser(const string &filename, bool reverseOrder):
|
EfinixHexParser::EfinixHexParser(const string &filename):
|
||||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE,
|
ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE,
|
||||||
false), _reverseOrder(reverseOrder)
|
false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int EfinixHexParser::parse()
|
int EfinixHexParser::parse()
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,13 @@ class EfinixHexParser: public ConfigBitstreamParser {
|
||||||
/*!
|
/*!
|
||||||
* \brief constructor
|
* \brief constructor
|
||||||
* \param[in] filename: raw file to read
|
* \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
|
* \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;
|
int parse() override;
|
||||||
|
|
||||||
private:
|
|
||||||
bool _reverseOrder; /*!< tail if byte must be reversed */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_EFINIXHEXPARSER_HPP_
|
#endif // SRC_EFINIXHEXPARSER_HPP_
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
#ifndef SRC_EPCQ_HPP_
|
#ifndef SRC_EPCQ_HPP_
|
||||||
#define SRC_EPCQ_HPP_
|
#define SRC_EPCQ_HPP_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "spiInterface.hpp"
|
#include "spiInterface.hpp"
|
||||||
#include "spiFlash.hpp"
|
#include "spiFlash.hpp"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ int EPCQ::erase_sector(char start_sector, char nb_sectors)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
* 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);
|
nb_read = fread(rd_buffer, 1, 256, fd);
|
||||||
if (nb_read == 0) {
|
if (nb_read == 0) {
|
||||||
printf("problem dans le read du fichier source\n");
|
printf("problem reading the source file\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buffer[1] = (offset >> 16) & 0xff;
|
buffer[1] = (offset >> 16) & 0xff;
|
||||||
|
|
@ -262,14 +262,14 @@ void EPCQ::read_id()
|
||||||
_spi->spi_put(0x9F, NULL, rx_buf, 3);
|
_spi->spi_put(0x9F, NULL, rx_buf, 3);
|
||||||
_device_id = rx_buf[2];
|
_device_id = rx_buf[2];
|
||||||
if (_verbose)
|
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 */
|
/* read EPCQ silicon id */
|
||||||
//tx_buf[0] = 0xAB;
|
//tx_buf[0] = 0xAB;
|
||||||
/* 3 dummy_byte + 1 byte*/
|
/* 3 dummy_byte + 1 byte*/
|
||||||
_spi->spi_put(0xAB, NULL, rx_buf, 4);
|
_spi->spi_put(0xAB, NULL, rx_buf, 4);
|
||||||
_silicon_id = rx_buf[3];
|
_silicon_id = rx_buf[3];
|
||||||
if (_verbose)
|
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)
|
EPCQ::EPCQ(SPIInterface *spi, int8_t verbose):SPIFlash(spi, verbose)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class EPCQ: public SPIFlash {
|
||||||
|
|
||||||
void read_id() override;
|
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);
|
//int erase_sector(char start_sector, char nb_sectors);
|
||||||
//void dumpflash(char *dest_file, int size);
|
//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_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_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_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_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_DONE_PERSIST (1 << 7) /* DONE Persistence 0=Disabled (Default), 1=Enabled */
|
||||||
# define FEA_JTAG_PERSIST (1 << 8) /* JTAG Port Persistence 0=Enabled (Default), 1=Disabled */
|
# define FEA_JTAG_PERSIST (1 << 8) /* JTAG Port Persistence 0=Enabled (Default), 1=Disabled */
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
FeaParser::FeaParser(string filename, bool verbose):
|
FeaParser::FeaParser(const string &filename, bool verbose):
|
||||||
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose),
|
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose),
|
||||||
_feabits(0), _has_feabits(false)
|
_feabits(0), _has_feabits(false)
|
||||||
{
|
{
|
||||||
|
|
@ -73,7 +73,7 @@ FeaParser::FeaParser(string filename, bool verbose):
|
||||||
_featuresRow[i] = 0;
|
_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
|
* \brief read a line with '\r''\n' or '\n' termination
|
||||||
* check if last char is '\r'
|
* check if last char is '\r'
|
||||||
* \return a vector of lines without [\r]\n
|
* \return a vector of lines without [\r]\n
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
class FeaParser: public ConfigBitstreamParser {
|
class FeaParser: public ConfigBitstreamParser {
|
||||||
public:
|
public:
|
||||||
FeaParser(std::string filename, bool verbose = false);
|
FeaParser(const std::string &filename, bool verbose = false);
|
||||||
int parse() override;
|
int parse() override;
|
||||||
void displayHeader() override;
|
void displayHeader() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ int FsParser::parseHeader()
|
||||||
if (buffer[buffer.size()-1] == '\r')
|
if (buffer[buffer.size()-1] == '\r')
|
||||||
buffer.pop_back();
|
buffer.pop_back();
|
||||||
|
|
||||||
/* store each line in dedicated buffer for futur use
|
/* store each line in dedicated buffer for future use
|
||||||
*/
|
*/
|
||||||
_lstRawData.push_back(buffer);
|
_lstRawData.push_back(buffer);
|
||||||
|
|
||||||
|
|
@ -70,8 +70,8 @@ int FsParser::parseHeader()
|
||||||
snprintf(&_hdr["idcode"][0], 9, "%08x", _idcode);
|
snprintf(&_hdr["idcode"][0], 9, "%08x", _idcode);
|
||||||
break;
|
break;
|
||||||
case 0x0A: /* user code or checksum ? */
|
case 0x0A: /* user code or checksum ? */
|
||||||
_hdr["CheckSum"] = string(4, ' ');
|
_hdr["CheckSum"] = string(8, ' ');
|
||||||
snprintf(&_hdr["CheckSum"][0], 5, "%04x", (uint16_t)(0xffff & val));
|
snprintf(&_hdr["CheckSum"][0], 9, "%08x", (uint32_t)(0xffffffff & val));
|
||||||
break;
|
break;
|
||||||
case 0x0B: /* only present when bit_security is set */
|
case 0x0B: /* only present when bit_security is set */
|
||||||
_hdr["SecurityBit"] = "ON";
|
_hdr["SecurityBit"] = "ON";
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue