Update to latest openFPGALoader files

This commit is contained in:
Stéphane Chevigny 2023-06-24 12:33:48 -04:00
commit f817819b3e
160 changed files with 8455 additions and 6852 deletions

View File

@ -38,8 +38,8 @@ jobs:
fail-fast: false
matrix:
os:
- 18
- 20
- 22
name: '🚧🐧 Ubuntu ${{ matrix.os }} | build'
runs-on: ubuntu-${{ matrix.os }}.04
steps:
@ -52,6 +52,7 @@ jobs:
sudo apt update -qq
sudo apt install -y \
cmake \
gzip \
libftdi1-2 \
libftdi1-dev \
libhidapi-hidraw0 \
@ -121,8 +122,8 @@ jobs:
fail-fast: false
matrix:
os:
- 18
- 20
- 22
name: '🚦🐧 Ubuntu ${{ matrix.os }} | test'
runs-on: ubuntu-${{ matrix.os }}.04
steps:

3
.gitignore vendored
View File

@ -45,3 +45,6 @@ build/
/doc/compatibility/boards.inc
/doc/compatibility/cable.inc
/doc/compatibility/fpga.inc
# VSCode local settings directory
/.vscode/

View File

@ -1,6 +1,10 @@
# Copy this file to /etc/udev/rules.d/
ACTION!="add|change", GOTO="openfpgaloader_rules_end"
# gpiochip subsystem
SUBSYSTEM=="gpio", MODE="0664", GROUP="plugdev", TAG+="uaccess"
SUBSYSTEM!="usb|tty|hidraw", GOTO="openfpgaloader_rules_end"
# Original FT232/FT245 VID:PID
@ -23,6 +27,8 @@ ATTRS{idVendor}=="0547", ATTRS{idProduct}=="1002", MODE="664", GROUP="plugdev",
# altera usb-blaster
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6002", MODE="664", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6003", MODE="664", GROUP="plugdev", TAG+="uaccess"
# altera usb-blasterII - uninitialized
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6810", MODE="664", GROUP="plugdev", TAG+="uaccess"
@ -32,10 +38,19 @@ ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev",
# dirtyJTAG
ATTRS{idVendor}=="1209", ATTRS{idProduct}=="c0ca", MODE="664", GROUP="plugdev", TAG+="uaccess"
# Jlink
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev", TAG+="uaccess"
# NXP LPC-Link2
ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="0090", MODE="664", GROUP="plugdev", TAG+="uaccess"
# NXP ARM mbed
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="664", GROUP="plugdev", TAG+="uaccess"
# icebreaker bitsy
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6146", MODE="664", GROUP="plugdev", TAG+="uaccess"
# orbtrace-mini dfu
ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3442", MODE="664", GROUP="plugdev", TAG+="uaccess"
LABEL="openfpgaloader_rules_end"

View File

@ -1,25 +1,36 @@
cmake_minimum_required(VERSION 3.0)
# set the project name
project(openFPGALoader VERSION "0.7.0" LANGUAGES CXX)
project(openFPGALoader VERSION "0.10.0" LANGUAGES CXX)
add_definitions(-DVERSION=\"v${PROJECT_VERSION}\")
option(ENABLE_OPTIM "Enable build with -O3 optimization level" ON)
option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(ENABLE_UDEV OFF)
set(ENABLE_UDEV OFF)
else()
option(ENABLE_UDEV "use udev to search JTAG adapter from /dev/xx" ON)
option(ENABLE_UDEV "use udev to search JTAG adapter from /dev/xx" ON)
endif()
option(ENABLE_CMSISDAP "enable cmsis DAP interface (requires hidapi)" ON)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
option(ENABLE_LIBGPIOD "enable libgpiod bitbang driver (requires libgpiod)" ON)
option(ENABLE_REMOTEBITBANG "enable remote bitbang driver" ON)
else()
set(ENABLE_LIBGPIOD OFF)
set(ENABLE_REMOTEBITBANG OFF)
endif()
option(USE_PKGCONFIG "Use pkgconfig to find libraries" ON)
option(LINK_CMAKE_THREADS "Use CMake find_package to link the threading library" OFF)
set(BLASTERII_PATH "" CACHE STRING "usbBlasterII firmware directory")
set(ISE_PATH "/opt/Xilinx/14.7" CACHE STRING "ise root directory (default: /opt/Xilinx/14.7)")
## specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra ${CMAKE_CXX_FLAGS_DEBUG}")
if (ENABLE_OPTIM)
set(CMAKE_CXX_FLAGS "-O3 ${CMAKE_CXX_FLAGS}")
endif()
if (BUILD_STATIC)
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static ${CMAKE_EXE_LINKER_FLAGS}")
@ -31,16 +42,20 @@ include(GNUInstallDirs)
add_definitions(-DDATA_DIR=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}\")
add_definitions(-DISE_DIR=\"${ISE_PATH}\")
add_definitions(-DBLASTERII_DIR=\"${BLASTERII_PATH}\")
if(USE_PKGCONFIG)
if (USE_PKGCONFIG)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
pkg_check_modules(HIDAPI hidapi-hidraw)
# if hidraw not found try with libusb
if(NOT HIDAPI_FOUND)
if (NOT HIDAPI_FOUND)
pkg_check_modules(HIDAPI hidapi-libusb)
endif()
if (NOT HIDAPI_FOUND)
pkg_check_modules(HIDAPI hidapi)
endif()
# zlib support (gzip)
pkg_check_modules(ZLIB zlib)
if (NOT ZLIB_FOUND)
@ -53,7 +68,7 @@ if(USE_PKGCONFIG)
endif()
endif(NOT ZLIB_FOUND)
if(ENABLE_UDEV)
if (ENABLE_UDEV)
pkg_check_modules(LIBUDEV libudev)
if (LIBUDEV_FOUND)
add_definitions(-DUSE_UDEV)
@ -62,6 +77,14 @@ if(USE_PKGCONFIG)
set(ENABLE_UDEV OFF)
endif()
endif()
if (ENABLE_LIBGPIOD)
pkg_check_modules(LIBGPIOD libgpiod)
if (NOT LIBGPIOD_FOUND)
message("libgpiod not found, disabling gpiod support")
set(ENABLE_LIBGPIOD OFF)
endif()
endif()
endif()
set(OPENFPGALOADER_SOURCE
@ -69,6 +92,7 @@ set(OPENFPGALOADER_SOURCE
src/anlogicBitParser.cpp
src/anlogicCable.cpp
src/ch552_jtag.cpp
src/common.cpp
src/dfu.cpp
src/dfuFileParser.cpp
src/dirtyJtag.cpp
@ -77,9 +101,10 @@ set(OPENFPGALOADER_SOURCE
src/fx2_ll.cpp
src/ice40.cpp
src/ihexParser.cpp
src/pofParser.cpp
src/rawParser.cpp
src/spiFlash.cpp
src/spiInterface.cpp
src/rawParser.cpp
src/usbBlaster.cpp
src/epcq.cpp
src/svf_jtag.cpp
@ -93,8 +118,10 @@ set(OPENFPGALOADER_SOURCE
src/ftdipp_mpsse.cpp
src/main.cpp
src/latticeBitParser.cpp
src/libusb_ll.cpp
src/gowin.cpp
src/device.cpp
src/jlink.cpp
src/lattice.cpp
src/progressBar.cpp
src/fsparser.cpp
@ -114,6 +141,7 @@ set(OPENFPGALOADER_HEADERS
src/anlogicBitParser.hpp
src/anlogicCable.hpp
src/ch552_jtag.hpp
src/common.hpp
src/cxxopts.hpp
src/dfu.hpp
src/dfuFileParser.hpp
@ -123,14 +151,17 @@ set(OPENFPGALOADER_HEADERS
src/fx2_ll.hpp
src/ice40.hpp
src/ihexParser.hpp
src/pofParser.hpp
src/progressBar.hpp
src/rawParser.hpp
src/usbBlaster.hpp
src/bitparser.hpp
src/ftdiJtagBitbang.hpp
src/ftdiJtagMPSSE.hpp
src/jlink.hpp
src/jtag.hpp
src/jtagInterface.hpp
src/libusb_ll.hpp
src/fsparser.hpp
src/part.hpp
src/board.hpp
@ -157,6 +188,19 @@ set(OPENFPGALOADER_HEADERS
src/colognechipCfgParser.hpp
)
link_directories(
${LIBUSB_LIBRARY_DIRS}
${LIBFTDI_LIBRARY_DIRS}
)
if (ENABLE_LIBGPIOD)
link_directories(${LIBGPIOD_LIBRARY_DIRS})
endif()
if (ENABLE_CMSISDAP AND HIDAPI_FOUND)
link_directories(${HIDAPI_LIBRARY_DIRS})
endif()
add_executable(openFPGALoader
${OPENFPGALOADER_SOURCE}
${OPENFPGALOADER_HEADERS}
@ -167,16 +211,6 @@ include_directories(
${LIBFTDI_INCLUDE_DIRS}
)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_library(LIBFTDI1STATIC libftdi1.a REQUIRED)
find_library(LIBUSB1STATIC libusb-1.0.a REQUIRED)
target_link_libraries(openFPGALoader ${LIBFTDI1STATIC} ${LIBUSB1STATIC})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation -framework IOKit -framework Security")
link_directories(/usr/local/lib)
target_include_directories(openFPGALoader PRIVATE /usr/local/include)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
else()
target_link_libraries(openFPGALoader
${LIBUSB_LIBRARIES}
${LIBFTDI_LIBRARIES}
@ -185,6 +219,9 @@ target_link_libraries(openFPGALoader
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
# winsock provides ntohs
target_link_libraries(openFPGALoader ws2_32)
target_sources(openFPGALoader PRIVATE src/pathHelper.cpp)
list(APPEND OPENFPGALOADER_HEADERS src/pathHelper.hpp)
endif()
# libusb_attach_kernel_driver is only available on Linux.
@ -192,28 +229,72 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_definitions(-DATTACH_KERNEL)
endif()
if(ENABLE_UDEV)
include_directories(${LIBUDEV_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
if (ENABLE_UDEV)
include_directories(${LIBUDEV_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${LIBUDEV_LIBRARIES})
endif()
if (ENABLE_LIBGPIOD)
include_directories(${LIBGPIOD_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${LIBGPIOD_LIBRARIES})
add_definitions(-DENABLE_LIBGPIOD=1)
target_sources(openFPGALoader PRIVATE src/libgpiodJtagBitbang.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/libgpiodJtagBitbang.hpp)
if (LIBGPIOD_VERSION VERSION_GREATER_EQUAL 2)
message("libgpiod v2 support enabled")
add_definitions(-DGPIOD_APIV2)
else()
message("libgpiod v1 support enabled")
endif()
endif(ENABLE_LIBGPIOD)
if (ENABLE_JETSONNANOGPIO)
add_definitions(-DENABLE_JETSONNANOGPIO=1)
target_sources(openFPGALoader PRIVATE src/jetsonNanoJtagBitbang.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/jetsonNanoJtagBitbang.hpp)
message("Jetson Nano GPIO support enabled")
endif(ENABLE_JETSONNANOGPIO)
if (ENABLE_UDEV OR ENABLE_LIBGPIOD OR ENABLE_JETSONNANOGPIO)
add_definitions(-DUSE_DEVICE_ARG)
endif(ENABLE_UDEV OR ENABLE_LIBGPIOD OR ENABLE_JETSONNANOGPIO)
if (BUILD_STATIC)
set_target_properties(openFPGALoader PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
if (ENABLE_CMSISDAP)
if (HIDAPI_FOUND)
include_directories(${HIDAPI_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
add_definitions(-DENABLE_CMSISDAP=1)
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
message("cmsis_dap support enabled")
else()
message("hidapi-libusb not found: cmsis_dap support disabled")
endif()
if (HIDAPI_FOUND)
include_directories(${HIDAPI_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${HIDAPI_LIBRARIES})
add_definitions(-DENABLE_CMSISDAP=1)
target_sources(openFPGALoader PRIVATE src/cmsisDAP.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/cmsisDAP.hpp)
message("cmsis_dap support enabled")
else()
message("hidapi-libusb not found: cmsis_dap support disabled")
endif()
endif(ENABLE_CMSISDAP)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_definitions(-DENABLE_XVC=1)
target_sources(openFPGALoader PRIVATE src/xvc_client.cpp src/xvc_server.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/xvc_client.hpp src/xvc_server.hpp)
set(CMAKE_EXE_LINKER_FLAGS "-pthread ${CMAKE_EXE_LINKER_FLAGS}")
message("Xilinx Virtual Server support enabled")
else()
message("Xilinx Virtual Server support disabled")
endif()
if (ENABLE_REMOTEBITBANG)
add_definitions(-DENABLE_REMOTEBITBANG=1)
target_sources(openFPGALoader PRIVATE src/remoteBitbang_client.cpp)
list (APPEND OPENFPGALOADER_HEADERS src/remoteBitbang_client.hpp)
message("Remote bitbang client support enabled")
else()
message("Remote bitbang client support disabled")
endif()
if (ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${ZLIB_LIBRARIES})
@ -221,7 +302,6 @@ if (ZLIB_FOUND)
else()
message("zlib library not found: can't flash intel/altera devices")
endif()
endif()
if (LINK_CMAKE_THREADS)
find_package(Threads REQUIRED)
@ -238,13 +318,43 @@ math(EXPR FTDI_VAL "${LIBFTDI_VERSION_MAJOR} * 100 + ${LIBFTDI_VERSION_MINOR}")
add_definitions(-DFTDI_VERSION=${FTDI_VAL})
install(TARGETS openFPGALoader DESTINATION bin)
file(GLOB BITS_FILES spiOverJtag/spiOverJtag_*.bit)
file(GLOB RBF_FILES spiOverJtag/spiOverJtag_*.rbf)
file(GLOB GZ_FILES spiOverJtag/spiOverJtag_*.*.gz)
install(FILES
test_sfl.svf
${BITS_FILES}
${RBF_FILES}
# Compress rbf and bit files present into repository
# TODO: test compat with Windows and MacOS
list(INSERT CMAKE_MODULE_PATH 0 ${PROJECT_SOURCE_DIR}/cmake/Modules)
include(FindGZIP)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND GZIP_PRG)
set(SPIOVERJTAG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/spiOverJtag")
file(GLOB BITS_FILES RELATIVE ${SPIOVERJTAG_DIR} spiOverJtag/spiOverJtag_*.bit)
file(GLOB RBF_FILES RELATIVE ${SPIOVERJTAG_DIR} spiOverJtag/spiOverJtag_*.rbf)
STRING(REGEX REPLACE ".bit" ".bit.gz" BIT_GZ_FILES "${BITS_FILES}")
STRING(REGEX REPLACE ".rbf" ".rbf.gz" RBF_GZ_FILES "${RBF_FILES}")
FOREACH(bit ${BITS_FILES} ${RBF_FILES})
ADD_CUSTOM_COMMAND(OUTPUT ${bit}.gz
COMMAND ${GZIP_PRG} -9 -c ${bit} > ${CMAKE_CURRENT_BINARY_DIR}/${bit}.gz
DEPENDS ${SPIOVERJTAG_DIR}/${bit}
WORKING_DIRECTORY ${SPIOVERJTAG_DIR}
COMMENT "Building ${bit}.gz")
list(APPEND GZ_FILES ${CMAKE_CURRENT_BINARY_DIR}/${bit}.gz)
ENDFOREACH(bit)
ADD_CUSTOM_TARGET(bit ALL DEPENDS ${BIT_GZ_FILES} ${RBF_GZ_FILES})
else()
file(GLOB BITS_FILES spiOverJtag/spiOverJtag_*.bit)
file(GLOB RBF_FILES spiOverJtag/spiOverJtag_*.rbf)
install(FILES
${BITS_FILES}
${RBF_FILES}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
)
endif()
install(FILES
${GZ_FILES}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
)

134
README.md
View File

@ -3,7 +3,7 @@
<p align="right">
<a title="Documentation" href="https://trabucayre.github.io/openFPGALoader"><img src="https://img.shields.io/website.svg?label=trabucayre.github.io%2FopenFPGALoader&longCache=true&style=flat-square&url=http%3A%2F%2Ftrabucayre.github.io%2FopenFPGALoader%2Findex.html&logo=GitHub"></a><!--
-->
<a title="'Test' workflow Status" href="https://github.com/trabucayre/openFPGALoader/actions?query=workflow%3ATest"><img alt="'Test' workflow Status" src="https://img.shields.io/github/workflow/status/trabucayre/openFPGALoader/Test?longCache=true&style=flat-square&label=Test&logo=github%20actions&logoColor=fff"></a><!--
<a title="'Test' workflow Status" href="https://github.com/trabucayre/openFPGALoader/actions/workflows/Test.yml"><img alt="'Test' workflow Status" src="https://img.shields.io/github/actions/workflow/status/trabucayre/openFPGALoader/Test.yml?branch=master&longCache=true&style=flat-square&label=Test&logo=github%20actions&logoColor=fff"></a><!--
-->
<a title="Releases" href="https://github.com/trabucayre/openFPGALoader/releases"><img src="https://img.shields.io/github/commits-since/trabucayre/openFPGALoader/latest.svg?longCache=true&style=flat-square&logo=git&logoColor=fff"></a>
</p>
@ -29,6 +29,8 @@ Also checkout the vendor-specific documentation:
[Lattice](https://trabucayre.github.io/openFPGALoader/vendors/lattice.html),
[Xilinx](https://trabucayre.github.io/openFPGALoader/vendors/xilinx.html).
OpenFPGALoader has a dedicated channel: [#openFPGALoader at libera.chat](https://web.libera.chat/#openFPGALoader).
## Quick Usage
`arty` in the example below is one of the many FPGA board configurations listed [here](https://trabucayre.github.io/openFPGALoader/compatibility/board.html).
@ -47,56 +49,96 @@ openFPGALoader -c cmsisdap fpga_bitstream.bit
## Usage
```
Usage: ./openFPGALoader [OPTION...] BIT_FILE
Usage: openFPGALoader [OPTION...] BIT_FILE
openFPGALoader -- a program to flash FPGA
--altsetting arg DFU interface altsetting (only for DFU mode)
--bitstream arg bitstream
-b, --board arg board name, may be used instead of cable
-c, --cable arg jtag interface
--invert-read-edge JTAG mode / FTDI: read on negative edge instead
of positive
--vid arg probe Vendor ID
--pid arg probe Product ID
--ftdi-serial arg FTDI chip serial number
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
A-D)
-d, --device arg device to use (/dev/ttyUSBx)
--detect detect FPGA
--dfu DFU mode
--dump-flash Dump flash mode
--external-flash select ext flash for device with internal and
external storage
--file-size arg provides size in Byte to dump, must be used with
dump-flash
--file-type arg provides file type instead of let's deduced by
using extension
--flash-sector arg flash sector (Lattice parts only)
--fpga-part arg fpga model flavor + package
--freq arg jtag frequency (Hz)
-f, --write-flash write bitstream in flash (default: false)
--index-chain arg device index in JTAG-chain
--list-boards list all supported boards
--list-cables list all supported cables
--list-fpga list all supported FPGA
-m, --write-sram write bitstream in SRAM (default: true)
-o, --offset arg start offset in EEPROM
--pins arg pin config (only for ft232R) TDI:TDO:TCK:TMS
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
--protect-flash arg protect SPI flash area
--quiet Produce quiet output (no progress bar)
-r, --reset reset FPGA after operations
--spi SPI mode (only for FTDI in serial mode)
--unprotect-flash Unprotect flash blocks
-v, --verbose Produce verbose output
--verbose-level arg verbose level -1: quiet, 0: normal, 1:verbose,
2:debug
-h, --help Give this help list
--verify Verify write operation (SPI Flash only)
-V, --Version Print program version
--altsetting arg DFU interface altsetting (only for DFU mode)
--bitstream arg bitstream
--secondary-bitstream arg
secondary bitstream (some Xilinx UltraScale
boards)
-b, --board arg board name, may be used instead of cable
-B, --bridge arg disable spiOverJtag model detection by
providing bitstream(intel/xilinx)
-c, --cable arg jtag interface
--invert-read-edge JTAG mode / FTDI: read on negative edge
instead of positive
--vid arg probe Vendor ID
--pid arg probe Product ID
--cable-index arg probe index (FTDI and cmsisDAP)
--busdev-num arg select a probe by it bus and device number
(bus_num:device_addr)
--ftdi-serial arg FTDI chip serial number
--ftdi-channel arg FTDI chip channel number (channels 0-3 map to
A-D)
--detect detect FPGA
--dfu DFU mode
--dump-flash Dump flash mode
--bulk-erase Bulk erase flash
--target-flash arg for boards with multiple flash chips (some
Xilinx UltraScale boards), select the target
flash: primary (default), secondary or both
--external-flash select ext flash for device with internal and
external storage
--file-size arg provides size in Byte to dump, must be used
with dump-flash
--file-type arg provides file type instead of let's deduced
by using extension
--flash-sector arg flash sector (Lattice parts only)
--fpga-part arg fpga model flavor + package
--freq arg jtag frequency (Hz)
-f, --write-flash write bitstream in flash (default: false)
--index-chain arg device index in JTAG-chain
--ip arg IP address (XVC and remote bitbang client)
--list-boards list all supported boards
--list-cables list all supported cables
--list-fpga list all supported FPGA
-m, --write-sram write bitstream in SRAM (default: true)
-o, --offset arg Start address (in bytes) for read/write into
non volatile memory (default: 0)
--pins arg pin config TDI:TDO:TCK:TMS
--probe-firmware arg firmware for JTAG probe (usbBlasterII)
--protect-flash arg protect SPI flash area
--quiet Produce quiet output (no progress bar)
-r, --reset reset FPGA after operations
--scan-usb scan USB to display connected probes
--skip-load-bridge skip writing bridge to SRAM when in
write-flash mode
--skip-reset skip resetting the device when in write-flash
mode
--spi SPI mode (only for FTDI in serial mode)
--unprotect-flash Unprotect flash blocks
-v, --verbose Produce verbose output
--verbose-level arg verbose level -1: quiet, 0: normal,
1:verbose, 2:debug
-h, --help Give this help list
--verify Verify write operation (SPI Flash only)
--port arg Xilinx Virtual Cable and remote bitbang Port
(default 3721)
--mcufw arg Microcontroller firmware
--conmcu Connect JTAG to MCU
-V, --Version Print program version
Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.
Report bugs to <gwenhael.goavec-merou@trabucayre.com>.
```
By default **spiOverJtag** are search into `${CMAKE_INSTALL_FULL_DATAROOTDIR}`
(*/usr/local/share/* by default). It's possible to change this behaviour by
using an environment variable:
```bash
export OPENFPGALOADER_SOJ_DIR=/somewhere
openFPGALoader xxxx
```
or
```
OPENFPGALOADER_SOJ_DIR=/somewhere openFPGALoader xxxx
```
`OPENFPGALOADER_SOJ_DIR` must point to directory containing **spiOverJtag**
bitstreams.

View File

@ -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)

View File

@ -54,9 +54,10 @@ Gowin:
- GW1NS-2C
- GW1NSR-4C
- GW1NZ-1
- GW2A-18C
URL: https://www.gowinsemi.com/en/product/detail/2/
Memory: OK
Flash: IF
Flash: IF / EF
Intel:
@ -68,7 +69,9 @@ Intel:
Flash: OK
- Description: Cyclone IV CE
Model: EP4CE22
Model:
- EP4CE22
- EP4CE115
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-iv/features.html
Memory: OK
Flash: OK
@ -76,7 +79,9 @@ Intel:
- Description: Cyclone V E
Model:
- 5CEA2
- 5CEA5
- 5CEBA4
- 5CEBA9
URL: https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-v.html
Memory: OK
Flash: OK
@ -96,6 +101,12 @@ Intel:
Memory: OK
Flash: OK
- Description: Max 10
Model: 10M08
URL: https://www.intel.fr/content/www/fr/fr/products/details/fpga/max/10.html
Memory: SVF
Flash: SVF
Lattice:
@ -107,8 +118,16 @@ Lattice:
- Description: ECP5
Model:
- 25F
- 5G 85F
- LFE5U-12
- LFE5U-25
- LFE5U-45
- LFE5U-85
- LFE5UM-25
- LFE5UM-45
- LFE5UM-85
- LFE5UM5G-25
- LFE5UM5G-45
- LFE5UM5G-85
URL: http://www.latticesemi.com/Products/FPGAandCPLD/ECP5
Memory: OK
Flash: OK
@ -163,6 +182,7 @@ Xilinx:
- Description: Artix 7
Model:
- xc7a25t
- xc7a35ti
- xc7a50t
- xc7a75t
@ -176,16 +196,42 @@ Xilinx:
Model:
- xc7k160t
- xc7k325t
- xc7k410t
- xc7k420t
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-7.html#productTable
Memory: OK
Flash: OK
- Description: Spartan 3
Model: xc3s200
URL: https://www.xilinx.com/products/silicon-devices/fpga/spartan-3.html
- Description: Artix UltraScale+
Model:
- xcau25p
URL: https://www.xilinx.com/products/silicon-devices/fpga/artix-ultrascale-plus.html
Memory: OK
Flash: TBD
- Description: Kintex UltraScale
Model:
- xcku035
- xcku040
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-ultrascale.html#productTable
Memory: OK
Flash: NA
- Description: Virtex UltraScale+
Model:
- xcvu9p
URL: https://www.xilinx.com/products/silicon-devices/fpga/virtex-ultrascale-plus.html#productTable
Memory: OK
Flash: OK
- Description: Spartan 3
Model:
- xc3s200
- xc3s500e
URL: https://www.xilinx.com/products/silicon-devices/fpga/spartan-3.html
Memory: OK
Flash: OK
- Description: Spartan 6
Model:
- xc6slx9
@ -216,8 +262,10 @@ Xilinx:
Memory: NA
Flash: OK
- Description: XC2C (coolrunner II)
Model: xc2c32a
- Description: XC2C/XA2C (coolrunner II)
Model:
- xc2c32a
- xa2c64a
URL: https://www.xilinx.com/support/documentation/data_sheets/ds090.pdf
Memory: TBD
Flash: OK
@ -240,7 +288,10 @@ Xilinx:
Flash: NA
- Description: ZynqMPSoC
Model: xczu2cg
Model:
- xczu2cg
- xczu9eg
- xczu11eg
URL: https://www.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html
Memory: OK
Flash: NA

View File

@ -13,6 +13,13 @@
Memory: OK
Flash: OK
- ID: litex-acorn-baseboard-mini
Description: The LiteX-Acorn-Baseboards are baseboards developed around the SQRL's Acorn board (or Nite/LiteFury)
URL: https://github.com/enjoy-digital/litex-acorn-baseboard/
FPGA: Artix xc7a200tsbg484
Memory: OK
Flash: OK
- ID: alchitry_au
Description: Alchitry Au
URL: https://alchitry.com/products/alchitry-au-fpga-development-board
@ -20,6 +27,27 @@
Memory: OK
Flash: OK
- ID: alchitry_au_plus
Description: Alchitry Au+ (Plus)
URL: https://www.sparkfun.com/products/17514
FPGA: Artix xc7a100tftg256
Memory: OK
Flash: OK
- ID: alinx_ax516
Description: ALINX AX516
URL: https://www.alinx.com/en/detail/281
FPGA: Spartan6 xc6slx16csg324
Memory: OK
Flash: OK
- ID: analogMax
Description: Trenz TEI0010 - AnalogMax
URL: https://wiki.trenz-electronic.de/display/PD/TEI0010+-+AnalogMax
FPGA: Max 10 10M08SAU169C8G
Memory: SVF
Flash: SVF
- ID: arty_a7_35t
Description: Digilent Arty A7
URL: https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start
@ -94,16 +122,23 @@
Memory: OK
Flash: OK
- ID: cmod_s7
Description: Digilent Cmod S7
URL: https://https://digilent.com/reference/programmable-logic/cmod-s7/start
FPGA: Spartan7 xc7s25csga225
Memory: NA
Flash: OK
- ID: gatemate_evb_jtag
Description: Cologne Chip GateMate FPGA Evaluation Board (JTAG mode)
URL: https://colognechip.com/programmable-logic/gatemate/
URL: https://colognechip.com/programmable-logic/gatemate-evaluation-board/
FPGA: Cologne Chip GateMate Series
Memory: OK
Flash: OK
- ID: gatemate_evb_spi
Description: Cologne Chip GateMate FPGA Evaluation Board (SPI mode)
URL: https://colognechip.com/programmable-logic/gatemate/
URL: https://colognechip.com/programmable-logic/gatemate-evaluation-board/
FPGA: Cologne Chip GateMate Series
Memory: OK
Flash: OK
@ -115,6 +150,14 @@
Memory: OK
Flash: OK
- ID: cmoda7_35t
Description: Digilent CmodA7
URL: https://digilent.com/reference/programmable-logic/cmod-a7/start
FPGA: Artix xc7a35tcpg236
Memory: OK
Flash: OK
Constraints: Cmod-A7-35T
- ID: colorlight
Description: Colorlight 5A-75B (version 7)
URL: https://fr.aliexpress.com/item/32281130824.html
@ -152,6 +195,20 @@
Memory: OK
Flash: OK
- ID: c10lp-refkit
Description: Trenz c10lp-refkit
URL: https://shop.trenz-electronic.de/en/TEI0009-02-055-8CA-Cyclone-10-LP-RefKit-10CL055-Development-Board-32-MByte-SDRAM-16-MByte-Flash
FPGA: Cyclone 10 LP 10CL055YU484C8G
Memory: OK
Flash: OK
- ID: c5g
Description: Terasic C5G (Cyclone V GX Starter Kit)
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=830
FPGA: Cyclone V GX 5CGXFC5C6F27C7N
Memory: OK
Flash: NT
- ID: de0
Description: Terasic DE0
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=364
@ -172,6 +229,12 @@
FPGA: Cyclone V SoC 5CSEMA4U23C6
Memory: OK
- ID: de10lite
Description: Terasic de10lite
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=218&No=1021&PartNo=1
FPGA: MAX 10 10M50DAF484C7G
Memory: OK
- ID: de10nano
Description: Terasic de10Nano
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=205&No=1046
@ -184,6 +247,12 @@
FPGA: Cyclone V SoC 5CSEMA5F31C6
Memory: OK
- ID: deca
Description: Arrow/Terasic DECA
URL: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=&No=944&PartNo=1
FPGA: MAX 10 10M50DAF484C6GES
Memory: OK
- ID: ecp5_evn
Description: Lattice ECP5 5G Evaluation Board
URL: https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP5EvaluationBoard
@ -224,6 +293,13 @@
Memory: OK
Flash: IF
- ID: hseda-xc6slx16
Description: XILINX SPARTAN6 XC6SLX16 Microblaze SDRAM USB2.0 FPGA
URL: http://hseda.com/product/xilinx/XC6SLX16/XC6SLX16.htm
FPGA: Spartan6 xc6slx16-ftg256
Memory: OK
Flash: OK
- ID: ice40_generic
Description: iCEBreaker
URL: https://1bitsquared.com/collections/fpga/products/icebreaker
@ -254,7 +330,7 @@
Description: iCE40-HX8K
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx
FPGA: iCE40 HX8k
Memory: NT
Memory: OK
Flash: AS
Constraints: iCE40-HX8K
@ -274,6 +350,14 @@
Flash: AS
Constraints: iCE40HX8K-EVB
- ID: ice40_generic
Description: iCE40 UltraPlus Breakout Board (iCE40UP5K-B-EVN)
URL: https://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40UltraPlusBreakoutBoard
FPGA: iCE40-UP5K
Memory: NT
Flash: AS
Constraints: iCE40-UP
- ID: ice40_generic
Description: Icezum Alhambra II
URL: https://alhambrabits.com/alhambra
@ -290,6 +374,20 @@
Flash: NT
Constraints: KC705
- ID: LD-KONFEKT
Description: Lone Dynamics Corporation - Machdyne Konfekt computer
URL: https://machdyne.com/product/konfekt-computer/
FPGA: ECP5 LFE5U-12F-6BG256C
Memory: OK
Flash: OK
- ID: LD-SCHOKO
Description: Lone Dynamics Corporation - Machdyne Schoko computer
URL: https://machdyne.com/product/schoko-computer/
FPGA: ECP5 LFE5U-45F-6CABGA256
Memory: OK
Flash: OK
- ID: licheeTang
Description: Sipeed Lichee Tang
URL: https://tang.sipeed.com/en/hardware-overview/lichee-tang/
@ -318,6 +416,22 @@
Memory: OK
Flash: OK
- ID: nexys_a7_50
Description: Digilent Nexys A7(Nexys 4 DDR)
URL: https://digilent.com/reference/programmable-logic/nexys-a7/start
FPGA: Artix xc7a50tcsg324
Memory: OK
Flash: OK
Constraints: Nexys4DDR
- ID: nexys_a7_100
Description: Digilent Nexys A7(Nexys 4 DDR)
URL: https://digilent.com/reference/programmable-logic/nexys-a7/start
FPGA: Artix nexys_a7_100
Memory: OK
Flash: OK
Constraints: Nexys4DDR
- ID: nexysVideo
Description: Digilent Nexys Video
URL: https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start
@ -325,6 +439,20 @@
Memory: OK
Flash: OK
- ID: xem8320
Description: Opal Kelly XEM8320
URL: https://opalkelly.com/products/xem8320/
FPGA: Artix UltraScale+ xcau25p-2ffvb676e
Memory: OK
Flash: TBD
- ID: orbtrace_dfu
Description: ORBTrace mini (dfu mode)
URL: https://store.zyp.no/product/orbtrace-mini
FPGA: ECP5 LFE5U-25F-8BG256C
Memory: NA
Flash: OK (DFU)
- ID: orangeCrab
Description: Orange Crab
URL: https://github.com/gregdavill/OrangeCrab
@ -333,6 +461,13 @@
Flash: OK (DFU)
Constraints: OrangeCrab-r0.2
- ID: papilio_one
Description: Papilio One
URL: https://papilio.cc/index.php?n=Papilio.PapilioOne
FPGA: Spartan3E xc3s500e-vq100
Memory: OK
Flash: OK
- ID: pipistrello
Description: Saanlima Pipistrello LX45
URL: http://pipistrello.saanlima.com/index.php?title=Welcome_to_Pipistrello
@ -340,6 +475,13 @@
Memory: OK
Flash: OK
- ID: pynq_z2
Description: PYNQ-Z2
URL: https://www.tulembedded.com/FPGA/ProductsPYNQ-Z2.html
FPGA: Zynq7000 xc7z020clg400
Memory: OK
Flash: NA
- ID: qmtechCycloneIV
Description: QMTech CycloneIV Core Board
URL: https://fr.aliexpress.com/item/32949281189.html
@ -354,6 +496,13 @@
Memory: OK
Flash: OK
- ID: qmtechCycloneV_5ce523
Description: QMTech CycloneV Core Board
URL: https://fr.aliexpress.com/item/1005001782703399.html
FPGA: Cyclone V 5CEFA5F23I7
Memory: OK
Flash: OK
- ID: qmtechKintex7
Description: QMTech Kintex7 Core Board
URL: https://www.aliexpress.com/item/1005003668804223.html
@ -390,12 +539,19 @@
Flash: NA
- ID: SPEC150
Description: CERN Simple PCIe FMC carrier SPEC
Description: CERN Simple PCIe FMC carrier SPEC
URL: https://ohwr.org/project/spec150/wikis/home
FPGA: Spartan6 xc6slx150Tfgg484
Memory: OK
Flash: OK
- ID: stlv7325
Description: Sitlinv STLV7325 Board
URL: https://www.aliexpress.com/item/1005001275162791.html
FPGA: Kintex xc7k325tffg676
Memory: OK
Flash: OK
- ID: tangnano
Description: Sipeed Tang Nano
URL: https://tangnano.sipeed.com/en/
@ -423,6 +579,20 @@
Memory: OK
Flash: IF/EF
- ID: tangnano20k
Description: Sipeed Tang Nano 20k
URL: https://wiki.sipeed.com/nano20k
FPGA: Gowin Arora GW2A(R)-18(C)
Memory: OK
Flash: EF
- ID: tangprimer20k
Description: Sipeed Tang Primer 20k
URL: https://wiki.sipeed.com/en/primer20k
FPGA: Gowin Arora GW2A(R)-18(C)
Memory: OK
Flash: EF
- ID: tec0117
Description: Trenz Gowin LittleBee (TEC0117)
URL: https://shop.trenz-electronic.de/en/TEC0117-01-FPGA-Module-with-GOWIN-LittleBee-and-8-MByte-internal-SDRAM
@ -430,6 +600,20 @@
Memory: OK
Flash: IF
- ID: trion_t120_bga576_spi
Description: Efinix Trion T120 BGA576 Dev Kit
URL: https://www.efinixinc.com/products-devkits-triont120bga576.html
FPGA: Trion T120BGA576
Memory: NA
Flash: AS
- ID: trion_ti60_f225_spi
Description: Efinix Titanium F225 Dev Kit
URL: https://www.efinixinc.com/products-devkits-titaniumti60f225.html
FPGA: Titanium Ti60F225
Memory: NA
Flash: AS
- ID: ulx3s
Description: Radiona ULX3S
URL: https://radiona.org/ulx3s/
@ -463,19 +647,19 @@
Memory: NA
Flash: AS
- ID: trion_t120_bga576_spi
Description: Efinix Trion T120 BGA576 Dev Kit
URL: https://www.efinixinc.com/products-devkits-triont120bga576.html
FPGA: Trion T120BGA576
Memory: NA
Flash: AS
- ID: usrpx300
Description: Ettus Research USRP X300
URL: https://www.ettus.com/all-products/x300-kit/
FPGA: Kintex xc7k325tffg900
Memory: OK
Flash: NA
- ID: trion_ti60_f225_spi
Description: Efinix Titanium F225 Dev Kit
URL: https://www.efinixinc.com/products-devkits-titaniumti60f225.html
FPGA: Titanium Ti60F225
Memory: NA
Flash: AS
- ID: usrpx310
Description: Ettus Research USRP X300
URL: https://www.ettus.com/all-products/x310-kit/
FPGA: Kintex xc7k410tffg900
Memory: OK
Flash: NA
- ID: xmf3
Description: PLDkit XMF3
@ -499,6 +683,20 @@
Flash: NA
Constraints: ZC706
- ID: zcu102
Description: Xilinx ZCU102
URL: https://www.xilinx.com/products/boards-and-kits/ek-u1-zcu102-g.html
FPGA: zynqMPSoC XCZU9EG
Memory: OK
Flash: NA
- ID: zcu106
Description: Xilinx ZCU106
URL: https://www.xilinx.com/products/boards-and-kits/zcu106.html
FPGA: zynqMPSoC XCZU7EV
Memory: OK
Flash: NA
- ID: zedboard
Description: Avnet ZedBoard
URL: https://www.avnet.com/wps/portal/us/products/avnet-boards/avnet-board-families/zedboard/
@ -520,3 +718,24 @@
FPGA: zynq7000 xc7z020clg400
Memory: OK
Flash: NA
- ID: vcu118
Description: Xilinx VCU118
URL: https://www.xilinx.com/products/boards-and-kits/vcu118.html
FPGA: Virtex UltraScale+ xcvu9p-flga2104
Memory: OK
Flash: OK
- ID: vcu128
Description: Xilinx VCU128
URL: https://www.xilinx.com/products/boards-and-kits/vcu128.html
FPGA: Virtex UltraScale+ xcvu37p-fsvh2892
Memory: OK
Flash: OK
- ID: kcu116
Description: Xilinx KCU116
URL: https://www.xilinx.com/products/boards-and-kits/kcu116.html
FPGA: Kintex UltraScale+ xcku5p-ffvb676
Memory: OK
Flash: OK

View File

@ -126,6 +126,10 @@ ft2232:
Description: USB-JTAG/UART debugger based on BL702 microcontroler.
URL: https://github.com/sipeed/RV-Debugger-BL702
- Name: Sipeed RV-Debugger-BL702
Description: RV-Debugger-BL702 is an opensource project that implement a JTAG+UART debugger with BL702C-A0.
URL: https://github.com/sipeed/RV-Debugger-BL702
- Name: honeycomb USB-JTAG interface.
Description: FT2232C clone based on STM32F042 microcontroler
URL: https://github.com/Disasm/f042-ftdi
@ -172,6 +176,19 @@ ecpix5-debug:
URL: https://shop.lambdaconcept.com/home/46-ecpix-5.html
jlink:
- Name: jlink
Description: SEGGER J-Link Debug Probes
URL: https://www.segger.com/products/debug-probes/j-link
- Name: jlink_base
Description: SEGGER J-Link BASE Debug Probes
- Name: jtrace_pro
Description: SEGGER J-Trace PRO Debug Probes
jtag-smt2-nc:
- Name: jtag-smt2-nc
@ -179,6 +196,13 @@ jtag-smt2-nc:
URL: https://digilent.com/shop/jtag-smt2-nc-surface-mount-programming-module
lpc-link2:
- Name: lpc-link2
Description: LPC-Link2 (OM13054) cmsisDAP firmware
URL: https://www.nxp.com/design/microcontrollers-developer-resources/lpc-link2:OM13054
orbtrace:
- Name: orbtrace interface
@ -186,6 +210,27 @@ orbtrace:
URL: https://github.com/orbcode/orbtrace
papilio:
- Name: papilio
Description: Papilio FPGA Platform
URL: https://papilio.cc/
steppenprobe:
- Name: steppenprobe
Description: Open Source Hardware JTAG/SWD/UART/SWO interface board based on FTDI FT2232H
URL: https://github.com/diegoherranz/steppenprobe
remote-bitgang:
- Name: OpenOCD remote bitbang
Description: The remote_bitbang JTAG driver is used to drive JTAG from a remote (TCP) process
URL: https://github.com/openocd-org/openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
tigard:
- Name: tigard
@ -204,3 +249,30 @@ usb-blasterII:
- Name: intel USB Blaster II interface
Description: JTAG programmer cable from intel/altera (EZ-USB FX2 + EPM570)
URL: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_usb_blstr_ii_cable.pdf
xvc-client:
- Name: Xilinx Virtual Cable
Description: Xilinx Virtual Cable (XVC) is a TCP/IP-based protocol that acts like a JTAG cable.
URL: https://github.com/Xilinx/XilinxVirtualCable
xvc-server:
- Name: Xilinx Virtual Cable (server side)
Description: Xilinx Virtual Cable (XVC) is a TCP/IP-based protocol that acts like a JTAG cable.
URL: https://github.com/Xilinx/XilinxVirtualCable
libgpiod:
- Name: Bitbang GPIO
Description: Bitbang GPIO pins on Linux host.
URL: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
jetson-nano-gpio:
- Name: Bitbang GPIO
Description: Bitbang GPIO pins on Jetson Nano Linux host. Use /dev/mem to have a faster clock.
URL: https://github.com/jwatte/jetson-gpio-example

View File

@ -11,7 +11,7 @@ Resetting an FPGA
openFPGALoader [options] -r
Using negative edge for TDO's sampling
====================================
======================================
If transaction are unstable you can try to change read edge by using
@ -43,7 +43,7 @@ Automatic file type detection bypass
====================================
Default behavior is to use file extension to determine file parser.
To avoid this mecanism ``--file-type type`` must be used.
To avoid this mechanism ``--file-type type`` must be used.
FT231/FT232 bitbang mode and pins configuration
===============================================
@ -82,3 +82,20 @@ Writing to an arbitrary address in flash memory
With FPGA using an external SPI flash (*xilinx*, *lattice ECP5/nexus/ice40*, *anlogic*, *efinix*) option ``-o`` allows
one to write raw binary file to an arbitrary adress in FLASH.
Using an alternative directory for *spiOverJtag*
================================================
By setting ``OPENFPGALOADER_SOJ_DIR`` it's possible to override default
*spiOverJtag* bitstreams directory:
.. code-block:: bash
export OPENFPGALOADER_SOJ_DIR=/somewhere
openFPGALoader xxxx
or
.. code-block:: bash
OPENFPGALOADER_SOJ_DIR=/somewhere openFPGALoader xxxx

View File

@ -6,7 +6,7 @@ First steps with openFPGALoader
Install
=======
Packages are available for Linux distributionsm, Windows (MSYS2) and macOS:
Packages are available for Linux distributions, Windows (MSYS2) and macOS:
* *Arch Linux*: ``sudo pacman -S openfpgaloader``

View File

@ -19,7 +19,7 @@ Alternatively, you could build from source. First: install required libraries:
.. code-block:: bash
sudo pacman -S git cmake make gcc pkgconf libftdi libusb zlib hidapi
sudo pacman -S git cmake make gcc pkgconf libftdi libusb zlib hidapi gzip
Build step is similar as Debian
@ -41,6 +41,8 @@ This application uses ``libftdi1``, so this library must be installed (and, depe
.. code-block:: bash
sudo apt install \
git \
gzip \
libftdi1-2 \
libftdi1-dev \
libhidapi-hidraw0 \
@ -85,6 +87,14 @@ You may also need to add this if you see link errors between ``libusb`` and ``pt
-DLINK_CMAKE_THREADS=ON
By default, ``libgpiod`` support is enabled
If you don't want this option, use:
.. code-block:: bash
-DENABLE_LIBGPIOD=OFF
Additionaly you have to install ``libgpiod``
To build the app:
@ -125,6 +135,14 @@ These rules set access right and group (``plugdev``) when a converter is plugged
After that you need to unplug and replug your device.
.. HINT::
``usermod`` is used to add ``$USER`` as a member of ``plugdev`` group.
However this update is not taken into account immediately: it's required to
logout from current session and login again.
Check, by using ``id $USER``, if ``plugdev`` is mentioned after ``groups=``.
An alternate (and temporary) solution is to use ``sudo - $USER`` to have
your user seen as a member of ``plugdev`` group (works only for the current terminal).
macOS
=====
@ -134,6 +152,19 @@ openFPGALoader is available as a `Homebrew <https://brew.sh>`__ formula:
brew install openfpgaloader
Alternatively, if you want to build it by hand:
.. code-block:: bash
brew install --only-dependencies openfpgaloader
brew install cmake pkg-config zlib gzip
git clone https://github.com/trabucayre/openFPGALoader
cd openFPGALoader
mkdir build
cd build
cmake ..
make -j
Windows
=======

View File

@ -8,3 +8,38 @@ I installed openFPGALoader but it says `command not found` when I try to launch
The correct spelling of the program is *openFPGALoader* with FPGA and the "L" of "Loader" in uppercase.
Ensure the spelling of the program is correct.
Gowin device could not communicate since last bitstream flashed. (issue `#206 <https://github.com/trabucayre/openFPGALoader/issues/206>`_)
==========================================================================================================================================
Gowin's FPGA may fails to be detected if **JTAGSEL_N** (pin 08 for *GW1N-4K*) is used as a GPIO.
To recover you have to pull down this pin (before power up) to recover JTAG interface (*UG292 - JTAGSELL_N section*).
JTAG init failed
================
Avoid using USB hubs and connect it directly to your PC USB port.
Tang Primer 20k program slow and stucked (issue `#250 <https://github.com/trabucayre/openFPGALoader/issues/250>`_)
==================================================================================================================
Check your openFPGALoader version:
.. code:: bash
openFPGALoader -V
If it is older than release then v0.9.0, install the most recent version (from commit `f5b89bff68a5e2147404a895c075773884077438 <https://github.com/trabucayre/openFPGALoader/commit/fe259fb78d185b3113661d04cd7efa9ae0232425>`_ or later).
Cannot flash Tang Nano 9k (issue `#251 <https://github.com/trabucayre/openFPGALoader/issues/251>`_)
===================================================================================================
This is a device issue, erase its Embedded Flash using Official GoWin Programmer (preferentially in Windows) and SRAM too, then you can use openFPGALoader again.
Unable to open FTDI device: -4 (usb_open() failed) (issue `#245 <https://github.com/trabucayre/openFPGALoader/issues/245>`_)
============================================================================================================================
Edit your `/etc/udev/rules.d/99-ftdi.rules` file exchanging your programming device permissions.
For more information, check the udev section from `this guide <install.rst>`_

View File

@ -17,7 +17,7 @@ Supported configuration files are bitfiles ``*.bit`` and it's ASCII equivalents
JTAG Configuration
------------------
Performs an active hardware reset and writes the configuration into the FPGA latches via JTAG. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xF0 (JTAG).
Performs an active hardware reset and writes the configuration into the FPGA latches via JTAG. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xC (JTAG).
1. Program using Evaluation Board:
@ -34,7 +34,7 @@ Performs an active hardware reset and writes the configuration into the FPGA lat
SPI Configuration
-----------------
Performs an active hardware reset and writes the configuration into the FPGA latches via SPI. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0x40 (SPI passive).
Performs an active hardware reset and writes the configuration into the FPGA latches via SPI. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0x4 (SPI passive).
1. Program using Evaluation Board:
@ -51,7 +51,7 @@ Performs an active hardware reset and writes the configuration into the FPGA lat
JTAG Flash Access
-----------------
It is possible to access external flashes via the internal JTAG-SPI-bypass. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xF0 (JTAG). Note that the FPGA will not start automatically.
It is possible to access external flashes via the internal JTAG-SPI-bypass. The configuration mode pins ``CFG_MD[3:0]`` must be set to 0xC (JTAG). Note that the FPGA will not start automatically.
1. Write to flash using Evaluation Board:
@ -74,7 +74,7 @@ The `offset` parameter can be used to store data at any point in the flash, e.g.
SPI Flash Access
----------------
If the programming device and FPGA share the same SPI signals, it is possible to hold the FPGA in reset and write data to the flash. The configuration mode can be set as desired. If the FPGA should start from the external memory after reset, the configuration mode pins ``CFG_MD[3:0]`` set to 0x00 (SPI active).
If the programming device and FPGA share the same SPI signals, it is possible to hold the FPGA in reset and write data to the flash. The configuration mode can be set as desired. If the FPGA should start from the external memory after reset, the configuration mode pins ``CFG_MD[3:0]`` set to 0x0 (SPI active).
1. Write to flash using Evaluation Board:
@ -92,4 +92,4 @@ The `offset` parameter can be used to store data at any point in the flash, e.g.
.. code-block:: bash
openFPGALoader -b gatemate_evb_spi -o <offset> <bitfile>.cfg.bit
openFPGALoader -b gatemate_evb_spi -o <offset> <bitfile>.cfg.bit

View File

@ -25,3 +25,27 @@ or, for xyloni board
Since openFPGALoader access the flash directly in SPI mode the ``-b fireant``, ``-b xyloni_spi`` is required (no
autodetection possible).
Trion and Titanium JTAG usage
==========================================
*openFPGALoader* supports loading to RAM and SPI Flash with JTAG
Tested with J-Link BASE
bin file load
-------------
.. code-block:: bash
openFPGALoader --cable jlink_base -m /somewhere/project/outflow/*.bin
hex file flash
-------------
Example for ti60f225.
NOTE: JTAG chains with more than one device (eg --index-chain) are currently not supported for writing to SPI flash
.. code-block:: bash
openFPGALoader --cable jlink_base --fpga-part ti60f225 -f /somewhere/project/outflow/*.hex

View File

@ -31,7 +31,11 @@ where ``BOARD_NAME`` is:
* ``tec0117``
* ``tangnano``
* ``tangnano1k``
* ``tangnano4k``
* ``tangnano9k``
* ``tangnano20k``
* ``tangprimer20k``
* ``runber``
Flash
@ -53,3 +57,8 @@ where ``BOARD_NAME`` is:
It's possible to flash external SPI Flash (connected to MSPI) in bscan mode by using ``--external-flash`` instead of
``-f``.
.. NOTE::
Gowin's FPGA may fails to be detected if **JTAGSEL_N** (pin 08 for *GW1N-4K*) is used as a GPIO.
To recover you have to pull down this pin (before power up) to recover JTAG interface (*UG292 - JTAGSELL_N section*).

16
doc/vendors/intel.rst vendored
View File

@ -9,6 +9,7 @@ Intel/Altera
.. NOTE::
* CYC1000
* C10LP-RefKit
* DE0
* de0nano
@ -21,7 +22,7 @@ SVF and RBF files are supported.
.. code-block:: bash
quartus_cpf -c -q -g 3.3 -n 12.0MHz p project_name.sof project_name.svf
quartus_cpf -c -q 12.0MHz -g 3.3 -n p project_name.sof project_name.svf
``sof`` to ``rbf`` generation:
@ -30,7 +31,7 @@ SVF and RBF files are supported.
quartus_cpf --option=bitstream_compression=off -c project_name.sof project_name.rbf
.. WARNING::
As mentionned in ``cyclone`` handbooks, real-time decompression is not supported by FPGA in JTAG mode.
As mentioned in ``cyclone`` handbooks, real-time decompression is not supported by FPGA in JTAG mode.
Keep in mind to disable this option.
file load:
@ -41,7 +42,7 @@ file load:
# or
openFPGALoader -b boardname project_name.rbf
with ``boardname`` = ``de0``, ``cyc1000``, ``de0nano``, ``de0nanoSoc`` or ``qmtechCycloneV``.
with ``boardname`` = ``de0``, ``cyc1000``, ``c10lp-refkit``, ``de0nano``, ``de0nanoSoc`` or ``qmtechCycloneV``.
SPI flash
---------
@ -52,12 +53,17 @@ RPD and RBF are supported.
.. code-block:: bash
# CYC1000
quartus_cpf -o auto_create_rpd=on -c -d EPCQ16A -s 10CL025YU256C8G project_name.svf project_name.jic
# C10LP-RefKit
quartus_cpf -o auto_create_rpd=on -c -d EPCQ16A -s 10CL055YU484C8G project_name.svf project_name.jic
file load:
.. code-block:: bash
openFPGALoader -b cyc1000 -r project_name_auto.rpd
openFPGALoader -b boardname -r project_name_auto.rpd
# or
openFPGALoader -b cyc1000 -r project_name.rbf
openFPGALoader -b boardname -r project_name.rbf
with ``boardname`` = ``cyc1000``, ``c10lp-refkit``.

View File

@ -16,13 +16,18 @@ File load:
.. code-block:: bash
openFPGALoader [-b yourboard] impl1/*.jed
openFPGALoader [-b yourboard] [--flash-sector CFG0] impl1/*.jed
where ``yourboard`` may be:
* ``machX02EVN``
* ``machX03EVN``
* ``machXO3SK``
and where ``--flash-sector CFG0`` is needed for the MachXO3D Breakout Board.
``.bit`` may also be used for *machXO2*
SRAM
----
@ -37,6 +42,7 @@ File load:
where ``yourboard`` may be:
* ``machX02EVN``
* ``machX03EVN``
* ``machXO3SK``
iCE40

View File

@ -60,7 +60,7 @@ SPI flash
.. NOTE::
``.bit``, ``.bin``, and ``.mcs`` are supported for FLASH.
``.mcs`` must be generated through vivado with a tcl script like:
``.mcs`` must be generated through Vivado with a tcl script like:
.. code-block:: tcl
@ -94,5 +94,24 @@ File load:
.. NOTE::
``--fpga-part`` is only required if this information is not provided at ``board.hpp`` level or if the board is not
officially supported.
device/packagee format is something like xc7a35tcsg324 (arty model).
device/package format is something like xc7a35tcsg324 (arty model).
See :ghsrc:`src/board.hpp <src/board.hpp>`, or :ghsrc:`spiOverJtag <spiOverJtag>` directory for examples.
Some boards with UltraScale FPGAs, like the VCU118 and KCU16, support the SPIx8 (Dual Quad SPI) configuration.
In this case, the ``spix8`` option ``write_cfgmem`` on the above example can be used to generate two ``.mcs`` files,
to fit bigger designs or for faster programming. Only ``.mcs`` files can be used to program the FPGA in this case.
In this case, to load the two ``.mcs`` files:
.. code-block:: bash
openFPGALoader --board vcu118 -f --target-flash both --bitstream *.runs/impl_1/*_primary.mcs --secondary-bitstream *.runs/impl_1/*_secondary.mcs
On these boards, each SPI flash can be programmed independently with the ``--target-flash`` option.
The default target is the ``primary`` flash.
For example, to program only the secondary flash with arbitrary data not related to FPGA configuration:
.. code-block:: bash
openFPGALoader --board vcu118 -f --target-flash secondary --bitstream arbitrary_data

View File

@ -27,7 +27,7 @@ build() {
-G "MSYS Makefiles" \
-DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \
../../../..
cmake --build .
MSYS2_ARG_CONV_EXCL="-DDATA_DIR=" cmake --build .
}
check() {

View File

@ -1 +1,3 @@
tmp_*
*.bit
*.rbf

View File

@ -36,60 +36,115 @@ elif subpart == "xc7a":
family = "Artix"
tool = "vivado"
elif subpart == "xc7k":
family = "Kintex 7"
tool = "vivado"
device_size = int(part.split('k')[1].split('t')[0])
if device_size <= 160:
family = "Kintex 7"
tool = "vivado"
else:
family = "Kintex7"
tool = "ise"
speed = -2
elif subpart == "xc7s":
family = "Spartan 7"
tool = "vivado"
elif subpart == "xc6s":
family = "Spartan6"
tool = "ise"
speed = -3
elif subpart == "xc3s":
family = "Spartan3E"
tool = "ise"
speed = -4
elif subpart in ["xcvu", "xcku"]:
family = "Xilinx UltraScale"
tool = "vivado"
else:
print("Error: unknown device")
os.sys.exit()
if tool in ["ise", "vivado"]:
pkg_name = {
"xc3s500evq100" : "xc3s_vq100",
"xc6slx9tqg144" : "xc6s_tqg144",
"xc6slx9csg324" : "xc6s_csg324",
"xc6slx16ftg256" : "xc6s_ftg256",
"xc6slx16csg324" : "xc6s_csg324",
"xc6slx45csg324" : "xc6s_csg324",
"xc6slx100fgg484" : "xc6s_fgg484",
"xc6slx150tcsg484" : "xc6s_csg484",
"xc6slx150tfgg484" : "xc6s_fgg484",
"xc7a25tcpg238" : "xc7a_cpg238",
"xc7a25tcsg325" : "xc7a_csg325",
"xc7a35tcpg236" : "xc7a_cpg236",
"xc7a35tcsg324" : "xc7a_csg324",
"xc7a35tftg256" : "xc7a_ftg256",
"xc7a50tcpg236" : "xc7a_cpg236",
"xc7a50tfgg484" : "xc7a_fgg484",
"xc7a50tcsg324" : "xc7a_csg324",
"xc7a50tfgg484" : "xc7a_fgg484",
"xc7a75tfgg484" : "xc7a_fgg484",
"xc7a100tcsg324" : "xc7a_csg324",
"xc7a100tfgg484" : "xc7a_fgg484",
"xc7a100tfgg676" : "xc7a_fgg676",
"xc7a200tsbg484" : "xc7a_sbg484",
"xc7a200tfbg484" : "xc7a_fbg484",
"xc7k160tffg676" : "xc7k_ffg676",
"xc7k325tffg676" : "xc7k_ffg676",
"xc7k325tffg900" : "xc7k_ffg900",
"xc7k420tffg901" : "xc7k_ffg901",
"xc7s25csga225" : "xc7s_csga225",
"xc7s25csga324" : "xc7s_csga324",
"xc7s50csga324" : "xc7s_csga324"
"xc7s50csga324" : "xc7s_csga324",
"xcvu9p-flga2104" : "xcvu9p_flga2104",
"xcvu37p-fsvh2892" : "xcvu37p_fsvh2892",
"xcku5p-ffvb676" : "xcku5p_ffvb676",
}[part]
if tool == "ise":
cst_type = "UCF"
tool_options = {'family': family,
'device': {
"xc6slx16ftg256": "xc6slx16",
"xc6slx16csg324": "xc6slx16",
"xc6slx45csg324": "xc6slx45",
"xc6slx100fgg484": "xc6slx100",
"xc6slx150tfgg484": "xc6slx150t"}[part],
"xc3s500evq100": "xc3s500e",
"xc6slx9tqg144": "xc6slx9",
"xc6slx9csg324": "xc6slx9",
"xc6slx16ftg256": "xc6slx16",
"xc6slx16csg324": "xc6slx16",
"xc6slx45csg324": "xc6slx45",
"xc6slx100fgg484": "xc6slx100",
"xc6slx150tcsg484": "xc6slx150t",
"xc6slx150tfgg484": "xc6slx150t",
"xc7k325tffg676": "xc7k325t",
"xc7k325tffg900": "xc7k325t",
"xc7k420tffg901": "xc7k420t",
}[part],
'package': {
"xc6slx16ftg256": "ftg256",
"xc6slx16csg324": "csg324",
"xc6slx45csg324": "csg324",
"xc6slx100fgg484": "fgg384",
"xc6slx150tfgg484": "fgg484"}[part],
'speed' : -3
"xc3s500evq100": "vq100",
"xc6slx9tqg144": "tqg144",
"xc6slx9csg324": "csg324",
"xc6slx16ftg256": "ftg256",
"xc6slx16csg324": "csg324",
"xc6slx45csg324": "csg324",
"xc6slx100fgg484": "fgg384",
"xc6slx150tcsg484": "csg484",
"xc6slx150tfgg484": "fgg484",
"xc7k325tffg676": "ffg676",
"xc7k325tffg900": "ffg900",
"xc7k420tffg901": "ffg901",
}[part],
'speed' : speed
}
else:
cst_type = "xdc"
tool_options = {'part': part+ '-1'}
if family == "Xilinx UltraScale":
if part in ["xcvu9p-flga2104", "xcku5p-ffvb676"]:
tool_options = {'part': part + '-1-e'}
parameters["secondaryflash"]= {
'datatype': 'int',
'paramtype': 'vlogdefine',
'description': 'secondary flash',
'default': 1}
elif part == "xcvu37p-fsvh2892":
tool_options = {'part': part + '-2L-e'}
else:
tool_options = {'part': part + '-1'}
cst_file = currDir + "constr_" + pkg_name + "." + cst_type.lower()
files.append({'name': currDir + 'xilinx_spiOverJtag.v',
'file_type': 'verilogSource'})
@ -97,10 +152,14 @@ if tool in ["ise", "vivado"]:
else:
full_part = {
"10cl025256": "10CL025YU256C8G",
"10cl055484": "10CL055YU484C8G",
"ep4ce11523": "EP4CE115F23C7",
"ep4ce2217" : "EP4CE22F17C6",
"ep4ce1523" : "EP4CE15F23C8",
"5ce223" : "5CEFA2F23I7",
"5ce523" : "5CEFA5F23I7",
"5ce423" : "5CEBA4F23C8",
"5ce927" : "5CEBA9F27C7",
"5cse423" : "5CSEMA4U23C6",
"5cse623" : "5CSEBA6U23I7"}[part]
files.append({'name': currDir + 'altera_spiOverJtag.v',

View File

@ -1,2 +1,3 @@
set_global_assignment -name ENABLE_INIT_DONE_OUTPUT ON
set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "ACTIVE SERIAL X4"
set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION ON

View File

@ -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;

View File

@ -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;

View File

@ -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}];

View File

@ -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}];

View File

@ -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}]

View File

@ -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}]

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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}];

View File

@ -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

View File

@ -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

View File

@ -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"];

View File

@ -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.

View File

@ -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;

View File

@ -7,6 +7,8 @@ file delete -force $build_path
# Project creation
set grade [dict create \
xc7a25tcpg238 -1 \
xc7a25tcsg325 -1 \
xc7a35tcpg236 -1 \
xc7a35tcsg324 -1 \
xc7a35tftg256 -1 \
@ -16,10 +18,13 @@ set grade [dict create \
xc7a200tsbg484 -1 \
xc7k325tffg676 -1 \
xc7k325tffg900 -2 \
xc7s25csga225 -1 \
xc7s50csga324 -1 \
]
set pkg_name [dict create \
xc7a25tcpg238 xc7a_cpg238 \
xc7a25tcsg325 xc7a_csg325 \
xc7a35tcpg236 xc7a_cpg236 \
xc7a35tcsg324 xc7a_csg324 \
xc7a35tftg256 xc7a_ftg256 \
@ -30,6 +35,7 @@ set pkg_name [dict create \
xc7a200tfbg484 xc7a_fbg484 \
xc7k325tffg676 xc7k_ffg676 \
xc7k325tffg900 xc7k_ffg900 \
xc7s25csga225 xc7s_csga225 \
xc7s50csga324 xc7s_csga324 \
]

View File

@ -1,13 +1,27 @@
module spiOverJtag
(
`ifndef virtexultrascale
output csn,
`ifdef spartan6
output sck,
`endif
`ifdef spartan3e
output sck,
`endif
output sdi_dq0,
input sdo_dq1,
output wpn_dq2,
output hldn_dq3
`endif // virtexultrascale
`ifdef secondaryflash
output sdi_sec_dq0,
input sdo_sec_dq1,
output wpn_sec_dq2,
output hldn_sec_dq3,
output csn_sec
`endif // secondaryflash
);
wire capture, drck, sel, update;
@ -41,7 +55,44 @@ module spiOverJtag
`ifdef spartan6
assign sck = drck;
`else
`else // !spartan6
`ifdef spartan3e
assign sck = drck;
assign runtest = tmp_up_s;
`else // !spartan6 && !spartan3e
`ifdef virtexultrascale
wire [3:0] di;
assign sdo_dq1 = di[1];
wire [3:0] do = {hldn_dq3, wpn_dq2, 1'b0, sdi_dq0};
wire [3:0] dts = 4'b0010;
// secondary BSCANE3 signals
wire sel_sec, drck_sec;
wire sck = (sel_sec) ? drck_sec : drck;
STARTUPE3 #(
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency (ns) for simulation.
) startupe3_inst (
.CFGCLK (), // 1-bit output: Configuration main clock output.
.CFGMCLK (), // 1-bit output: Configuration internal oscillator clock output.
.DI (di), // 4-bit output: Allow receiving on the D input pin.
.EOS (), // 1-bit output: Active-High output signal indicating the End Of Startup.
.PREQ (), // 1-bit output: PROGRAM request to fabric output.
.DO (do), // 4-bit input: Allows control of the D pin output.
.DTS (dts), // 4-bit input: Allows tristate of the D pin.
.FCSBO (csn), // 1-bit input: Controls the FCS_B pin for flash access.
.FCSBTS (1'b0), // 1-bit input: Tristate the FCS_B pin.
.GSR (1'b0), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port).
.GTS (1'b0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name).
.KEYCLEARB(1'b0), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM).
.PACK (1'b0), // 1-bit input: PROGRAM acknowledge input.
.USRCCLKO (sck), // 1-bit input: User CCLK input.
.USRCCLKTS(1'b0), // 1-bit input: User CCLK 3-state enable input.
.USRDONEO (1'b1), // 1-bit input: User DONE pin output control.
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output.
);
`else // !spartan6 && !spartan3e && !virtexultrascale
STARTUPE2 #(
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation.
@ -61,7 +112,28 @@ module spiOverJtag
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output
);
`endif
`endif
`endif
`ifdef spartan3e
BSCAN_SPARTAN3 bscane2_inst (
.CAPTURE(capture), // 1-bit output: CAPTURE output from TAP controller.
.DRCK1 (drck), // 1-bit output: Gated TCK output. When SEL
// is asserted, DRCK toggles when
// CAPTURE or SHIFT are asserted.
.DRCK2 (), // 1-bit output: USER2 function
.RESET (), // 1-bit output: Reset output for TAP controller.
.SEL1 (sel), // 1-bit output: USER1 instruction active output.
.SEL2 (), // 1-bit output: USER2 instruction active output.
.SHIFT (), // 1-bit output: SHIFT output from TAP controller.
.TDI (tdi), // 1-bit output: Test Data Input (TDI) output
// from TAP controller.
.UPDATE (update), // 1-bit output: UPDATE output from TAP controller
.TDO1 (tdo), // 1-bit input: Test Data Output (TDO) input
// for USER1 function.
.TDO2 () // 1-bit input: USER2 function
);
`else
`ifdef spartan6
BSCAN_SPARTAN6 #(
`else
@ -88,5 +160,60 @@ module spiOverJtag
.TDO (tdo) // 1-bit input: Test Data Output (TDO) input
// for USER function.
);
`endif
`ifdef secondaryflash
reg fsm_csn_sec;
wire tdo_sec;
assign wpn_sec_dq2 = 1'b1;
assign hldn_sec_dq3 = 1'b1;
assign sdi_sec_dq0 = tdi;
assign tdo_sec = (sel_sec) ? sdo_sec_dq1 : tdi;
assign csn_sec = fsm_csn_sec;
wire tmp_cap_sec_s = capture && sel_sec;
wire tmp_up_sec_s = update && sel_sec;
always @(posedge drck_sec, posedge runtest) begin
if (runtest) begin
fsm_csn_sec <= 1'b1;
end else begin
if (tmp_cap_sec_s) begin
fsm_csn_sec <= 1'b0;
end else if (tmp_up_sec_s) begin
fsm_csn_sec <= 1'b1;
end else begin
fsm_csn_sec <= fsm_csn_sec;
end
end
end
BSCANE2 #(
.JTAG_CHAIN(2) // Value for USER command.
) bscane2_sec_inst (
.CAPTURE(), // 1-bit output: CAPTURE output from TAP controller.
.DRCK (drck_sec), // 1-bit output: Gated TCK output. When SEL
// is asserted, DRCK toggles when
// CAPTURE or SHIFT are asserted.
.RESET (), // 1-bit output: Reset output for TAP controller.
.RUNTEST(), // 1-bit output: Output asserted when TAP
// controller is in Run Test/Idle state.
.SEL (sel_sec), // 1-bit output: USER instruction active output.
.SHIFT (), // 1-bit output: SHIFT output from TAP controller.
.TCK (), // 1-bit output: Test Clock output.
// Fabric connection to TAP Clock pin.
.TDI (), // 1-bit output: Test Data Input (TDI) output
// from TAP controller.
.TMS (), // 1-bit output: Test Mode Select output.
// Fabric connection to TAP.
.UPDATE (), // 1-bit output: UPDATE output from TAP controller
.TDO (tdo_sec) // 1-bit input: Test Data Output (TDO) input
// for USER function.
);
`else // secondaryflash
assign sel_sec = 1'b0;
assign drck_sec = 1'b0;
`endif // secondaryflash
endmodule

View File

@ -9,26 +9,31 @@
#include <string>
#include "common.hpp"
#include "jtag.hpp"
#include "device.hpp"
#include "epcq.hpp"
#include "progressBar.hpp"
#include "rawParser.hpp"
#if defined (_WIN64) || defined (_WIN32)
#include "pathHelper.hpp"
#endif
#define IDCODE 6
#define USER0 0x0C
#define USER1 0x0E
#define BYPASS 0x3FF
#define IRLENGTH 10
// DATA_DIR is defined at compile time.
#define BIT_FOR_FLASH (DATA_DIR "/openFPGALoader/test_sfl.svf")
Altera::Altera(Jtag *jtag, const std::string &filename,
const std::string &file_type, Device::prog_type_t prg_type,
const std::string &device_package, bool verify, int8_t verbose):
const std::string &device_package,
const std::string &spiOverJtagPath, bool verify, int8_t verbose,
bool skip_load_bridge, bool skip_reset):
Device(jtag, filename, file_type, verify, verbose),
SPIInterface(filename, verbose, 256, verify),
_svf(_jtag, _verbose), _device_package(device_package),
SPIInterface(filename, verbose, 256, verify, skip_load_bridge,
skip_reset),
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath),
_vir_addr(0x1000), _vir_length(14)
{
if (prg_type == Device::RD_FLASH) {
@ -148,19 +153,46 @@ void Altera::programMem(RawParser &_bit)
_jtag->set_state(Jtag::RUN_TEST_IDLE);
}
bool Altera::post_flash_access()
{
if (_skip_reset)
printInfo("Skip resetting device");
else
reset();
return true;
}
bool Altera::prepare_flash_access()
{
if (_skip_load_bridge) {
printInfo("Skip loading bridge for spiOverjtag");
return true;
}
return load_bridge();
}
bool Altera::load_bridge()
{
if (_device_package.empty()) {
printError("Can't program SPI flash: missing device-package information");
return false;
std::string bitname;
if (!_spiOverJtagPath.empty()) {
bitname = _spiOverJtagPath;
} else {
if (_device_package.empty()) {
printError("Can't program SPI flash: missing device-package information");
return false;
}
bitname = get_shell_env_var("OPENFPGALOADER_SOJ_DIR", DATA_DIR "/openFPGALoader");
#ifdef HAS_ZLIB
bitname += "/spiOverJtag_" + _device_package + ".rbf.gz";
#else
bitname += "/spiOverJtag_" + _device_package + ".rbf";
#endif
}
// DATA_DIR is defined at compile time.
std::string bitname = DATA_DIR "/openFPGALoader/spiOverJtag_";
#ifdef HAS_ZLIB
bitname += _device_package + ".rbf.gz";
#else
bitname += _device_package + ".rbf";
#if defined (_WIN64) || defined (_WIN32)
/* Convert relative path embedded at compile time to an absolute path */
bitname = PathHelper::absolutePath(bitname);
#endif
std::cout << "use: " << bitname << std::endl;
@ -190,13 +222,9 @@ void Altera::program(unsigned int offset, bool unprotect_flash)
*/
/* mem mode -> svf */
if (_mode == Device::MEM_MODE) {
if (_file_extension == "svf") {
_svf.parse(_filename);
} else {
RawParser _bit(_filename, false);
_bit.parse();
programMem(_bit);
}
RawParser _bit(_filename, false);
_bit.parse();
programMem(_bit);
} else if (_mode == Device::SPI_MODE) {
// reverse only bitstream raw binaries data no
bool reverseOrder = false;

View File

@ -20,7 +20,9 @@ class Altera: public Device, SPIInterface {
const std::string &file_type,
Device::prog_type_t prg_type,
const std::string &device_package,
bool verify, int8_t verbose);
const std::string &spiOverJtagPath,
bool verify, int8_t verbose,
bool skip_load_bridge, bool skip_reset);
~Altera();
void programMem(RawParser &_bit);
@ -56,6 +58,12 @@ class Altera: public Device, SPIInterface {
bool unprotect_flash() override {
return SPIInterface::unprotect_flash();
}
/*!
* \brief bulk erase SPI flash
*/
bool bulk_erase_flash() override {
return SPIInterface::bulk_erase_flash();
}
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
uint32_t len) override;
@ -64,8 +72,8 @@ class Altera: public Device, SPIInterface {
uint32_t timeout, bool verbose = false) override;
protected:
bool prepare_flash_access() override {return load_bridge();}
bool post_flash_access() override {reset(); return true;}
bool prepare_flash_access() override;
bool post_flash_access() override;
private:
/*!
@ -92,8 +100,8 @@ class Altera: public Device, SPIInterface {
void shiftVDR(uint8_t * tx, uint8_t * rx, uint32_t len,
int end_state = Jtag::UPDATE_DR, bool debug = false);
SVF_jtag _svf;
std::string _device_package;
std::string _spiOverJtagPath; /**< spiOverJtag explicit path */
uint32_t _vir_addr; /**< addr affected to virtual jtag */
uint32_t _vir_length; /**< length of virtual jtag IR */
};

View File

@ -29,7 +29,7 @@ Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type, bool verify, int8_t verbose):
Device(jtag, filename, file_type, verify, verbose),
SPIInterface(filename, verbose, 0, verify), _svf(_jtag, _verbose)
SPIInterface(filename, verbose, 0, verify)
{
if (prg_type == Device::RD_FLASH) {
_mode = Device::READ_MODE;
@ -64,11 +64,6 @@ void Anlogic::program(unsigned int offset, bool unprotect_flash)
if (_mode == Device::NONE_MODE)
return;
if (_file_extension == "svf") {
_svf.parse(_filename);
return;
}
AnlogicBitParser bit(_filename, (_mode == Device::MEM_MODE), _verbose);
printInfo("Parse file ", false);

View File

@ -40,6 +40,13 @@ class Anlogic: public Device, SPIInterface {
return SPIInterface::unprotect_flash();
}
/*!
* \brief bulk erase SPI flash
*/
bool bulk_erase_flash() override {
return SPIInterface::bulk_erase_flash();
}
/*!
* \brief dump len byte from base_addr from SPI flash
* \param[in] base_addr: start offset
@ -66,8 +73,6 @@ class Anlogic: public Device, SPIInterface {
*/
virtual bool post_flash_access() override {reset(); return true;}
private:
SVF_jtag _svf;
};
#endif // SRC_ANLOGIC_HPP_

View File

@ -107,11 +107,11 @@ int AnlogicBitParser::parse()
_bit_data.clear();
for (auto it = blocks.begin(); it != blocks.end(); it++) {
for (size_t pos = 0; pos < it->size(); pos++) {
for (size_t xpos = 0; xpos < it->size(); xpos++) {
if (_reverseOrder == true)
_bit_data += reverseByte(((*it)[pos]));
_bit_data += reverseByte(((*it)[xpos]));
else
_bit_data += ((*it)[pos]);
_bit_data += ((*it)[xpos]);
}
}
_bit_length = _bit_data.size() * 8;

View File

@ -44,9 +44,8 @@ enum analogicCableFreq {
ANLOGICCABLE_FREQ_90K = 0xff
};
AnlogicCable::AnlogicCable(uint32_t clkHZ, uint8_t verbose):
_verbose(verbose),
dev_handle(NULL), usb_ctx(NULL), _tdi(0), _tms(0)
AnlogicCable::AnlogicCable(uint32_t clkHZ):
dev_handle(NULL), usb_ctx(NULL)
{
int ret;

View File

@ -19,7 +19,7 @@
class AnlogicCable : public JtagInterface {
public:
AnlogicCable(uint32_t clkHZ, uint8_t verbose);
AnlogicCable(uint32_t clkHZ);
virtual ~AnlogicCable();
int setClkFreq(uint32_t clkHZ) override;
@ -43,13 +43,9 @@ class AnlogicCable : public JtagInterface {
int flush() override;
private:
uint8_t _verbose;
int write(uint8_t *in_buf, uint8_t *out_buf, int len, int rd_len);
libusb_device_handle *dev_handle;
libusb_context *usb_ctx;
uint8_t _tdi;
uint8_t _tms;
};
#endif // SRC_ANLOGICCABLE_HPP_

View File

@ -38,7 +38,7 @@ int BitParser::parseHeader()
int pos_data = 0;
int ret = 1;
short length;
string tmp(64, ' ');
string tmp;
int pos, prev_pos;
/* Field 1 : misc header */
@ -109,10 +109,21 @@ int BitParser::parse()
/* process all field */
int pos = parseHeader();
/* rest of the file is data to send */
_bit_data.resize(_raw_data.size() - pos);
std::move(_raw_data.begin() + pos, _raw_data.end(), _bit_data.begin());
_bit_length = _bit_data.size();
/* _bit_length is length of data to send */
int rest_of_file_length = _file_size - pos;
if (_bit_length < rest_of_file_length) {
printWarn("File is longer than bitstream length declared in the header: " +
std::to_string(rest_of_file_length) + " vs " + std::to_string(_bit_length)
);
} else if (_bit_length > rest_of_file_length) {
printError("File is shorter than bitstream length declared in the header: " +
std::to_string(rest_of_file_length) + " vs " + std::to_string(_bit_length)
);
return 1;
}
_bit_data.resize(_bit_length);
std::move(_raw_data.begin() + pos, _raw_data.begin() + pos + _bit_length, _bit_data.begin());
if (_reverseOrder) {
for (int i = 0; i < _bit_length; i++) {

View File

@ -125,7 +125,7 @@ static std::map <std::string, target_board_t> board_list = {
JTAG_BOARD("colorlight", "", "", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("colorlight-i5", "", "cmsisdap", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("colorlight-i9", "", "cmsisdap", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "ft2232",0,0,CABLE_DEFAULT),
JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "ft2232", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("c10lp-refkit", "10cl055484", "ft2232", 0, 0, CABLE_DEFAULT),

View File

@ -3,13 +3,12 @@
* Copyright (C) 2019 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*/
#ifndef CABLE_HPP
#define CABLE_HPP
#ifndef SRC_CABLE_HPP_
#define SRC_CABLE_HPP_
#include <map>
#include <string>
#include "ftdipp_mpsse.hpp"
#include <cstdint>
/*!
* \brief define type of communication
@ -19,51 +18,115 @@ enum communication_type {
MODE_CH552_JTAG, /*! ch552_jtag firmware */
MODE_FTDI_BITBANG, /*! used with ft232RL/ft231x */
MODE_FTDI_SERIAL, /*! ft2232, ft232H */
MODE_JLINK, /*! ft2232, ft232H */
MODE_DIRTYJTAG, /*! JTAG probe firmware for STM32F1 */
MODE_USBBLASTER, /*! JTAG probe firmware for USBBLASTER */
MODE_CMSISDAP, /*! CMSIS-DAP JTAG probe */
MODE_DFU, /*! DFU based probe */
MODE_XVC_CLIENT, /*! Xilinx Virtual Cable client */
MODE_LIBGPIOD_BITBANG, /*! Bitbang gpio pins */
MODE_JETSONNANO_BITBANG, /*! Bitbang gpio pins */
MODE_REMOTEBITBANG, /*! Remote Bitbang mode */
};
/*!
* \brief FTDI specific configuration structure
*/
typedef struct {
int type;
FTDIpp_MPSSE::mpsse_bit_config config;
} cable_t;
int interface; /*! FTDI interface (A, B, C, D) */
int bit_low_val; /*! xDBUS 0-7 default value */
int bit_low_dir; /*! xDBUS 0-7 default direction (0: in, 1: out) */
int bit_high_val; /*! xCBUS 0-7 default value */
int bit_high_dir; /*! xCBUS 0-7 default direction (0: in, 1: out) */
int index;
int status_pin;
} mpsse_bit_config;
/*!
* \brief FTDI interface ID
*/
enum ftdi_if {
FTDI_INTF_A = 1,
FTDI_INTF_B = 2,
FTDI_INTF_C = 3,
FTDI_INTF_D = 4
};
/*!
* \brief cable characteristics
*/
struct cable_t {
communication_type type; /*! see enum communication_type */
int vid; /*! Vendor ID */
int pid; /*! Product ID */
uint8_t bus_addr; /*! bus number (must be set to 0: user defined */
uint8_t device_addr; /*! device number (must be set 0: user defined */
mpsse_bit_config config; /*! FTDI specific configurations */
};
/* FTDI serial (MPSSE) configuration */
#define FTDI_SER(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \
{MODE_FTDI_SERIAL, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}}
/* FTDI bitbang configuration */
#define FTDI_BB(_vid, _pid, _intf, _blv, _bld, _bhv, _bhd) \
{MODE_FTDI_BITBANG, _vid, _pid, 0, 0, {_intf, _blv, _bld, _bhv, _bhd, 0, -1}}
/* CMSIS DAP configuration */
#define CMSIS_CL(_vid, _pid) \
{MODE_CMSISDAP, _vid, _pid, 0, 0, {}}
/* Others cable configuration */
#define CABLE_DEF(_type, _vid, _pid) \
{_type, _vid, _pid, 0, 0, {}}
static std::map <std::string, cable_t> cable_list = {
// last 4 bytes are ADBUS7-0 value, ADBUS7-0 direction, ACBUS7-0 value, ACBUS7-0 direction
// some cables requires explicit values on some of the I/Os
{"anlogicCable", {MODE_ANLOGICCABLE, {}}},
{"arm-usb-ocd-h", {MODE_FTDI_SERIAL, {0x15ba, 0x002b, INTERFACE_A, 0x08, 0x1B, 0x09, 0x0B}}},
{"bus_blaster", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x1B, 0x08, 0x0B}}},
{"bus_blaster_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x08, 0x0B}}},
{"ch552_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
{"cmsisdap", {MODE_CMSISDAP, {0x0d28, 0x0204, 0, 0, 0, 0, 0 }}},
{"gatemate_pgm", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x10, 0x9B, 0x14, 0x17}}},
{"gatemate_evb_jtag", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x10, 0x1B, 0x00, 0x01}}},
{"gatemate_evb_spi", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x00, 0x1B, 0x00, 0x01}}},
{"dfu", {MODE_DFU, {}}},
{"digilent", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
{"digilent_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0xe8, 0xeb, 0x00, 0x60}}},
{"digilent_hs2", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
{"digilent_hs3", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x88, 0x8B, 0x20, 0x30}}},
{"digilent_ad", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x80, 0x80}}},
{"dirtyJtag", {MODE_DIRTYJTAG, {}}},
{"efinix_spi_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
{"efinix_jtag_ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_B, 0x08, 0x8B, 0x00, 0x00}}},
{"efinix_spi_ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x8B, 0x00, 0x00}}},
{"ft2232", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
{"ft2232_b", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x0B, 0x00, 0x00}}},
{"ft231X", {MODE_FTDI_BITBANG, {0x0403, 0x6015, INTERFACE_A, 0x00, 0x00, 0x00, 0x00}}},
{"ft232", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
{"ft232RL", {MODE_FTDI_BITBANG, {0x0403, 0x6001, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
{"ft4232", {MODE_FTDI_SERIAL, {0x0403, 0x6011, INTERFACE_A, 0x08, 0x0B, 0x08, 0x0B}}},
{"ecpix5-debug", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_A, 0xF8, 0xFB, 0xFF, 0xFF}}},
{"jtag-smt2-nc", {MODE_FTDI_SERIAL, {0x0403, 0x6014, INTERFACE_A, 0xe8, 0xeb, 0x00, 0x60}}},
{"orbtrace", {MODE_CMSISDAP, {0x1209, 0x3443, 0, 0, 0, 0, 0 }}},
{"tigard", {MODE_FTDI_SERIAL, {0x0403, 0x6010, INTERFACE_B, 0x08, 0x3B, 0x00, 0x00}}},
{"usb-blaster", {MODE_USBBLASTER, {0x09Fb, 0x6001, 0, 0, 0, 0, 0 }}},
{"usb-blasterII", {MODE_USBBLASTER, {0x09Fb, 0x6810, 0, 0, 0, 0, 0 }}},
{"anlogicCable", CABLE_DEF(MODE_ANLOGICCABLE, 0x0547, 0x1002)},
{"arm-usb-ocd-h", FTDI_SER(0x15ba, 0x002b, FTDI_INTF_A, 0x08, 0x1B, 0x09, 0x0B)},
{"bus_blaster", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x1B, 0x08, 0x0B)},
{"bus_blaster_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x08, 0x0B)},
{"ch552_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
{"cmsisdap", CMSIS_CL(0x0d28, 0x0204 )},
{"gatemate_pgm", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x10, 0x9B, 0x14, 0x17)},
{"gatemate_evb_jtag", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x10, 0x1B, 0x00, 0x01)},
{"gatemate_evb_spi", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x00, 0x1B, 0x00, 0x01)},
{"dfu", CABLE_DEF(MODE_DFU, 0, 0 )},
{"digilent", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
{"digilent_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0xe8, 0xeb, 0x00, 0x60)},
{"digilent_hs2", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
{"digilent_hs3", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x88, 0x8B, 0x20, 0x30)},
{"digilent_ad", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x80, 0x80)},
{"dirtyJtag", CABLE_DEF(MODE_DIRTYJTAG, 0x1209, 0xC0CA )},
{"efinix_spi_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
{"efinix_jtag_ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_B, 0x08, 0x8B, 0x00, 0x00)},
{"efinix_spi_ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x8B, 0x00, 0x00)},
{"ft2232", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
{"ft2232_b", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x0B, 0x00, 0x00)},
{"ft231X", FTDI_BB (0x0403, 0x6015, FTDI_INTF_A, 0x00, 0x00, 0x00, 0x00)},
{"ft232", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
{"ft232RL", FTDI_BB( 0x0403, 0x6001, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
{"ft4232", FTDI_SER(0x0403, 0x6011, FTDI_INTF_A, 0x08, 0x0B, 0x08, 0x0B)},
{"ecpix5-debug", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0xF8, 0xFB, 0xFF, 0xFF)},
{"jlink", CABLE_DEF(MODE_JLINK, 0x1366, 0x0105 )},
{"jlink_base", CABLE_DEF(MODE_JLINK, 0x1366, 0x0101 )},
{"jtrace_pro", CABLE_DEF(MODE_JLINK, 0x1366, 0x1020 )},
{"jtag-smt2-nc", FTDI_SER(0x0403, 0x6014, FTDI_INTF_A, 0xe8, 0xeb, 0x00, 0x60)},
{"lpc-link2", CMSIS_CL(0x1fc9, 0x0090 )},
{"orbtrace", CMSIS_CL(0x1209, 0x3443 )},
{"papilio", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x08, 0x0B, 0x09, 0x0B)},
{"steppenprobe", FTDI_SER(0x0403, 0x6010, FTDI_INTF_A, 0x58, 0xFB, 0x00, 0x99)},
{"tigard", FTDI_SER(0x0403, 0x6010, FTDI_INTF_B, 0x08, 0x3B, 0x00, 0x00)},
{"usb-blaster", CABLE_DEF(MODE_USBBLASTER, 0x09Fb, 0x6001 )},
{"usb-blasterII", CABLE_DEF(MODE_USBBLASTER, 0x09Fb, 0x6810 )},
{"xvc-client", CABLE_DEF(MODE_XVC_CLIENT, 0x0000, 0x0000 )},
#ifdef ENABLE_LIBGPIOD
{"libgpiod", CABLE_DEF(MODE_LIBGPIOD_BITBANG, 0, 0x0000 )},
#endif
#ifdef ENABLE_JETSONNANOGPIO
{"jetson-nano-gpio", {MODE_JETSONNANO_BITBANG, {}}},
#endif
#ifdef ENABLE_REMOTEBITBANG
{"remote-bitbang", CABLE_DEF(MODE_REMOTEBITBANG, 0x0000, 0x0000 )},
#endif
};
#endif
#endif // SRC_CABLE_HPP_

View File

@ -29,11 +29,12 @@ using namespace std;
#define display(...) do {}while(0)
#endif
CH552_jtag::CH552_jtag(const FTDIpp_MPSSE::mpsse_bit_config &cable,
string dev, const string &serial, uint32_t clkHZ, uint8_t verbose):
CH552_jtag::CH552_jtag(const cable_t &cable,
const string &dev, const string &serial, uint32_t clkHZ,
uint8_t verbose):
FTDIpp_MPSSE(cable, dev, serial, clkHZ, verbose), _to_read(0)
{
init_internal(cable);
init_internal(cable.config);
}
CH552_jtag::~CH552_jtag()
@ -59,7 +60,7 @@ CH552_jtag::~CH552_jtag()
"Loopback failed, expect problems on later runs %d\n", read);
}
void CH552_jtag::init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable)
void CH552_jtag::init_internal(const mpsse_bit_config &cable)
{
display("iProduct : %s\n", _iproduct);
@ -181,7 +182,7 @@ int CH552_jtag::writeTDI(uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last)
*/
int tx_buff_size = mpsse_get_buffer_size();
int real_len = (last) ? len - 1 : len; // if its a buffer in a big send send len
// else supress last bit -> with TMS
// else suppress last bit -> with TMS
int nb_byte = real_len >> 3; // number of byte to send
int nb_bit = (real_len & 0x07); // residual bits
int xfer = tx_buff_size - 7; // 2 byte for opcode and size 2 time
@ -286,7 +287,7 @@ int CH552_jtag::writeTDI(uint8_t *tdi, uint8_t *tdo, uint32_t len, bool last)
unsigned char last_bit = (tdi) ? *tx_ptr : 0;
/* next: serie of bit to send: inconditionnaly write AND read
/* next: serie of bit to send: unconditionally write AND read
*/
if (nb_bit != 0) {
display("%s read/write %d bit\n", __func__, nb_bit);

View File

@ -10,6 +10,7 @@
#include <string>
#include <vector>
#include "cable.hpp"
#include "jtagInterface.hpp"
#include "ftdipp_mpsse.hpp"
@ -22,7 +23,7 @@
class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
public:
CH552_jtag(const FTDIpp_MPSSE::mpsse_bit_config &cable, std::string dev,
CH552_jtag(const cable_t &cable, const std::string &dev,
const std::string &serial, uint32_t clkHZ, uint8_t verbose = false);
virtual ~CH552_jtag();
@ -48,7 +49,7 @@ class CH552_jtag : public JtagInterface, private FTDIpp_MPSSE {
int flush() override;
private:
void init_internal(const FTDIpp_MPSSE::mpsse_bit_config &cable);
void init_internal(const mpsse_bit_config &cable);
uint32_t _to_read; /*!< amount of byte to read */
};
#endif // SRC_CH552_JTAG_HPP_

View File

@ -88,8 +88,8 @@ enum cmsisdap_status {
DAP_ERROR = 0xff
};
CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
_device_idx(0), _vid(vid), _pid(pid),
CmsisDAP::CmsisDAP(const cable_t &cable, int index, uint8_t verbose):_verbose(verbose),
_device_idx(0), _vid(cable.vid), _pid(cable.pid),
_serial_number(L""), _dev(NULL), _num_tms(0), _is_connect(false)
{
std::vector<struct hid_device_info *> dev_found;
@ -109,7 +109,7 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
* if vid/pid are 0 this function return all;
* if vid/pid are >0 only one (or 0) device returned
*/
devs = hid_enumerate(vid, pid);
devs = hid_enumerate(cable.vid, cable.pid);
for (cur_dev = devs; NULL != cur_dev; cur_dev = cur_dev->next) {
dev_found.push_back(cur_dev);
@ -121,18 +121,36 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
throw std::runtime_error("No device found");
}
/* more than one device: can't continue without more information */
if (dev_found.size() > 1) {
if (dev_found.size() > 1 && index == -1) {
hid_exit();
throw std::runtime_error(
"Error: more than one device. Please provides VID/PID");
"Error: more than one device. Please provides VID/PID or cable-index");
}
/* if index check for if interface exist */
if (index != -1) {
bool found = false;
for (size_t i = 0; i < dev_found.size(); i++) {
if (dev_found[i]->interface_number == index) {
found = true;
_device_idx = i;
break;
}
}
if (!found) {
hid_exit();
throw std::runtime_error(
"Error: no compatible interface with index " + std::to_string(_device_idx));
}
}
printInfo("Found " + std::to_string(dev_found.size()) + " compatible device:");
for (size_t i = 0; i < dev_found.size(); i++) {
char val[256];
snprintf(val, sizeof(val), "\t0x%04x 0x%04x %ls",
snprintf(val, sizeof(val), "\t0x%04x 0x%04x 0x%d %ls",
dev_found[i]->vendor_id,
dev_found[i]->product_id,
dev_found[i]->interface_number,
dev_found[i]->product_string);
printInfo(val);
}
@ -144,6 +162,10 @@ CmsisDAP::CmsisDAP(int vid, int pid, uint8_t verbose):_verbose(verbose),
_serial_number = wstring(dev_found[_device_idx]->serial_number);
/* open the device */
_dev = hid_open_path(dev_found[_device_idx]->path);
if (!_dev) {
throw std::runtime_error(
std::string("Couldn't open device. Check permissions for ") + dev_found[_device_idx]->path);
}
/* cleanup enumeration */
hid_free_enumeration(devs);

View File

@ -12,18 +12,20 @@
#include <string>
#include <vector>
#include "cable.hpp"
#include "jtagInterface.hpp"
class CmsisDAP: public JtagInterface {
public:
/*!
* \brief contructor: open device with vid/pid if != 0
* \brief constructor: open device with vid/pid if != 0
* else search for a compatible device
* \param[in] vid: vendor id
* \param[in] pid: product id
* \param[in] index: interface number
* \param[in] verbose: verbose level 0 normal, 1 verbose
*/
CmsisDAP(const int vid, const int pid, uint8_t verbose);
CmsisDAP(const cable_t &cable, int index, uint8_t verbose);
~CmsisDAP();
@ -77,13 +79,13 @@ class CmsisDAP: public JtagInterface {
private:
/*!
* \brief connect device in JTAG mode
* \return 1 if success <= 0 otherwhise
* \return 1 if success <= 0 otherwise
*/
int dapConnect();
/*!
* \brief disconnect device
* \return 1 if success <= 0 otherwhise
* \return 1 if success <= 0 otherwise
*/
int dapDisconnect();
int dapResetTarget();

View File

@ -12,14 +12,15 @@
CologneChip::CologneChip(FtdiSpi *spi, const std::string &filename,
const std::string &file_type, Device::prog_type_t prg_type,
uint16_t rstn_pin, uint16_t done_pin, uint16_t failn_pin, uint16_t oen_pin,
uint16_t rstn_pin, uint16_t done_pin, uint16_t fail_pin, uint16_t oen_pin,
bool verify, int8_t verbose) :
Device(NULL, filename, file_type, verify, verbose), _rstn_pin(rstn_pin),
_done_pin(done_pin), _failn_pin(failn_pin), _oen_pin(oen_pin)
_done_pin(done_pin), _fail_pin(fail_pin), _oen_pin(oen_pin)
{
_spi = spi;
_spi->gpio_set_input(_done_pin | _failn_pin);
_spi->gpio_set_input(_done_pin | _fail_pin);
_spi->gpio_set_output(_rstn_pin | _oen_pin);
_ftdi_jtag = nullptr;
if (prg_type == Device::WR_SRAM) {
_mode = Device::MEM_MODE;
@ -34,6 +35,7 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
bool verify, int8_t verbose) :
Device(jtag, filename, file_type, verify, verbose)
{
_spi = nullptr;
/* check which cable/board we're using in order to select pin definitions */
std::string spi_board_name;
if (board_name != "-") {
@ -47,13 +49,13 @@ CologneChip::CologneChip(Jtag* jtag, const std::string &filename,
/* pin configurations valid for both evaluation board and programer */
_rstn_pin = spi_board->reset_pin;
_done_pin = spi_board->done_pin;
_failn_pin = DBUS6;
_fail_pin = DBUS6;
_oen_pin = spi_board->oe_pin;
/* cast _jtag->_jtag from JtagInterface to FtdiJtagMPSSE to access GPIO */
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(_jtag->_jtag);
_ftdi_jtag->gpio_set_input(_done_pin | _failn_pin);
_ftdi_jtag->gpio_set_input(_done_pin | _fail_pin);
_ftdi_jtag->gpio_set_output(_rstn_pin | _oen_pin);
if (prg_type == Device::WR_SRAM) {
@ -72,7 +74,7 @@ void CologneChip::reset()
_spi->gpio_clear(_rstn_pin | _oen_pin);
usleep(SLEEP_US);
_spi->gpio_set(_rstn_pin);
} else if (_ftdi_jtag) {
} else {
_ftdi_jtag->gpio_clear(_rstn_pin | _oen_pin);
usleep(SLEEP_US);
_ftdi_jtag->gpio_set(_rstn_pin);
@ -80,24 +82,24 @@ void CologneChip::reset()
}
/**
* Obtain CFG_DONE and ~CFG_FAILED signals. Configuration is successfull iff
* CFG_DONE=true and ~CFG_FAILED=false.
* Obtain CFG_DONE and CFG_FAILED signals. Configuration is successful if
* CFG_DONE=true and CFG_FAILED=false.
*/
bool CologneChip::cfgDone()
{
uint16_t status = 0;
if (_spi) {
status = _spi->gpio_get(true);
} else if (_ftdi_jtag) {
} else {
status = _ftdi_jtag->gpio_get(true);
}
bool done = (status & _done_pin) > 0;
bool fail = (status & _failn_pin) == 0;
bool fail = (status & _fail_pin) > 0;
return (done && !fail);
}
/**
* Prints information if configuration was successfull.
* Prints information if configuration was successful.
*/
void CologneChip::waitCfgDone()
{
@ -118,13 +120,12 @@ void CologneChip::waitCfgDone()
/**
* Dump flash contents to file. Works in both SPI and JTAG-SPI-bypass mode.
*/
bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
uint32_t len)
bool CologneChip::dumpFlash(uint32_t base_addr, uint32_t len)
{
if (_spi) {
/* enable output and hold reset */
_spi->gpio_clear(_rstn_pin | _oen_pin);
} else if (_ftdi_jtag) {
} else {
/* enable output and disable reset */
_ftdi_jtag->gpio_clear(_oen_pin);
_ftdi_jtag->gpio_set(_rstn_pin);
@ -137,12 +138,12 @@ bool CologneChip::dumpFlash(const std::string &filename, uint32_t base_addr,
if (_spi) {
flash = new SPIFlash(reinterpret_cast<SPIInterface *>(_spi), false,
_verbose);
} else if (_ftdi_jtag) {
} else {
flash = new SPIFlash(this, false, _verbose);
}
flash->reset();
flash->power_up();
flash->dump(filename, base_addr, len);
flash->dump(_filename, base_addr, len);
} catch (std::exception &e) {
printError("Fail");
printError(std::string(e.what()));

View File

@ -24,7 +24,7 @@ class CologneChip: public Device, SPIInterface {
public:
CologneChip(FtdiSpi *spi, const std::string &filename,
const std::string &file_type, Device::prog_type_t prg_type,
uint16_t rstn_pin, uint16_t done_pin, uint16_t failn_pin, uint16_t oen_pin,
uint16_t rstn_pin, uint16_t done_pin, uint16_t fail_pin, uint16_t oen_pin,
bool verify, int8_t verbose);
CologneChip(Jtag* jtag, const std::string &filename,
const std::string &file_type, Device::prog_type_t prg_type,
@ -34,12 +34,14 @@ class CologneChip: public Device, SPIInterface {
bool cfgDone();
void waitCfgDone();
bool dumpFlash(const std::string &filename, uint32_t base_addr, uint32_t len);
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
virtual bool protect_flash(uint32_t len) override {
(void) len;
printError("protect flash not supported"); return false;}
virtual bool unprotect_flash() override {
printError("unprotect flash not supported"); return false;}
virtual bool bulk_erase_flash() override {
printError("bulk erase flash not supported"); return false;}
void program(unsigned int offset, bool unprotect_flash) override;
int idCode() override {return 0;}
@ -64,7 +66,7 @@ class CologneChip: public Device, SPIInterface {
FtdiJtagMPSSE *_ftdi_jtag = NULL;
uint16_t _rstn_pin;
uint16_t _done_pin;
uint16_t _failn_pin;
uint16_t _fail_pin;
uint16_t _oen_pin;
};

21
src/common.cpp Normal file
View File

@ -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);
}

20
src/common.hpp Normal file
View File

@ -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_

View File

@ -35,7 +35,7 @@ ConfigBitstreamParser::ConfigBitstreamParser(const string &filename, int mode,
{
(void) mode;
if (!filename.empty()) {
uint32_t offset = filename.find_last_of(".");
size_t offset = filename.find_last_of(".");
FILE *_fd = fopen(filename.c_str(), "rb");
if (!_fd) {

View File

@ -731,7 +731,7 @@ namespace cxxopts
}
// The fallback parser. It uses the stringstream parser to parse all types
// that have not been overloaded explicitly. It has to be placed in the
// that have not been overloaded explicitly. It has to be placed in the
// source code before all other more specialized templates.
template <typename T>
void

View File

@ -48,10 +48,13 @@ class Device {
printError("dump flash not supported"); return false;}
virtual bool protect_flash(uint32_t len) = 0;
virtual bool unprotect_flash() = 0;
virtual bool bulk_erase_flash() = 0;
virtual int idCode() = 0;
virtual void reset();
virtual bool connectJtagToMCU() {return false;}
protected:
Jtag *_jtag;
std::string _filename;

View File

@ -46,8 +46,8 @@ enum dfu_cmd {
* - index as jtag chain (fix issue when more than one device connected)
*/
DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
int16_t altsetting,
DFU::DFU(const string &filename, bool bypass_bitstream,
uint16_t vid, uint16_t pid, int16_t altsetting,
int verbose_lvl):_verbose(verbose_lvl > 0), _debug(verbose_lvl > 1),
_quiet(verbose_lvl < 0), dev_idx(0), _vid(0), _pid(0),
_altsetting(altsetting),
@ -55,38 +55,43 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
_bit(NULL)
{
struct dfu_status status;
int dfu_vid = 0, dfu_pid = 0;
int dfu_vid = 0, dfu_pid = 0, ret;
printInfo("Open file ", false);
printInfo("Open file : ", false);
try {
_bit = new DFUFileParser(filename, _verbose > 0);
printSuccess("DONE");
} catch (std::exception &e) {
printError("FAIL");
throw runtime_error("Error: Fail to open file");
}
if (bypass_bitstream) {
_bit = nullptr;
printInfo("bypassed");
} else {
try {
_bit = new DFUFileParser(filename, _verbose > 0);
printSuccess("DONE");
} catch (std::exception &e) {
printError("FAIL");
throw runtime_error("Error: Fail to open file");
}
printInfo("Parse file ", false);
try {
_bit->parse();
printSuccess("DONE");
} catch (std::exception &e) {
printError("FAIL");
delete _bit;
throw runtime_error("Error: Fail to parse file");
}
printInfo("Parse file ", false);
try {
_bit->parse();
printSuccess("DONE");
} catch (std::exception &e) {
printError("FAIL");
delete _bit;
throw runtime_error("Error: Fail to parse file");
}
if (_verbose > 0)
_bit->displayHeader();
if (_verbose > 0)
_bit->displayHeader();
/* get VID and PID from dfu file */
try {
dfu_vid = std::stoi(_bit->getHeaderVal("idVendor"), 0, 16);
dfu_pid = std::stoi(_bit->getHeaderVal("idProduct"), 0, 16);
} catch (std::exception &e) {
if (_verbose)
printWarn(e.what());
/* get VID and PID from dfu file */
try {
dfu_vid = std::stoi(_bit->getHeaderVal("idVendor"), 0, 16);
dfu_pid = std::stoi(_bit->getHeaderVal("idProduct"), 0, 16);
} catch (std::exception &e) {
if (_verbose)
printWarn(e.what());
}
}
if (libusb_init(&usb_ctx) < 0) {
@ -128,12 +133,16 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
displayDFU();
/* don't try device without vid/pid */
if (_vid == 0 || _pid == 0) {
if ((_vid == 0 || _pid == 0) && _bit) {
libusb_exit(usb_ctx);
delete _bit;
throw std::runtime_error("Can't open device vid/pid == 0");
}
/* the If bitstream has been bypassed -> it's the end */
if (!_bit)
return;
/* open the first */
if (open_DFU(0) == EXIT_FAILURE) {
libusb_exit(usb_ctx);
@ -143,10 +152,14 @@ DFU::DFU(const string &filename, uint16_t vid, uint16_t pid,
printf("%02x %02x\n", _vid, _pid);
char state = get_state();
if (_verbose > 0) {
printInfo("Default DFU status " + dfu_dev_state_val[state]);
get_status(&status);
if ((ret = get_status(&status)) < 0) {
delete _bit;
throw std::runtime_error("get device status failed with error code " +
std::to_string(ret));
}
printInfo("Default DFU status " + dfu_dev_state_val[status.bState]);
}
}
@ -154,7 +167,8 @@ DFU::~DFU()
{
close_DFU();
libusb_exit(usb_ctx);
delete _bit;
if (_bit)
delete _bit;
}
/* open the device using VID and PID
@ -162,6 +176,7 @@ DFU::~DFU()
int DFU::open_DFU(int index)
{
struct dfu_dev curr_dfu;
int ret;
if (_vid == 0 || _pid == 0) {
printError("Error: Can't open device without VID/PID");
@ -178,15 +193,16 @@ int DFU::open_DFU(int index)
printError("Error: fail to open device");
return EXIT_FAILURE;
}
if (libusb_claim_interface(dev_handle, curr_intf) != 0) {
if ((ret = libusb_claim_interface(dev_handle, curr_intf)) != 0) {
libusb_close(dev_handle);
printError("Error: fail to claim interface");
printError("Error: fail to claim interface with error code " + std::to_string(ret));
return EXIT_FAILURE;
}
if (libusb_set_interface_alt_setting(dev_handle, curr_intf, 0) != 0) {
if ((ret = libusb_set_interface_alt_setting(dev_handle, curr_intf, _altsetting)) != 0) {
libusb_release_interface(dev_handle, curr_intf);
libusb_close(dev_handle);
printError("Error: fail to set interface");
printError("Error: fail to set interface " + std::to_string(curr_intf) +
" with error code " + std::to_string(ret));
return EXIT_FAILURE;
}
@ -303,10 +319,11 @@ int DFU::searchDFUDevices()
int ret = libusb_open(usb_dev, &handle);
if (ret == 0) {
if (searchIfDFU(handle, usb_dev, &desc) != 0) {
ret = searchIfDFU(handle, usb_dev, &desc);
libusb_close(handle);
if (ret != 0) {
return EXIT_FAILURE;
}
libusb_close(handle);
} else if (_debug) {
char mess[256];
sprintf(mess,"Unable to open device: "
@ -366,10 +383,17 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle,
my_dev.device = libusb_get_device_address(dev);
my_dev.bMaxPacketSize0 = desc->bMaxPacketSize0;
memset(my_dev.iProduct, 0, 128);
libusb_get_string_descriptor_ascii(handle, desc->iProduct,
my_dev.iProduct, 128);
if (strlen((char *)my_dev.iProduct) == 0)
snprintf((char *)my_dev.iProduct, 128, "empty");
memset(my_dev.iInterface, 0, 128);
libusb_get_string_descriptor_ascii(handle, intf->iInterface,
my_dev.iInterface, 128);
if (strlen((char *)my_dev.iInterface) == 0)
snprintf((char *)my_dev.iInterface, 128, "empty");
int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path));
my_dev.path[r] = '\0';
@ -433,9 +457,11 @@ int DFU::set_state(char newState)
{
int ret = 0;
struct dfu_status status;
char curr_state = get_state();
while (curr_state != newState) {
switch (curr_state) {
if (get_status(&status) < 0)
return -1;
while (status.bState != newState) {
switch (status.bState) {
case STATE_appIDLE:
if (dfu_detach() == EXIT_FAILURE)
return -1;
@ -446,7 +472,6 @@ int DFU::set_state(char newState)
cerr << dfu_dev_status_val[status.bStatus] << endl;
return -1;
}
curr_state = status.bState;
break;
case STATE_appDETACH:
if (newState == STATE_appIDLE) {
@ -484,15 +509,14 @@ int DFU::set_state(char newState)
printError("Fails to send packet\n");
return ret;
}
if ((ret = get_state()) < 0)
if (get_status(&status) < 0)
return ret;
/* not always true:
* the newState may be the next one or another */
if (ret != newState) {
printError(dfu_dev_state_val[ret]);
if (status.bState != newState) {
printError(dfu_dev_state_val[status.bState]);
return -1;
}
curr_state = ret;
break;
case STATE_dfuERROR:
if (newState == STATE_appIDLE) {
@ -520,7 +544,6 @@ int DFU::set_state(char newState)
cerr << dfu_dev_status_val[status.bStatus] << endl;
return -1;
}
curr_state = status.bState;
break;
}
}
@ -550,6 +573,10 @@ int DFU::get_status(struct dfu_status *status)
(((uint32_t)buffer[1] & 0xff) << 0);
status->bState = buffer[4];
status->iString = buffer[5];
} else if (res < 0) {
printError("Get DFU status failed with error " +
std::to_string(res) +
"(" + std::string(libusb_error_name(res)) + ")");
}
return res;
}
@ -657,6 +684,10 @@ int DFU::download()
printError("Error: No device. Can't download file");
return -1;
}
if (!_bit) {
printError("Error: No bitstream. Stop");
return -1;
}
int ret, ret_val = EXIT_SUCCESS;
uint8_t *buffer, *ptr;
@ -673,7 +704,9 @@ int DFU::download()
}
/* download must start in dfu IDLE state */
if (get_state() != STATE_dfuIDLE)
if (get_status(&status) < 0)
return -1;
if (status.bState != STATE_dfuIDLE)
set_state(STATE_dfuIDLE);
xfer_len = libusb_le16_to_cpu(curr_dev.dfu_desc.wTransferSize);
@ -733,12 +766,16 @@ int DFU::download()
/* send the zero sized download request
* dfuDNLOAD_IDLE -> dfuMANITEST-SYNC
*/
ret = set_state(STATE_dfuMANIFEST_SYNC);
printInfo("send zero sized download request: ", false);
//ret = set_state(STATE_dfuMANIFEST_SYNC);
ret = send(true, DFU_DNLOAD, transaction, NULL, 0);
if (ret < 0) {
printError("Error: fail to change state " + to_string(ret));
return -6;
}
printSuccess("DONE");
/* Now FSM must be in dfuMANITEST-SYNC */
bool must_continue = true;
do {

View File

@ -24,7 +24,8 @@ class DFU {
* \param[in] altsetting: device altsetting to use
* \param[in] verbose_lvl: verbose level 0 normal, -1 quiet, 1 verbose
*/
DFU(const std::string &filename, uint16_t vid, uint16_t pid,
DFU(const std::string &filename, bool bypass_bitstream,
uint16_t vid, uint16_t pid,
int16_t altsetting, int verbose_lvl);
~DFU();
@ -234,7 +235,7 @@ class DFU {
int dev_idx; /**< device index in dfu_dev */
uint16_t _vid; /**< device Vendor ID */
uint16_t _pid; /**< device Product ID */
int16_t _altsetting; /**< device altesetting */
int16_t _altsetting; /**< device altsetting */
struct libusb_context *usb_ctx; /**< usb context */
libusb_device_handle * dev_handle; /**< current device handle */
int curr_intf; /**< device interface to use */

View File

@ -25,12 +25,12 @@ class DFUFileParser: public ConfigBitstreamParser {
DFUFileParser(const std::string &filename, bool verbose);
/*!
* \brief read full content of the file, fill the buffer
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwhise
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwise
*/
int parse() override;
/*!
* \brief read DFU suffix content of the file, fill _hdr structure
* \return EXIT_SUCCESS if suffix is fully read, EXIT_FAILURE otherwhise
* \return EXIT_SUCCESS if suffix is fully read, EXIT_FAILURE otherwise
*/
int parseHeader();
/*!

View File

@ -25,6 +25,7 @@ using namespace std;
#define DIRTYJTAG_WRITE_EP 0x01
#define DIRTYJTAG_READ_EP 0x82
#define DIRTYJTAG_TIMEOUT 1000
enum dirtyJtagCmd {
CMD_STOP = 0x00,
@ -44,7 +45,7 @@ enum CommandModifier {
struct version_specific
{
uint8_t no_read; // command modifer for xfer no read
uint8_t no_read; // command modifier for xfer no read
uint16_t max_bits; // max bit count that can be transferred
};
@ -87,7 +88,8 @@ DirtyJtag::DirtyJtag(uint32_t clkHZ, uint8_t verbose):
}
_version = 0;
getVersion();
if (!getVersion())
throw std::runtime_error("Fail to get version");
if (setClkFreq(clkHZ) < 0) {
cerr << "Fail to set frequency" << endl;
@ -103,7 +105,7 @@ DirtyJtag::~DirtyJtag()
libusb_exit(usb_ctx);
}
void DirtyJtag::getVersion()
bool DirtyJtag::getVersion()
{
int actual_length;
int ret;
@ -111,17 +113,17 @@ void DirtyJtag::getVersion()
CMD_STOP};
uint8_t rx_buf[64];
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, 2, &actual_length, 1000);
buf, 2, &actual_length, DIRTYJTAG_TIMEOUT);
if (ret < 0) {
cerr << "getVersion: usb bulk write failed " << ret << endl;
return;
return false;
}
do {
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
rx_buf, 64, &actual_length, 1000);
rx_buf, 64, &actual_length, DIRTYJTAG_TIMEOUT);
if (ret < 0) {
cerr << "getVersion: read: usb bulk read failed " << ret << endl;
return;
return false;
}
} while (actual_length == 0);
if (!strncmp("DJTAG1\n", (char*)rx_buf, 7)) {
@ -134,6 +136,8 @@ void DirtyJtag::getVersion()
cerr << "dirtyJtag version unknown" << endl;
_version = 0;
}
return true;
}
@ -158,7 +162,7 @@ int DirtyJtag::setClkFreq(uint32_t clkHZ)
static_cast<uint8_t>(0xff & ((clkHZ / 1000) )),
CMD_STOP};
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, 4, &actual_length, 1000);
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
if (ret < 0) {
cerr << "setClkFreq: usb bulk write failed " << ret << endl;
return -EXIT_FAILURE;
@ -197,7 +201,8 @@ int DirtyJtag::writeTMS(uint8_t *tms, uint32_t len, bool flush_buffer)
}
buf[buffer_idx++] = CMD_STOP;
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, buffer_idx, &actual_length, 1000);
buf, buffer_idx, &actual_length,
DIRTYJTAG_TIMEOUT);
if (ret < 0)
{
cerr << "writeTMS: usb bulk write failed " << ret << endl;
@ -220,7 +225,7 @@ int DirtyJtag::toggleClk(uint8_t tms, uint8_t tdi, uint32_t clk_len)
buf[2] = (clk_len > 64) ? 64 : (uint8_t)clk_len;
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, 4, &actual_length, 1000);
buf, 4, &actual_length, DIRTYJTAG_TIMEOUT);
if (ret < 0) {
cerr << "toggleClk: usb bulk write failed " << ret << endl;
return -EXIT_FAILURE;
@ -240,16 +245,16 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
{
int actual_length;
uint32_t real_bit_len = len - (end ? 1 : 0);
uint32_t real_byte_len = (len + 7) / 8;
uint32_t kRealByteLen = (len + 7) / 8;
uint8_t tx_cpy[real_byte_len];
uint8_t tx_cpy[kRealByteLen];
uint8_t tx_buf[512], rx_buf[512];
uint8_t *tx_ptr, *rx_ptr = rx;
if (tx)
memcpy(tx_cpy, tx, real_byte_len);
memcpy(tx_cpy, tx, kRealByteLen);
else
memset(tx_cpy, 0, real_byte_len);
memset(tx_cpy, 0, kRealByteLen);
tx_ptr = tx_cpy;
tx_buf[0] = CMD_XFER | (rx ? 0 : v_options[_version].no_read);
@ -282,7 +287,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
actual_length = 0;
int ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
(unsigned char *)tx_buf, (byte_to_send + header_offset),
&actual_length, 1000);
&actual_length, DIRTYJTAG_TIMEOUT);
if ((ret < 0) || (actual_length != (int)(byte_to_send + header_offset))) {
cerr << "writeTDI: fill: usb bulk write failed " << ret <<
"actual length: " << actual_length << endl;
@ -294,7 +299,7 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
int transfer_length = (bit_to_send > 255) ? byte_to_send :32;
do {
ret = libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
rx_buf, transfer_length, &actual_length, 1000);
rx_buf, transfer_length, &actual_length, DIRTYJTAG_TIMEOUT);
if (ret < 0) {
cerr << "writeTDI: read: usb bulk read failed " << ret << endl;
return EXIT_FAILURE;
@ -338,7 +343,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
CMD_STOP,
};
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, sizeof(buf), &actual_length, 1000) < 0)
buf, sizeof(buf), &actual_length,
DIRTYJTAG_TIMEOUT) < 0)
{
cerr << "writeTDI: last bit error: usb bulk write failed 1" << endl;
return -EXIT_FAILURE;
@ -346,7 +352,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
do
{
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_READ_EP,
&sig, 1, &actual_length, 1000) < 0)
&sig, 1, &actual_length,
DIRTYJTAG_TIMEOUT) < 0)
{
cerr << "writeTDI: last bit error: usb bulk read failed" << endl;
return -EXIT_FAILURE;
@ -360,7 +367,8 @@ int DirtyJtag::writeTDI(uint8_t *tx, uint8_t *rx, uint32_t len, bool end)
buf[2] &= ~SIG_TCK;
buf[3] = CMD_STOP;
if (libusb_bulk_transfer(dev_handle, DIRTYJTAG_WRITE_EP,
buf, 4, &actual_length, 1000) < 0)
buf, 4, &actual_length,
DIRTYJTAG_TIMEOUT) < 0)
{
cerr << "writeTDI: last bit error: usb bulk write failed 2" << endl;
return -EXIT_FAILURE;

View File

@ -46,7 +46,7 @@ class DirtyJtag : public JtagInterface {
uint8_t _verbose;
int sendBitBang(uint8_t mask, uint8_t val, uint8_t *read, bool last);
void getVersion();
bool getVersion();
libusb_device_handle *dev_handle;
libusb_context *usb_ctx;

View File

@ -20,7 +20,7 @@
#define KCYN "\x1B[36m"
#define KWHT "\x1B[37m"
void printError(std::string err, bool eol)
void printError(const std::string &err, bool eol)
{
if (isatty(STDERR_FILENO))
std::cerr << KRED << err << "\e[0m";
@ -31,7 +31,7 @@ void printError(std::string err, bool eol)
std::cerr << std::endl;
}
void printWarn(std::string warn, bool eol)
void printWarn(const std::string &warn, bool eol)
{
if (isatty(STDOUT_FILENO))
std::cout << KYEL << warn << "\e[0m" << std::flush;
@ -42,7 +42,7 @@ void printWarn(std::string warn, bool eol)
std::cout << std::endl;
}
void printInfo(std::string info, bool eol)
void printInfo(const std::string &info, bool eol)
{
if (isatty(STDOUT_FILENO))
std::cout << KBLUL << info << "\e[0m" << std::flush;
@ -53,7 +53,7 @@ void printInfo(std::string info, bool eol)
std::cout << std::endl;
}
void printSuccess(std::string success, bool eol)
void printSuccess(const std::string &success, bool eol)
{
if (isatty(STDOUT_FILENO))
std::cout << KGRN << success << "\e[0m" << std::flush;

View File

@ -9,9 +9,9 @@
#include <iostream>
#include <string>
void printError(std::string err, bool eol = true);
void printWarn(std::string warn, bool eol = true);
void printInfo(std::string info, bool eol = true);
void printSuccess(std::string success, bool eol = true);
void printError(const std::string &err, bool eol = true);
void printWarn(const std::string &warn, bool eol = true);
void printInfo(const std::string &info, bool eol = true);
void printSuccess(const std::string &success, bool eol = true);
#endif // DISPLAY_HPP_

View File

@ -9,16 +9,22 @@
#include <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "common.hpp"
#include "device.hpp"
#include "display.hpp"
#include "efinixHexParser.hpp"
#include "ftdispi.hpp"
#include "device.hpp"
#include "ftdiJtagMPSSE.hpp"
#include "ftdispi.hpp"
#include "jtag.hpp"
#include "part.hpp"
#include "progressBar.hpp"
#include "rawParser.hpp"
#if defined (_WIN64) || defined (_WIN32)
#include "pathHelper.hpp"
#endif
#include "spiFlash.hpp"
Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
@ -27,21 +33,47 @@ Efinix::Efinix(FtdiSpi* spi, const std::string &filename,
uint16_t oe_pin,
bool verify, int8_t verbose):
Device(NULL, filename, file_type, verify, verbose), _ftdi_jtag(NULL),
_rst_pin(rst_pin), _done_pin(done_pin), _cs_pin(0), _oe_pin(oe_pin)
_rst_pin(rst_pin), _done_pin(done_pin), _cs_pin(0), _oe_pin(oe_pin),
_fpga_family(UNKNOWN_FAMILY), _irlen(0), _device_package(""),
_spiOverJtagPath("")
{
_spi = spi;
_spi->gpio_set_input(_done_pin);
_spi->gpio_set_output(_rst_pin | _oe_pin);
init_common(Device::WR_FLASH);
}
Efinix::Efinix(Jtag* jtag, const std::string &filename,
const std::string &file_type,
const std::string &board_name,
bool verify, int8_t verbose):
const std::string &file_type, Device::prog_type_t prg_type,
const std::string &board_name, const std::string &device_package,
const std::string &spiOverJtagPath, bool verify, int8_t verbose):
Device(jtag, filename, file_type, verify, verbose),
SPIInterface(filename, verbose, 256, false, false, false),
_spi(NULL), _rst_pin(0), _done_pin(0), _cs_pin(0),
_oe_pin(0)
_oe_pin(0), _fpga_family(UNKNOWN_FAMILY), _irlen(0),
_device_package(device_package), _spiOverJtagPath(spiOverJtagPath)
{
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(jtag->get_ll_class());
/* detect FPGA type (Trion or Titanium) */
const uint32_t idcode = _jtag->get_target_device_id();
const std::string family = fpga_list[idcode].family;
if (family == "Titanium") {
if (_file_extension == "hex" && prg_type == Device::WR_SRAM) {
throw std::runtime_error("Error: loading (RAM) hex file is not "
"allowed for Titanium devices");
} else if (_file_extension == "bit" && prg_type == Device::WR_FLASH) {
throw std::runtime_error("Error: writing bit (FLASH) file is not "
"allowed for Titanium devices");
}
_fpga_family = TITANIUM_FAMILY;
} else if (family == "Trion") {
_fpga_family = TRION_FAMILY;
} else {
throw std::runtime_error("Error: unknown family " + family);
}
/* get irlen value from model */
_irlen = fpga_list[idcode].irlength;
/* WA: before using JTAG, device must restart with cs low
* but cs and rst for xyloni are connected to interfaceA (ie SPI)
* TODO: some boards have cs, reset and done in both interface
@ -56,45 +88,76 @@ Efinix::Efinix(Jtag* jtag, const std::string &filename,
} else if (board_name == "titanium_ti60_f225_jtag") {
spi_board_name = "titanium_ti60_f225";
} else {
throw std::runtime_error("Error: unknown board name");
init_common(prg_type);
return;
}
/* 2: retrieve spi board */
target_board_t *spi_board = &(board_list[spi_board_name]);
const target_board_t *spi_board = &(board_list[spi_board_name]);
/* 3: SPI cable */
cable_t *spi_cable = &(cable_list[spi_board->cable_name]);
cable_t spi_cable = (cable_list[spi_board->cable_name]);
spi_cable.bus_addr = _ftdi_jtag->bus_addr();
spi_cable.device_addr = _ftdi_jtag->device_addr();
/* 4: get pinout (cs, oe, rst) */
_cs_pin = spi_board->spi_pins_config.cs_pin;
_rst_pin = spi_board->reset_pin;
_oe_pin = spi_board->oe_pin;
_done_pin = spi_board->done_pin;
/* 5: open SPI interface */
_spi = new FtdiSpi(spi_cable->config, spi_board->spi_pins_config,
_spi = new FtdiSpi(spi_cable, spi_board->spi_pins_config,
jtag->getClkFreq(), verbose > 0);
_ftdi_jtag = reinterpret_cast<FtdiJtagMPSSE *>(jtag);
/* 6: configure pins direction and default state */
_spi->gpio_set_output(_oe_pin | _rst_pin | _cs_pin);
init_common(prg_type);
}
void Efinix::init_common(const Device::prog_type_t &prg_type)
{
if (_spi) {
_spi->gpio_set_input(_done_pin);
_spi->gpio_set_output(_rst_pin | _oe_pin);
}
switch (prg_type) {
case Device::WR_FLASH:
_mode = (_jtag) ? Device::FLASH_MODE : Device::SPI_MODE;
break;
case Device::WR_SRAM:
if (!_jtag) {
throw std::runtime_error("Efinix: SRAM load requires jtag");
}
_mode = MEM_MODE;
break;
default:
_mode = NONE_MODE;
}
}
Efinix::~Efinix()
{}
{
if (_jtag && _spi)
delete _spi;
}
void Efinix::reset()
{
if (_ftdi_jtag) // not supported
if (!_spi) {
printError("jtag: reset not supported");
return;
}
uint32_t timeout = 1000;
_spi->gpio_clear(_rst_pin | _oe_pin);
usleep(1000);
_spi->gpio_set(_rst_pin | _oe_pin);
printInfo("Reset ", false);
do {
timeout--;
usleep(12000);
} while (((_spi->gpio_get(true) & _done_pin) == 0) || timeout > 0);
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
if (timeout == 0)
printError("FAIL");
else
@ -105,13 +168,15 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
{
if (_file_extension.empty())
return;
if (_mode == Device::NONE_MODE)
return;
ConfigBitstreamParser *bit;
try {
if (_file_extension == "hex") {
bit = new EfinixHexParser(_filename, _verbose);
if (_file_extension == "hex" || _file_extension == "bit") {
bit = new EfinixHexParser(_filename);
} else {
if (offset == 0) {
if (offset == 0 && _spi) {
printError("Error: can't write raw data at the beginning of the flash");
throw std::exception();
}
@ -131,21 +196,37 @@ void Efinix::program(unsigned int offset, bool unprotect_flash)
return;
}
unsigned char *data = bit->getData();
int length = bit->getLength() / 8;
const uint8_t *data = bit->getData();
const int length = bit->getLength() / 8;
if (_verbose)
bit->displayHeader();
if (_ftdi_jtag)
programJTAG(data, length);
else
programSPI(offset, data, length, unprotect_flash);
switch (_mode) {
case MEM_MODE:
programJTAG(data, length);
break;
case FLASH_MODE:
if (_jtag)
SPIInterface::write(offset, const_cast<uint8_t *>(data),
length, unprotect_flash);
else
programSPI(offset, data, length, unprotect_flash);
break;
default:
return;
}
delete bit;
}
bool Efinix::dumpFlash(const std::string &filename,
uint32_t base_addr, uint32_t len)
bool Efinix::dumpFlash(uint32_t base_addr, uint32_t len)
{
if (!_spi) {
printError("jtag: dumpFlash not supported");
return false;
}
uint32_t timeout = 1000;
_spi->gpio_clear(_rst_pin);
@ -155,7 +236,7 @@ bool Efinix::dumpFlash(const std::string &filename,
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), false, _verbose);
flash.reset();
flash.power_up();
flash.dump(filename, base_addr, len);
flash.dump(_filename, base_addr, len);
} catch (std::exception &e) {
printError("Fail");
printError(std::string(e.what()));
@ -179,11 +260,9 @@ bool Efinix::dumpFlash(const std::string &filename,
return false;
}
void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
bool unprotect_flash)
void Efinix::programSPI(unsigned int offset, const uint8_t *data,
const int length, const bool unprotect_flash)
{
uint32_t timeout = 1000;
_spi->gpio_clear(_rst_pin | _oe_pin);
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,
@ -193,24 +272,13 @@ void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
printf("%02x\n", flash.read_status_reg());
flash.read_id();
flash.erase_and_prog(offset, data, length);
flash.erase_and_prog(offset, const_cast<uint8_t *>(data), length);
/* verify write if required */
if (_verify)
flash.verify(offset, data, length);
_spi->gpio_set(_rst_pin | _oe_pin);
usleep(12000);
printInfo("Wait for CDONE ", false);
do {
timeout--;
usleep(12000);
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
if (timeout == 0)
printError("FAIL");
else
printSuccess("DONE");
reset();
}
#define SAMPLE_PRELOAD 0x02
@ -219,21 +287,28 @@ void Efinix::programSPI(unsigned int offset, uint8_t *data, int length,
#define IDCODE 0x03
#define PROGRAM 0x04
#define ENTERUSER 0x07
#define IRLENGTH 4
#define USER1 0x08
void Efinix::programJTAG(uint8_t *data, int length)
void Efinix::programJTAG(const uint8_t *data, const int length)
{
int xfer_len = 512, tx_end;
uint8_t tx[512];
/* trion has to be reseted with cs low */
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
usleep(30000);
_spi->gpio_set(_rst_pin); // assert RST
usleep(50000);
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
usleep(50000);
if (_fpga_family == TITANIUM_FAMILY)
_jtag->set_state(Jtag::RUN_TEST_IDLE);
if(_spi) {
/* trion has to be reseted with cs low */
_spi->gpio_clear(_oe_pin | _cs_pin | _rst_pin);
usleep(30000);
_spi->gpio_set(_rst_pin); // assert RST
usleep(50000);
_spi->gpio_set(_oe_pin | _rst_pin); // release OE
usleep(50000);
}
if (_fpga_family == TITANIUM_FAMILY)
_jtag->set_state(Jtag::TEST_LOGIC_RESET);
/* force run_test_idle state */
_jtag->set_state(Jtag::RUN_TEST_IDLE);
usleep(100000);
@ -241,8 +316,8 @@ void Efinix::programJTAG(uint8_t *data, int length)
/* send PROGRAM state and stay in SHIFT_DR until
* full configuration data has been sent
*/
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR);
_jtag->shiftIR(PROGRAM, IRLENGTH, Jtag::EXIT1_IR); // T20 fix
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR);
_jtag->shiftIR(PROGRAM, _irlen, Jtag::EXIT1_IR); // T20 fix
ProgressBar progress("Load SRAM", length, 50, _quiet);
@ -264,9 +339,160 @@ void Efinix::programJTAG(uint8_t *data, int length)
usleep(10000);
_jtag->shiftIR(ENTERUSER, IRLENGTH, Jtag::EXIT1_IR);
_jtag->shiftIR(ENTERUSER, _irlen, Jtag::EXIT1_IR);
memset(tx, 0, 512);
_jtag->shiftDR(tx, NULL, 100);
_jtag->shiftIR(IDCODE, IRLENGTH);
_jtag->shiftIR(IDCODE, _irlen);
uint8_t idc[4];
_jtag->shiftDR(NULL, idc, 4);
printf("%02x%02x%02x%02x\n",
idc[0], idc[1], idc[2], idc[3]);
}
bool Efinix::post_flash_access()
{
if (_skip_reset)
printInfo("Skip resetting device");
else
reset();
return true;
}
bool Efinix::prepare_flash_access()
{
if (_skip_load_bridge) {
printInfo("Skip loading bridge for spiOverjtag");
return true;
}
std::string bitname;
if (!_spiOverJtagPath.empty()) {
bitname = _spiOverJtagPath;
} else {
if (_device_package.empty()) {
printError("Can't program SPI flash: missing device-package information");
return false;
}
bitname = get_shell_env_var("OPENFPGALOADER_SOJ_DIR",
DATA_DIR "/openFPGALoader");
bitname += "/spiOverJtag_efinix_" + _device_package + ".bit.gz";
}
#if defined (_WIN64) || defined (_WIN32)
/* Convert relative path embedded at compile time to an absolute path */
bitname = PathHelper::absolutePath(bitname);
#endif
std::cout << "use: " << bitname << std::endl;
/* first: load spi over jtag */
try {
EfinixHexParser bridge(bitname);
bridge.parse();
const uint8_t *data = bridge.getData();
const int length = bridge.getLength() / 8;
programJTAG(data, length);
} catch (std::exception &e) {
printError(e.what());
return false;
}
return true;
}
/* */
/* SPI interface */
/* */
/*
* jtag : jtag interface
* cmd : opcode for SPI flash
* tx : buffer to send
* rx : buffer to fill
* len : number of byte to send/receive (cmd not comprise)
* so to send only a cmd set len to 0 (or omit this param)
*/
int Efinix::spi_put(uint8_t cmd,
uint8_t *tx, uint8_t *rx, uint32_t len)
{
int kXferLen = len + 1 + ((rx == NULL) ? 0 : 1);
uint8_t jtx[kXferLen];
jtx[0] = EfinixHexParser::reverseByte(cmd);
uint8_t jrx[kXferLen];
if (tx != NULL) {
for (uint32_t i=0; i < len; i++)
jtx[i+1] = EfinixHexParser::reverseByte(tx[i]);
}
/* addr BSCAN user1 */
_jtag->shiftIR(USER1, _irlen);
/* send first already stored cmd,
* in the same time store each byte
* to next
*/
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*kXferLen);
if (rx != NULL) {
for (uint32_t i=0; i < len; i++)
rx[i] = EfinixHexParser::reverseByte(jrx[i+1] >> 1) | (jrx[i+2] & 0x01);
}
return 0;
}
int Efinix::spi_put(uint8_t *tx, uint8_t *rx, uint32_t len)
{
int kXferLen = len + ((rx == NULL) ? 0 : 1);
uint8_t jtx[kXferLen];
uint8_t jrx[kXferLen];
if (tx != NULL) {
for (uint32_t i=0; i < len; i++)
jtx[i] = EfinixHexParser::reverseByte(tx[i]);
}
/* addr BSCAN user1 */
_jtag->shiftIR(USER1, _irlen);
/* send first already stored cmd,
* in the same time store each byte
* to next
*/
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*kXferLen);
if (rx != NULL) {
for (uint32_t i=0; i < len; i++)
rx[i] = EfinixHexParser::reverseByte(jrx[i] >> 1) | (jrx[i+1] & 0x01);
}
return 0;
}
int Efinix::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
uint32_t timeout, bool verbose)
{
uint8_t rx[2], dummy[2], tmp;
uint8_t tx = EfinixHexParser::reverseByte(cmd);
uint32_t count = 0;
_jtag->shiftIR(USER1, _irlen, Jtag::UPDATE_IR);
_jtag->shiftDR(&tx, NULL, 8, Jtag::SHIFT_DR);
do {
_jtag->shiftDR(dummy, rx, 8*2, Jtag::SHIFT_DR);
tmp = (EfinixHexParser::reverseByte(rx[0] >> 1)) | (0x01 & rx[1]);
count++;
if (count == timeout){
printf("timeout: %x %x %x\n", tmp, rx[0], rx[1]);
break;
}
if (verbose) {
printf("%x %x %x %u\n", tmp, mask, cond, count);
}
} while ((tmp & mask) != cond);
_jtag->shiftDR(dummy, rx, 8*2, Jtag::EXIT1_DR);
_jtag->go_test_logic_reset();
if (count == timeout) {
printf("%x\n", tmp);
std::cout << "wait: Error" << std::endl;
return -ETIME;
}
return 0;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2020 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
* Copyright (C) 2020-2023 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
*/
#ifndef SRC_EFINIX_HPP_
@ -12,41 +12,64 @@
#include "ftdiJtagMPSSE.hpp"
#include "ftdispi.hpp"
#include "jtag.hpp"
#include "spiInterface.hpp"
class Efinix: public Device {
class Efinix: public Device, SPIInterface {
public:
Efinix(FtdiSpi *spi, const std::string &filename,
const std::string &file_type,
uint16_t rst_pin, uint16_t done_pin, uint16_t oe_pin,
bool verify, int8_t verbose);
Efinix(Jtag* jtag, const std::string &filename,
const std::string &file_type,
const std::string &board_name,
const std::string &file_type, Device::prog_type_t prg_type,
const std::string &board_name, const std::string &device_package,
const std::string &spiOverJtagPath,
bool verify, int8_t verbose);
~Efinix();
void program(unsigned int offset, bool unprotect_flash) override;
bool dumpFlash(const std::string &filename,
uint32_t base_addr, uint32_t len);
virtual bool protect_flash(uint32_t len) override {
bool dumpFlash(uint32_t base_addr, uint32_t len) override;
bool protect_flash(uint32_t len) override {
(void) len;
printError("protect flash not supported"); return false;}
virtual bool unprotect_flash() override {
bool unprotect_flash() override {
printError("unprotect flash not supported"); return false;}
bool bulk_erase_flash() override {
printError("bulk erase flash not supported"); return false;}
/* not supported in SPI Active mode */
int idCode() override {return 0;}
void reset() override;
/* spi interface */
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
uint32_t len) override;
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
uint32_t timeout, bool verbose = false) override;
private:
void programSPI(unsigned int offset, uint8_t *data, int length,
bool unprotect_flash);
void programJTAG(uint8_t *data, int length);
/* list of efinix family devices */
enum efinix_family_t {
TITANIUM_FAMILY = 0,
TRION_FAMILY,
UNKNOWN_FAMILY = 999
};
void init_common(const Device::prog_type_t &prg_type);
void programSPI(unsigned int offset, const uint8_t *data,
const int length, const bool unprotect_flash);
void programJTAG(const uint8_t *data, const int length);
bool post_flash_access() override;
bool prepare_flash_access() override;
FtdiSpi *_spi;
FtdiJtagMPSSE *_ftdi_jtag;
uint16_t _rst_pin;
uint16_t _done_pin;
uint16_t _cs_pin;
uint16_t _oe_pin;
efinix_family_t _fpga_family;
int _irlen;
std::string _device_package;
std::string _spiOverJtagPath;
};
#endif // SRC_EFINIX_HPP_

View File

@ -12,9 +12,9 @@
using namespace std;
EfinixHexParser::EfinixHexParser(const string &filename, bool reverseOrder):
EfinixHexParser::EfinixHexParser(const string &filename):
ConfigBitstreamParser(filename, ConfigBitstreamParser::ASCII_MODE,
false), _reverseOrder(reverseOrder)
false)
{}
int EfinixHexParser::parse()

View File

@ -21,17 +21,13 @@ class EfinixHexParser: public ConfigBitstreamParser {
/*!
* \brief constructor
* \param[in] filename: raw file to read
* \param[in] reverseOrder: reverse each byte (LSB -> MSB, MSB -> LSB)
*/
EfinixHexParser(const std::string &filename, bool reverseOrder);
EfinixHexParser(const std::string &filename);
/*!
* \brief read full content of the file, fill the buffer
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwhise
* \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwise
*/
int parse() override;
private:
bool _reverseOrder; /*!< tail if byte must be reversed */
};
#endif // SRC_EFINIXHEXPARSER_HPP_

View File

@ -6,8 +6,10 @@
#ifndef SRC_EPCQ_HPP_
#define SRC_EPCQ_HPP_
#include <cstdint>
#include <iostream>
#include <vector>
#include "spiInterface.hpp"
#include "spiFlash.hpp"

View File

@ -133,7 +133,7 @@ int EPCQ::erase_sector(char start_sector, char nb_sectors)
}
#endif
/* write must be do by 256bytes. Before writting next 256bytes we must
/* write must be do by 256bytes. Before writing next 256bytes we must
* wait for WIP goes low
*/
@ -185,7 +185,7 @@ void EPCQ::program(unsigned int start_offset, string filename, bool reverse)
nb_read = fread(rd_buffer, 1, 256, fd);
if (nb_read == 0) {
printf("problem dans le read du fichier source\n");
printf("problem reading the source file\n");
break;
}
buffer[1] = (offset >> 16) & 0xff;
@ -262,14 +262,14 @@ void EPCQ::read_id()
_spi->spi_put(0x9F, NULL, rx_buf, 3);
_device_id = rx_buf[2];
if (_verbose)
printf("device id 0x%x attendu 0x15\n", _device_id);
printf("device id 0x%x expected 0x15\n", _device_id);
/* read EPCQ silicon id */
//tx_buf[0] = 0xAB;
/* 3 dummy_byte + 1 byte*/
_spi->spi_put(0xAB, NULL, rx_buf, 4);
_silicon_id = rx_buf[3];
if (_verbose)
printf("silicon id 0x%x attendu 0x14\n", _silicon_id);
printf("silicon id 0x%x expected 0x14\n", _silicon_id);
}
EPCQ::EPCQ(SPIInterface *spi, int8_t verbose):SPIFlash(spi, verbose)

View File

@ -17,7 +17,7 @@ class EPCQ: public SPIFlash {
void read_id() override;
//void program(unsigned int start_offet, string filename, bool reverse=true);
//void program(unsigned int start_offset, string filename, bool reverse=true);
//int erase_sector(char start_sector, char nb_sectors);
//void dumpflash(char *dest_file, int size);

View File

@ -24,7 +24,7 @@
# define FEA_I2C_DG_FIL_EN (1 << 0) /* I2C deglitch filter enable for Primary I2C Port 0=Disabled (Default), 1=Enabled */
# define FEA_FLASH_PROT_SEC_SEL (0x7 << 1) /* Flash Protection Sector Selection */
# define FEA_MY_ASSP_EN (1 << 4) /* MY_ASSP Enabled 0=Disabled (Default), 1=Enabled */
# define FEA_PROG_PERSIST (1 << 5) /* PROGRAMN Persistence 0=Enabled (Default), 1=Disabled */
# define FEA_PROG_PERSIST (1 << 5) /* PROGRAM Persistence 0=Enabled (Default), 1=Disabled */
# define FEA_INITN_PERSIST (1 << 6) /* INITN Persistence 0=Disabled (Default), 1=Enabled */
# define FEA_DONE_PERSIST (1 << 7) /* DONE Persistence 0=Disabled (Default), 1=Enabled */
# define FEA_JTAG_PERSIST (1 << 8) /* JTAG Port Persistence 0=Enabled (Default), 1=Disabled */
@ -65,7 +65,7 @@
using namespace std;
FeaParser::FeaParser(string filename, bool verbose):
FeaParser::FeaParser(const string &filename, bool verbose):
ConfigBitstreamParser(filename, ConfigBitstreamParser::BIN_MODE, verbose),
_feabits(0), _has_feabits(false)
{
@ -73,7 +73,7 @@ FeaParser::FeaParser(string filename, bool verbose):
_featuresRow[i] = 0;
}
/* fill a vector with consecutive lines, begining with 0 or 1, until EOF
/* fill a vector with consecutive lines, beginning with 0 or 1, until EOF
* \brief read a line with '\r''\n' or '\n' termination
* check if last char is '\r'
* \return a vector of lines without [\r]\n

View File

@ -17,7 +17,7 @@
class FeaParser: public ConfigBitstreamParser {
public:
FeaParser(std::string filename, bool verbose = false);
FeaParser(const std::string &filename, bool verbose = false);
int parse() override;
void displayHeader() override;

Some files were not shown because too many files have changed in this diff Show More