Merge branch 'remotes/openocd/master' into riscv64

Merged 1025be363e

Conflicts:
	src/flash/nor/Makefile.am
	src/rtos/Makefile.am
	src/rtos/rtos.c
	src/target/Makefile.am
	src/target/target.c
	src/target/target_type.h

Doesn't build yet, but I fixed the conflicts that git pointed out.
gitignore-build
Tim Newsome 2017-06-13 11:52:50 -07:00
commit 845c2f6b69
303 changed files with 17138 additions and 10591 deletions

2
.gitignore vendored
View File

@ -52,8 +52,8 @@ doc/openocd.pg
doc/openocd.toc doc/openocd.toc
doc/openocd.tp doc/openocd.tp
doc/openocd.vr doc/openocd.vr
doc/texinfo.tex
doc/version.texi doc/version.texi
texinfo.tex
src/openocd src/openocd
src/openocd.exe src/openocd.exe

View File

@ -5,22 +5,45 @@ AUTOMAKE_OPTIONS = gnu 1.6
# make sure we pass the correct jimtcl flags to distcheck # make sure we pass the correct jimtcl flags to distcheck
DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim
# do not run Jim Tcl tests (esp. during distcheck)
check-recursive:
@true
nobase_dist_pkgdata_DATA = \ nobase_dist_pkgdata_DATA = \
contrib/libdcc/dcc_stdio.c \ contrib/libdcc/dcc_stdio.c \
contrib/libdcc/dcc_stdio.h \ contrib/libdcc/dcc_stdio.h \
contrib/libdcc/example.c \ contrib/libdcc/example.c \
contrib/libdcc/README \ contrib/libdcc/README \
contrib/99-openocd.rules contrib/60-openocd.rules
SUBDIRS =
DIST_SUBDIRS =
bin_PROGRAMS =
noinst_LTLIBRARIES =
info_TEXINFOS =
dist_man_MANS =
EXTRA_DIST =
if INTERNAL_JIMTCL if INTERNAL_JIMTCL
SUBDIRS = jimtcl SUBDIRS += jimtcl
else DIST_SUBDIRS += jimtcl
SUBDIRS =
endif endif
SUBDIRS += src doc # common flags used in openocd build
AM_CFLAGS = $(GCC_WARNINGS)
EXTRA_DIST = \ AM_CPPFLAGS = $(HOST_CPPFLAGS)\
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
-I$(top_srcdir)/src/helper \
-DPKGDATADIR=\"$(pkgdatadir)\" \
-DBINDIR=\"$(bindir)\"
if INTERNAL_JIMTCL
AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
-I$(top_builddir)/jimtcl
endif
EXTRA_DIST += \
BUGS \ BUGS \
HACKING \ HACKING \
NEWTAPS \ NEWTAPS \
@ -96,17 +119,26 @@ distclean-local:
DISTCLEANFILES = doxygen.log DISTCLEANFILES = doxygen.log
METASOURCES = AUTO
BUILT_SOURCES =
CLEANFILES =
MAINTAINERCLEANFILES = \ MAINTAINERCLEANFILES = \
$(srcdir)/INSTALL \ %D%/INSTALL \
$(srcdir)/configure \ %D%/configure \
$(srcdir)/Makefile.in \ %D%/Makefile.in \
$(srcdir)/depcomp \ %D%/depcomp \
$(srcdir)/config.guess \ %D%/config.guess \
$(srcdir)/config.sub \ %D%/config.sub \
$(srcdir)/config.h.in \ %D%/config.h.in \
$(srcdir)/config.h.in~ \ %D%/config.h.in~ \
$(srcdir)/compile \ %D%/compile \
$(srcdir)/ltmain.sh \ %D%/ltmain.sh \
$(srcdir)/missing \ %D%/missing \
$(srcdir)/aclocal.m4 \ %D%/aclocal.m4 \
$(srcdir)/install-sh %D%/install-sh \
%D%/texinfo.tex
include src/Makefile.am
include doc/Makefile.am

155
NEWS-0.10.0 Normal file
View File

@ -0,0 +1,155 @@
This file includes highlights of the changes made in the OpenOCD
source archive release.
JTAG Layer:
* New driver for J-Link adapters based on libjaylink
(including support for FPGA configuration, SWO and EMUCOM)
* FTDI improvements to work at 30MHz clock
* BCM2835 native driver SWD and Raspberry Pi2 support
* BCM2835 is set to 4ma drive, slow slew rate
* ixo-usb-jtag (emulation of an Altera Bus Blaster I on
Cypress FX2 IC) support
* JTAG pass-through mode for CMSIS-DAP (including support for
FPGA configuration)
* OpenJTAG support for Cypress CY7C65215
* connect_assert_srst support for SWD
* Xilinx Virtex-II Series7 bitstream loading support
* Use JEP106 data to decode IDs
* Deprecated "ft2232" driver removed (use "ftdi" instead)
* GPL-incompatible FTDI D2XX library support dropped (Presto,
OpenJTAG and USB-Blaster I are using libftdi only now)
* ZY1000 support dropped (unmaintained since long)
* oocd_trace support dropped
Boundary Scan:
Target Layer:
* ARMv7-A, Cortex-M, Cortex-A/R important fixes and
improvements (allowing e.g. simultaneous debugging of A8 and
M3 cores, JTAG WAIT support etc.)
* ARM Cortex-A,R allow interrupt disable during single-step
(maskisr command)
* Semihosting support for ARMv7-A
* ARM Cortex-M7 support
* Intel Quark mcu D2000 support
* Freescale LS102x SAP support
* ThreadX RTOS support on ARM926E-JS
* Cortex-M RTOS stack alignment fixes
* FreeRTOS FPU support
* uC/OS-III RTOS support
* bridging semihosting to GDB's File-I/O support
* -defer-examine option added to target create command
* verify_image_checksum command added
Flash Layer:
* Atmel SAM4S, SAM4N, SAM4C support
* Atmel SAMV, SAMS, SAME (Cortex-M7) support
* Atmel AT91SAMD handle reset run/halt in DSU, other fixes
* Atmel AT91SAML21, SAML22, SAMC20/SAMC21, SAMD09 support
* ST STM32F4x support
* ST STM32F74x/76x/77x, STM32L4 support
* ST STM32L0 categories 1, 2 and 5 support
* Kinetis K02, K21, K22, K24, K26, K63, K64, K66 support
* Kinetis KE, KVx, K8x families support
* Kinetis FlexNVM handling
* Kinetis flash protection, security, mass_erase improvements
* Infineon XMC4xxx family support
* Infineon XMC1000 flash driver
* Energy Micro EFM32 Happy Gecko support
* Energy Micro EFM32 debug interface lock support
* Analog Devices ADuCM360 support
* Unified Nuvoton NuMicro flash driver
* NIIET K1921VK01T (Cortex-M4) support
* Nordic Semiconductor nRF51 improvements
* Spansion FM4 flash (including MB9BFx64/x65, S6E2DH) driver
* Ambiq Micro Apollo flash driver
* PIC32MX new device IDs, 17x/27x flash support
* read_bank() and verify_bank() NOR flash internal API to
allow reading (and verifying) non-memory-mapped devices
* JTAGSPI driver to access SPI NOR flashes via a trivial
FPGA proxy
* Milandr read/verify for Info memory support
* Various discrete SPI NOR flashes support
* CFI 16-bit flash reversed endianness support
Board, Target, and Interface Configuration Scripts:
* Digilent JTAG-HS2, JTAG-HS3 interfaces configs
* FTDI UM232H module as JTAG interface config
* 100ask's OpenJTAG interface config
* MBFTDI interface config
* XDS100v3 interface config
* Freescale Vybrid VF6xx target config
* EmCraft VF6 SOM and baseboard configs
* Freescale SabreSD board config
* Freescale VF65GS10 tower board config
* Pipistrello Xilinx Spartan6 LX45 FPGA board config
* miniSpartan6+ board config
* Xilinx Kintex7 Development board config
* Parallella-I board config
* Digilent Atlys and Analog Discovery board configs
* Numato Opsis board config
* Xilinx Spartan 6 FPGA "Device DNA" reading support
* Altera 10M50 FPGA (MAX10 family) target config
* Altera EPM240 CPLD (MAXII family) target config
* Marsohod2, Marsohod3 FPGA, Marsohod CPLD boards configs
* Novena's integrated FPGA board config
* XMOS XS1-XAU8A-10's ARM core config
* XMOS xCORE-XA Core Module board config
* Exynos5250 target config
* Arndale board config
* FM4 MB9BFxxx family configs
* Spansion SK-FM4-U120-9B560 board config
* Diolan LPC4357-DB1 board config
* ST STM32F469 discovery board config
* ST STM32F7-DISCO, STM327[4|5]6G-EVAL boards configs
* ST STM32L4 discovery, NUCLEO L476RG, STM32F429I-DISC1 boards
configs
* Atheros AR2313, AR2315 targets config
* Netgear WP102 board config
* La Fonera FON2200 board config
* Linksys WAG200G board config
* LPC-Link2 board config
* NXP LPC4370 target config
* Atmel SAMV, SAMS, SAME target configs
* Atmel SAM E70 Xplained, SAM V71 Xplained Ultra boards
configs
* Nordic nRF52 target config
* Nordic nRF51-DK, nRF52-DK boards configs
* Infineon XMC4700 Relax Kit, XMC4800 Relax EtherCAT Kit,
XMC4300 Relax EtherCAT Kit boards configs
* Renesas S7G2 target config
* Renesas DK-S7G2 board config
* Altera EP3C10 FPGA (Cyclone III family) target config
* TI MSP432P4xx target config
* Cypress PSoC 5LP target config
* Analog Devices ADSP-SC58x target config (Cortex-A5 core only)
Server Layer:
* tcl_trace command for async target trace output via Tcl RPC
Documentation:
Build and Release:
* Various fixes thanks to http://coccinellery.org/
* libftdi is now autodetected with pkgconfig
* Releases should now support reproducible builds
* Conversion to non-recursive make, requires automake >= 1.14
* Udev rules modified to add uaccess tag and moved to
60-openocd.rules
* Support searching for scripts relative to the openocd binary
for all major architectures
This release also contains a number of other important functional and
cosmetic bugfixes. For more details about what has changed since the
last release, see the git repository history:
http://sourceforge.net/p/openocd/code/ci/v0.10.0/log/?path=
For older NEWS, see the NEWS files associated with each release
(i.e. NEWS-<version>).
For more information about contributing test reports, bug fixes, or new
features and device support, please read the new Developer Manual (or
the BUGS and PATCHES.txt files in the source archive).

55
README
View File

@ -4,7 +4,7 @@ Welcome to OpenOCD!
OpenOCD provides on-chip programming and debugging support with a OpenOCD provides on-chip programming and debugging support with a
layered architecture of JTAG interface and TAP support including: layered architecture of JTAG interface and TAP support including:
- (X)SVF playback to faciliate automated boundary scan and FPGA/CPLD - (X)SVF playback to facilitate automated boundary scan and FPGA/CPLD
programming; programming;
- debug target support (e.g. ARM, MIPS): single-stepping, - debug target support (e.g. ARM, MIPS): single-stepping,
breakpoints/watchpoints, gprof profiling, etc; breakpoints/watchpoints, gprof profiling, etc;
@ -45,9 +45,6 @@ e.g.:
openocd -f interface/stlink-v2-1.cfg -c "transport select hla_swd" \ openocd -f interface/stlink-v2-1.cfg -c "transport select hla_swd" \
-f target/stm32l0.cfg -f target/stm32l0.cfg
NB: when using an FTDI-based adapter you should prefer configs in the
ftdi directory; the old configs for the ft2232 are deprecated.
After OpenOCD startup, connect GDB with After OpenOCD startup, connect GDB with
(gdb) target extended-remote localhost:3333 (gdb) target extended-remote localhost:3333
@ -126,7 +123,7 @@ XScale, Intel Quark.
Flash drivers Flash drivers
------------- -------------
ADUC702x, AT91SAM, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, FM4, Kinetis, ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, FM4, Kinetis,
LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI, Marvell QSPI, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI, Marvell QSPI,
Milandr, NIIET, NuMicro, PIC32mx, PSoC4, SiM3x, Stellaris, STM32, STMSMI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, SiM3x, Stellaris, STM32, STMSMI,
STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx, STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx,
@ -184,10 +181,6 @@ suggestions:
particular hardware; particular hardware;
- Use "ftdi" interface adapter driver for the FTDI-based devices. - Use "ftdi" interface adapter driver for the FTDI-based devices.
As a PACKAGER, never link against the FTD2XX library, as the resulting
binaries can't be legally distributed, due to the restrictions of the
GPL.
================ ================
Building OpenOCD Building OpenOCD
@ -221,18 +214,16 @@ You'll also need:
Additionally, for building from git: Additionally, for building from git:
- autoconf >= 2.64 - autoconf >= 2.64
- automake >= 1.9 - automake >= 1.14
- texinfo - texinfo
USB-based adapters depend on libusb-1.0 and some older drivers require USB-based adapters depend on libusb-1.0 and some older drivers require
libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as
FreeBSD's, additionally needs the corresponding .pc files. FreeBSD's, additionally needs the corresponding .pc files.
USB-Blaster, ASIX Presto, OpenJTAG and ft2232 interface adapter USB-Blaster, ASIX Presto and OpenJTAG interface adapter
drivers need either one of: drivers need:
- libftdi: http://www.intra2net.com/en/developer/libftdi/index.php - libftdi: http://www.intra2net.com/en/developer/libftdi/index.php
- ftd2xx: http://www.ftdichip.com/Drivers/D2XX.htm (proprietary,
GPL-incompatible)
CMSIS-DAP support needs HIDAPI library. CMSIS-DAP support needs HIDAPI library.
@ -242,7 +233,7 @@ Permissions delegation
Running OpenOCD with root/administrative permissions is strongly Running OpenOCD with root/administrative permissions is strongly
discouraged for security reasons. discouraged for security reasons.
For USB devices on GNU/Linux you should use the contrib/99-openocd.rules For USB devices on GNU/Linux you should use the contrib/60-openocd.rules
file. It probably belongs somewhere in /etc/udev/rules.d, but file. It probably belongs somewhere in /etc/udev/rules.d, but
consult your operating system documentation to be sure. Do not forget consult your operating system documentation to be sure. Do not forget
to add yourself to the "plugdev" group. to add yourself to the "plugdev" group.
@ -304,40 +295,6 @@ use both the --enable-parport AND the --enable-parport-giveio option
if you want to use giveio instead of ioperm parallel port access if you want to use giveio instead of ioperm parallel port access
method. method.
Using FTDI's FTD2XX
-------------------
The (closed source) FTDICHIP.COM solution is faster than libftdi on
Windows. That is the motivation for supporting it even though its
licensing restricts it to non-redistributable OpenOCD binaries, and it
is not available for all operating systems used with OpenOCD. You may,
however, build such copies for personal use.
The FTDICHIP drivers come as either a (win32) ZIP file, or a (Linux)
TAR.GZ file. You must unpack them ``some where'' convenient. As of this
writing FTDICHIP does not supply means to install these files "in an
appropriate place."
You should use the following ./configure options to make use of
FTD2XX:
--with-ftd2xx-win32-zipdir
Where (CYGWIN/MINGW) the zip file from ftdichip.com
was unpacked <default=search>
--with-ftd2xx-linux-tardir
Where (Linux/Unix) the tar file from ftdichip.com
was unpacked <default=search>
--with-ftd2xx-lib=(static|shared)
Use static or shared ftd2xx libs (default is static)
Remember, this library is binary-only, while OpenOCD is licenced
according to GNU GPLv2 without any exceptions. That means that
_distributing_ copies of OpenOCD built with the FTDI code would
violate the OpenOCD licensing terms.
Note that on Linux there is no good reason to use these FTDI binaries;
they are no faster (on Linux) than libftdi, and cause licensing issues.
========================== ==========================
Obtaining OpenOCD From GIT Obtaining OpenOCD From GIT

3
TODO
View File

@ -93,9 +93,6 @@ interface support:
-# rewrite implementation to use non-blocking I/O -# rewrite implementation to use non-blocking I/O
- J-Link driver: - J-Link driver:
- fix to work with long scan chains, such as R.Doss's svf test. - fix to work with long scan chains, such as R.Doss's svf test.
- FT2232 (libftdi):
- make performance comparable to alternatives (on Win32, D2XX is faster)
- make usability comparable to alternatives
- Autodetect USB based adapters; this should be easy on Linux. If there's - Autodetect USB based adapters; this should be easy on Linux. If there's
more than one, list the options; otherwise, just select that one. more than one, list the options; otherwise, just select that one.

View File

@ -39,5 +39,12 @@ else
git submodule update git submodule update
fi fi
if [ -x src/jtag/drivers/libjaylink/autogen.sh ]; then
(
cd src/jtag/drivers/libjaylink
./autogen.sh
)
fi
echo "Bootstrap complete. Quick build instructions:" echo "Bootstrap complete. Quick build instructions:"
echo "./configure ...." echo "./configure ...."

View File

@ -1,12 +0,0 @@
# common flags used in openocd build
AM_CPPFLAGS = -I$(top_srcdir)/src \
-I$(top_builddir)/src \
-I$(top_srcdir)/src/helper \
-DPKGDATADIR=\"$(pkgdatadir)\" \
-DBINDIR=\"$(bindir)\"
if INTERNAL_JIMTCL
AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
-I$(top_builddir)/jimtcl
endif

File diff suppressed because it is too large Load Diff

145
contrib/60-openocd.rules Normal file
View File

@ -0,0 +1,145 @@
# Copy this file to /etc/udev/rules.d/
ACTION!="add|change", GOTO="openocd_rules_end"
SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end"
# Please keep this list sorted by VID:PID
# opendous and estick
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Original FT232/FT245 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Original FT2232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Original FT4232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Original FT232H VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess"
# DISTORTEC JTAG-lock-pick Tiny 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TUMPA, TUMPA Lite
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="660", GROUP="plugdev", TAG+="uaccess"
# XDS100v2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI/Luminary Stellaris Evaluation Board FTDI (several)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="660", GROUP="plugdev", TAG+="uaccess"
# egnite Turtelizer 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Section5 ICEbear
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Amontec JTAGkey and JTAGkey-tiny
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI ICDI
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess"
# STLink v1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="660", GROUP="plugdev", TAG+="uaccess"
# STLink v2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", TAG+="uaccess"
# STLink v2-1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Cypress KitProg in KitProg mode
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f139", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Cypress KitProg in CMSIS-DAP mode
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f138", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Hilscher NXHX Boards
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Hitex STR9-comStick
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Hitex STM32-PerformanceStick
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Altera USB Blaster
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Amontec JTAGkey-HiSpeed
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess"
# SEGGER J-Link
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Raisonance RLink
ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Debug Board for Neo1973
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-USB-OCD
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-USB-OCD-TINY
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-JTAG-EW
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-USB-OCD-TINY-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-USB-OCD-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess"
# USBprog with OpenOCD firmware
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess"
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Ambiq Micro EVK and Debug boards.
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="1106", MODE="664", GROUP="plugdev", TAG+="uaccess"
# Marvell Sheevaplug
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Keil Software, Inc. ULink
ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="660", GROUP="plugdev", TAG+="uaccess"
# CMSIS-DAP compatible adapters
ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess"
LABEL="openocd_rules_end"

View File

@ -1,134 +0,0 @@
# Copy this file to /etc/udev/rules.d/
ACTION!="add|change", GOTO="openocd_rules_end"
SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end"
# Please keep this list sorted by VID:PID
# opendous and estick
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="664", GROUP="plugdev"
# Original FT232/FT245 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev"
# Original FT2232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev"
# Original FT4232 VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev"
# Original FT232H VID:PID
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="664", GROUP="plugdev"
# DISTORTEC JTAG-lock-pick Tiny 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="664", GROUP="plugdev"
# TUMPA, TUMPA Lite
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev"
# XDS100v2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="664", GROUP="plugdev"
# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="664", GROUP="plugdev"
# TI/Luminary Stellaris Evaluation Board FTDI (several)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev"
# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev"
# egnite Turtelizer 2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="664", GROUP="plugdev"
# Section5 ICEbear
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev"
# Amontec JTAGkey and JTAGkey-tiny
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev"
# TI ICDI
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="664", GROUP="plugdev"
# STLink v1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="664", GROUP="plugdev"
# STLink v2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="664", GROUP="plugdev"
# STLink v2-1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev"
# Hilscher NXHX Boards
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="664", GROUP="plugdev"
# Hitex STR9-comStick
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev"
# Hitex STM32-PerformanceStick
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev"
# Altera USB Blaster
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev"
# Amontec JTAGkey-HiSpeed
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev"
# SEGGER J-Link
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="664", GROUP="plugdev"
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="664", GROUP="plugdev"
# Raisonance RLink
ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev"
# Debug Board for Neo1973
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD-TINY
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev"
# Olimex ARM-JTAG-EW
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD-TINY-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="664", GROUP="plugdev"
# USBprog with OpenOCD firmware
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev"
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev"
# Marvell Sheevaplug
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
# Keil Software, Inc. ULink
ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="664", GROUP="plugdev"
# CMSIS-DAP compatible adapters
ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev"
LABEL="openocd_rules_end"

View File

@ -12,7 +12,8 @@ ARM_CROSS_COMPILE ?= arm-none-eabi-
arm_dirs = \ arm_dirs = \
flash/fm4 \ flash/fm4 \
flash/kinetis_ke \ flash/kinetis_ke \
flash/xmc1xxx flash/xmc1xxx \
debug/xscale
arm: arm:
for d in $(common_dirs); do \ for d in $(common_dirs); do \

View File

@ -0,0 +1,33 @@
BIN2C = ../../../../src/helper/bin2char.sh
CROSS_COMPILE ?= arm-none-eabi-
CC=$(CROSS_COMPILE)gcc
OBJCOPY=$(CROSS_COMPILE)objcopy
OBJDUMP=$(CROSS_COMPILE)objdump
CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
LDFLAGS = -Tdebug_handler.ld
all: debug_handler.inc
.PHONY: clean
.INTERMEDIATE: debug_handler.elf
debug_handler.elf: protocol.h
%.elf: %.S
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
%.bin: %.elf
$(OBJCOPY) -Obinary $< $@
%.inc: %.bin
$(BIN2C) < $< > $@
clean:
-rm -f *.elf *.lst *.bin *.inc

View File

@ -0,0 +1,101 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x10,0xde,0x1a,0xee,0x02,0xd1,0x1d,0xe2,0x01,0x00,0x00,0x1a,0x03,0xd1,0xa0,0xe3,
0x10,0xde,0x0a,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0x0e,0x08,0xee,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xee,0x08,0xee,0x01,0x00,0xa0,0xe1,
0x70,0x01,0x00,0xeb,0x02,0x00,0xa0,0xe1,0x6e,0x01,0x00,0xeb,0x03,0x00,0xa0,0xe1,
0x6c,0x01,0x00,0xeb,0x04,0x00,0xa0,0xe1,0x6a,0x01,0x00,0xeb,0x05,0x00,0xa0,0xe1,
0x68,0x01,0x00,0xeb,0x06,0x00,0xa0,0xe1,0x66,0x01,0x00,0xeb,0x07,0x00,0xa0,0xe1,
0x64,0x01,0x00,0xeb,0x00,0x00,0x4f,0xe1,0x62,0x01,0x00,0xeb,0x00,0x00,0x4f,0xe1,
0x20,0x00,0xc0,0xe3,0xc0,0x00,0x80,0xe3,0x1f,0x10,0x00,0xe2,0x10,0x00,0x51,0xe3,
0x01,0x00,0x00,0x1a,0x1f,0x00,0xc0,0xe3,0x1f,0x00,0x80,0xe3,0x3d,0x00,0x00,0xea,
0x5c,0x01,0x00,0xeb,0x00,0x00,0x50,0xe3,0x39,0x00,0x00,0x0a,0x01,0x00,0x50,0xe3,
0x5a,0x00,0x00,0x0a,0x11,0x00,0x50,0xe3,0x7b,0x00,0x00,0x0a,0x12,0x00,0x50,0xe3,
0x83,0x00,0x00,0x0a,0x14,0x00,0x50,0xe3,0x8b,0x00,0x00,0x0a,0x21,0x00,0x50,0xe3,
0x93,0x00,0x00,0x0a,0x22,0x00,0x50,0xe3,0x9b,0x00,0x00,0x0a,0x24,0x00,0x50,0xe3,
0xa3,0x00,0x00,0x0a,0x30,0x00,0x50,0xe3,0x14,0x00,0x00,0x0a,0x31,0x00,0x50,0xe3,
0x2b,0x01,0x00,0x0a,0x40,0x00,0x50,0xe3,0xc4,0x00,0x00,0x0a,0x41,0x00,0x50,0xe3,
0xed,0x00,0x00,0x0a,0x50,0x00,0x50,0xe3,0xa7,0x00,0x00,0x0a,0x51,0x00,0x50,0xe3,
0xac,0x00,0x00,0x0a,0x52,0x00,0x50,0xe3,0xac,0x00,0x00,0x0a,0x53,0x00,0x50,0xe3,
0xac,0x00,0x00,0x0a,0x60,0x00,0x50,0xe3,0x9b,0x00,0x00,0x0a,0x61,0x00,0x50,0xe3,
0x0c,0x01,0x00,0x0a,0x62,0x00,0x50,0xe3,0x14,0x01,0x00,0x0a,0xd7,0xff,0xff,0xea,
0x34,0x01,0x00,0xeb,0x00,0xf0,0x69,0xe1,0x32,0x01,0x00,0xeb,0x00,0x70,0xa0,0xe1,
0x30,0x01,0x00,0xeb,0x00,0x60,0xa0,0xe1,0x2e,0x01,0x00,0xeb,0x00,0x50,0xa0,0xe1,
0x2c,0x01,0x00,0xeb,0x00,0x40,0xa0,0xe1,0x2a,0x01,0x00,0xeb,0x00,0x30,0xa0,0xe1,
0x28,0x01,0x00,0xeb,0x00,0x20,0xa0,0xe1,0x26,0x01,0x00,0xeb,0x00,0x10,0xa0,0xe1,
0x24,0x01,0x00,0xeb,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xee,0x19,0xee,
0x00,0xf0,0x5e,0xe2,0x1f,0x01,0x00,0xeb,0x00,0x70,0x0f,0xe1,0x00,0xf0,0x21,0xe1,
0x00,0x00,0xa0,0xe1,0x1f,0x10,0x00,0xe2,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,
0x10,0x8e,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0x9e,0x08,0xee,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xae,0x08,0xee,0x10,0xfe,0x1e,0xee,
0xfd,0xff,0xff,0x6a,0x10,0xbe,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,
0x10,0xce,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xde,0x08,0xee,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xee,0x08,0xee,0x1f,0x00,0x51,0xe3,
0x03,0x00,0x00,0x0a,0x00,0x00,0x4f,0xe1,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,
0x10,0x0e,0x08,0xee,0x07,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1,0x9f,0xff,0xff,0xea,
0xfc,0x00,0x00,0xeb,0x00,0x70,0x0f,0xe1,0x00,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1,
0x1f,0x10,0x00,0xe2,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x8e,0x19,0xee,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x9e,0x19,0xee,0x10,0xfe,0x1e,0xee,
0xfd,0xff,0xff,0x5a,0x10,0xae,0x19,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,
0x10,0xbe,0x19,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xce,0x19,0xee,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xde,0x19,0xee,0x10,0xfe,0x1e,0xee,
0xfd,0xff,0xff,0x5a,0x10,0xee,0x19,0xee,0x1f,0x00,0x51,0xe3,0x03,0x00,0x00,0x0a,
0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x0e,0x19,0xee,0x00,0xf0,0x69,0xe1,
0x07,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1,0x7c,0xff,0xff,0xea,0xd9,0x00,0x00,0xeb,
0x00,0x20,0xa0,0xe1,0xd7,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0x01,0x00,0xd2,0xe4,
0x9a,0x8f,0x07,0xee,0xcf,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,
0x72,0xff,0xff,0xea,0xcf,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xcd,0x00,0x00,0xeb,
0x00,0x10,0xa0,0xe1,0xb2,0x00,0xd2,0xe0,0x9a,0x8f,0x07,0xee,0xc5,0x00,0x00,0xeb,
0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x68,0xff,0xff,0xea,0xc5,0x00,0x00,0xeb,
0x00,0x20,0xa0,0xe1,0xc3,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0x04,0x00,0x92,0xe4,
0x9a,0x8f,0x07,0xee,0xbb,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,
0x5e,0xff,0xff,0xea,0xbb,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xb9,0x00,0x00,0xeb,
0x00,0x10,0xa0,0xe1,0xb7,0x00,0x00,0xeb,0x01,0x00,0xc2,0xe4,0x9a,0x8f,0x07,0xee,
0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x54,0xff,0xff,0xea,0xb1,0x00,0x00,0xeb,
0x00,0x20,0xa0,0xe1,0xaf,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0xad,0x00,0x00,0xeb,
0xb2,0x00,0xc2,0xe0,0x9a,0x8f,0x07,0xee,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,
0x4a,0xff,0xff,0xea,0xa7,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xa5,0x00,0x00,0xeb,
0x00,0x10,0xa0,0xe1,0xa3,0x00,0x00,0xeb,0x04,0x00,0x82,0xe4,0x9a,0x8f,0x07,0xee,
0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x40,0xff,0xff,0xea,0x10,0x0e,0x1a,0xee,
0x20,0x00,0xc0,0xe3,0x10,0x0e,0x0a,0xee,0x3c,0xff,0xff,0xea,0x99,0x00,0x00,0xeb,
0x01,0x1b,0xa0,0xe3,0xb2,0x0f,0x07,0xee,0x20,0x00,0x80,0xe2,0x01,0x10,0x51,0xe2,
0xfb,0xff,0xff,0x1a,0x35,0xff,0xff,0xea,0x16,0x0f,0x07,0xee,0x33,0xff,0xff,0xea,
0x15,0x0f,0x07,0xee,0x31,0xff,0xff,0xea,0x10,0x0f,0x12,0xee,0x00,0x00,0xa0,0xe1,
0x04,0xf0,0x4f,0xe2,0x2d,0xff,0xff,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x00,0x00,0xeb,0x00,0x10,0x8f,0xe2,0x80,0xf1,0x81,0xe0,0x10,0x0f,0x10,0xee,
0x23,0x00,0x00,0xea,0x30,0x0f,0x10,0xee,0x21,0x00,0x00,0xea,0x10,0x0f,0x11,0xee,
0x1f,0x00,0x00,0xea,0x30,0x0f,0x11,0xee,0x1d,0x00,0x00,0xea,0x10,0x0f,0x12,0xee,
0x1b,0x00,0x00,0xea,0x10,0x0f,0x13,0xee,0x19,0x00,0x00,0xea,0x10,0x0f,0x15,0xee,
0x17,0x00,0x00,0xea,0x10,0x0f,0x16,0xee,0x15,0x00,0x00,0xea,0x10,0x0f,0x1d,0xee,
0x13,0x00,0x00,0xea,0x10,0x0f,0x1f,0xee,0x11,0x00,0x00,0xea,0x18,0x0f,0x1e,0xee,
0x0f,0x00,0x00,0xea,0x19,0x0f,0x1e,0xee,0x0d,0x00,0x00,0xea,0x10,0x0f,0x1e,0xee,
0x0b,0x00,0x00,0xea,0x13,0x0f,0x1e,0xee,0x09,0x00,0x00,0xea,0x14,0x0f,0x1e,0xee,
0x07,0x00,0x00,0xea,0x10,0x0e,0x1b,0xee,0x05,0x00,0x00,0xea,0x10,0x0e,0x1c,0xee,
0x03,0x00,0x00,0xea,0x10,0x0e,0x1d,0xee,0x01,0x00,0x00,0xea,0x10,0x0e,0x1a,0xee,
0xff,0xff,0xff,0xea,0x53,0x00,0x00,0xeb,0xf8,0xfe,0xff,0xea,0x55,0x00,0x00,0xeb,
0x00,0x10,0xa0,0xe1,0x53,0x00,0x00,0xeb,0x00,0x20,0x8f,0xe2,0x81,0xf1,0x82,0xe0,
0x10,0x0f,0x00,0xee,0xf1,0xfe,0xff,0xea,0x30,0x0f,0x00,0xee,0xef,0xfe,0xff,0xea,
0x10,0x0f,0x01,0xee,0xed,0xfe,0xff,0xea,0x30,0x0f,0x01,0xee,0xeb,0xfe,0xff,0xea,
0x10,0x0f,0x02,0xee,0xe9,0xfe,0xff,0xea,0x10,0x0f,0x03,0xee,0xe7,0xfe,0xff,0xea,
0x10,0x0f,0x05,0xee,0xe5,0xfe,0xff,0xea,0x10,0x0f,0x06,0xee,0xe3,0xfe,0xff,0xea,
0x10,0x0f,0x0d,0xee,0xe1,0xfe,0xff,0xea,0x10,0x0f,0x0f,0xee,0xdf,0xfe,0xff,0xea,
0x18,0x0f,0x0e,0xee,0xdd,0xfe,0xff,0xea,0x19,0x0f,0x0e,0xee,0xdb,0xfe,0xff,0xea,
0x10,0x0f,0x0e,0xee,0xd9,0xfe,0xff,0xea,0x13,0x0f,0x0e,0xee,0xd7,0xfe,0xff,0xea,
0x14,0x0f,0x0e,0xee,0xd5,0xfe,0xff,0xea,0x10,0x0e,0x0b,0xee,0xd3,0xfe,0xff,0xea,
0x10,0x0e,0x0c,0xee,0xd1,0xfe,0xff,0xea,0x10,0x0e,0x0d,0xee,0xcf,0xfe,0xff,0xea,
0x10,0x0e,0x0a,0xee,0xcd,0xfe,0xff,0xea,0x01,0x1c,0xa0,0xe3,0x10,0x0e,0x1b,0xee,
0x24,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfb,0xff,0xff,0x1a,0x10,0x0e,0x1c,0xee,
0x20,0x00,0x00,0xeb,0x10,0x0e,0x1d,0xee,0x1e,0x00,0x00,0xeb,0xc3,0xfe,0xff,0xea,
0x01,0x1c,0xa0,0xe3,0x10,0x0e,0x1b,0xee,0x01,0x10,0x51,0xe2,0xfc,0xff,0xff,0x1a,
0xbe,0xfe,0xff,0xea,0x1b,0x00,0x00,0xeb,0x00,0xf0,0x69,0xe1,0x19,0x00,0x00,0xeb,
0x00,0x70,0xa0,0xe1,0x17,0x00,0x00,0xeb,0x00,0x60,0xa0,0xe1,0x15,0x00,0x00,0xeb,
0x00,0x50,0xa0,0xe1,0x13,0x00,0x00,0xeb,0x00,0x40,0xa0,0xe1,0x11,0x00,0x00,0xeb,
0x00,0x30,0xa0,0xe1,0x0f,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0x0d,0x00,0x00,0xeb,
0x00,0x10,0xa0,0xe1,0x0b,0x00,0x00,0xeb,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,
0x10,0xee,0x19,0xee,0x10,0xde,0x1a,0xee,0x01,0xd0,0x8d,0xe3,0x10,0xde,0x0a,0xee,
0x00,0xf0,0x5e,0xe2,0xfe,0xff,0xff,0xea,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,
0x10,0x0e,0x08,0xee,0x0e,0xf0,0xa0,0xe1,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,
0x10,0x0e,0x19,0xee,0x0e,0xf0,0xa0,0xe1,

View File

@ -13,20 +13,21 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
from migen.fhdl.std import * from migen import *
from mibuild.generic_platform import * from migen.build.generic_platform import *
from mibuild.xilinx import XilinxPlatform from migen.build import xilinx
from mibuild.xilinx.vivado import XilinxVivadoToolchain
from mibuild.xilinx.ise import XilinxISEToolchain
""" """
This migen script produces proxy bitstreams to allow programming SPI flashes This migen script produces proxy bitstreams to allow programming SPI flashes
behind FPGAs. JTAG signalling is connected directly to SPI signalling. CS_N is behind FPGAs.
asserted when the JTAG IR contains the USER1 instruction and the state is
SHIFT-DR.
Xilinx bscan cells sample TDO on falling TCK and forward it. Bitstream binaries built with this script are available at:
https://github.com/jordens/bscan_spi_bitstreams
JTAG signalling is connected directly to SPI signalling. CS_N is
asserted when the JTAG IR contains the USER1 instruction and the state is
SHIFT-DR. Xilinx bscan cells sample TDO on falling TCK and forward it.
MISO requires sampling on rising CLK and leads to one cycle of latency. MISO requires sampling on rising CLK and leads to one cycle of latency.
https://github.com/m-labs/migen https://github.com/m-labs/migen
@ -35,8 +36,10 @@ https://github.com/m-labs/migen
class Spartan3(Module): class Spartan3(Module):
macro = "BSCAN_SPARTAN3" macro = "BSCAN_SPARTAN3"
toolchain = "ise"
def __init__(self, platform): def __init__(self, platform):
platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup"
self.clock_domains.cd_jtag = ClockDomain(reset_less=True) self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
spi = platform.request("spiflash") spi = platform.request("spiflash")
shift = Signal() shift = Signal()
@ -58,7 +61,10 @@ class Spartan3A(Spartan3):
class Spartan6(Module): class Spartan6(Module):
toolchain = "ise"
def __init__(self, platform): def __init__(self, platform):
platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup"
self.clock_domains.cd_jtag = ClockDomain(reset_less=True) self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
spi = platform.request("spiflash") spi = platform.request("spiflash")
shift = Signal() shift = Signal()
@ -72,7 +78,13 @@ class Spartan6(Module):
class Series7(Module): class Series7(Module):
toolchain = "vivado"
def __init__(self, platform): def __init__(self, platform):
platform.toolchain.bitstream_commands.extend([
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
"set_property BITSTREAM.CONFIG.UNUSEDPIN Pullnone [current_design]",
])
self.clock_domains.cd_jtag = ClockDomain(reset_less=True) self.clock_domains.cd_jtag = ClockDomain(reset_less=True)
spi = platform.request("spiflash") spi = platform.request("spiflash")
clk = Signal() clk = Signal()
@ -89,184 +101,105 @@ class Series7(Module):
i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1) i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1)
class XilinxBscanSpi(XilinxPlatform): class XilinxBscanSpi(xilinx.XilinxPlatform):
packages = {
# (package-speedgrade, id): [cs_n, clk, mosi, miso, *pullups]
("cp132", 1): ["M2", "N12", "N2", "N8"],
("fg320", 1): ["U3", "U16", "T4", "N10"],
("fg320", 2): ["V3", "U16", "T11", "V16"],
("fg484", 1): ["Y4", "AA20", "AB14", "AB20"],
("fgg484", 1): ["Y4", "AA20", "AB14", "AB20"],
("fgg400", 1): ["Y2", "Y19", "W12", "W18"],
("ftg256", 1): ["T2", "R14", "P10", "T14"],
("ft256", 1): ["T2", "R14", "P10", "T14"],
("fg400", 1): ["Y2", "Y19", "W12", "W18"],
("cs484", 1): ["U7", "V17", "V13", "W17"],
("qg144-2", 1): ["P38", "P70", "P64", "P65", "P62", "P61"],
("cpg196-2", 1): ["P2", "N13", "P11", "N11", "N10", "P10"],
("cpg236-1", 1): ["K19", None, "D18", "D19", "G18", "F18"],
("csg484-2", 1): ["AB5", "W17", "AB17", "Y17", "V13", "W13"],
("csg324-2", 1): ["V3", "R15", "T13", "R13", "T14", "V14"],
("csg324-1", 1): ["L13", None, "K17", "K18", "L14", "M14"],
("fbg484-1", 1): ["T19", None, "P22", "R22", "P21", "R21"],
("fbg484-1", 2): ["L16", None, "H18", "H19", "G18", "F19"],
("fbg676-1", 1): ["C23", None, "B24", "A25", "B22", "A22"],
("ffg901-1", 1): ["V26", None, "R30", "T30", "R28", "T28"],
("ffg1156-1", 1): ["V30", None, "AA33", "AA34", "Y33", "Y34"],
("ffg1157-1", 1): ["AL33", None, "AN33", "AN34", "AK34", "AL34"],
("ffg1158-1", 1): ["C24", None, "A23", "A24", "B26", "A26"],
("ffg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
("fhg1761-1", 1): ["AL36", None, "AM36", "AN36", "AJ36", "AJ37"],
("flg1155-1", 1): ["AL28", None, "AE28", "AF28", "AJ29", "AJ30"],
("flg1932-1", 1): ["V32", None, "T33", "R33", "U31", "T31"],
("flg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
}
pinouts = { pinouts = {
# bitstreams are named by die, package does not matter, speed grade # bitstreams are named by die, package does not matter, speed grade
# should not matter. # should not matter.
# cs_n, clk, mosi, miso, *pullups #
"xc3s100e": ("cp132", # chip: (package, id, standard, class)
["M2", "N12", "N2", "N8"], "xc3s100e": ("cp132", 1, "LVCMOS33", Spartan3),
"LVCMOS33", Spartan3), "xc3s1200e": ("fg320", 1, "LVCMOS33", Spartan3),
"xc3s1200e": ("fg320", "xc3s1400a": ("fg484", 1, "LVCMOS33", Spartan3A),
["U3", "U16", "T4", "N10"], "xc3s1400an": ("fgg484", 1, "LVCMOS33", Spartan3A),
"LVCMOS33", Spartan3), "xc3s1600e": ("fg320", 1, "LVCMOS33", Spartan3),
"xc3s1400a": ("fg484", "xc3s200a": ("fg320", 2, "LVCMOS33", Spartan3A),
["Y4", "AA20", "AB14", "AB20"], "xc3s200an": ("ftg256", 1, "LVCMOS33", Spartan3A),
"LVCMOS33", Spartan3A), "xc3s250e": ("cp132", 1, "LVCMOS33", Spartan3),
"xc3s1400an": ("fgg484", "xc3s400a": ("fg320", 2, "LVCMOS33", Spartan3A),
["Y4", "AA20", "AB14", "AB20"], "xc3s400an": ("fgg400", 1, "LVCMOS33", Spartan3A),
"LVCMOS33", Spartan3A), "xc3s500e": ("cp132", 1, "LVCMOS33", Spartan3),
"xc3s1600e": ("fg320", "xc3s50a": ("ft256", 1, "LVCMOS33", Spartan3A),
["U3", "U16", "T4", "N10"], "xc3s50an": ("ftg256", 1, "LVCMOS33", Spartan3A),
"LVCMOS33", Spartan3), "xc3s700a": ("fg400", 1, "LVCMOS33", Spartan3A),
"xc3s200a": ("fg320", "xc3s700an": ("fgg484", 1, "LVCMOS33", Spartan3A),
["V3", "U16", "T11", "V16"], "xc3sd1800a": ("cs484", 1, "LVCMOS33", Spartan3A),
"LVCMOS33", Spartan3A), "xc3sd3400a": ("cs484", 1, "LVCMOS33", Spartan3A),
"xc3s200an": ("ftg256",
["T2", "R14", "P10", "T14"],
"LVCMOS33", Spartan3A),
"xc3s250e": ("cp132",
["M2", "N12", "N2", "N8"],
"LVCMOS33", Spartan3),
"xc3s400a": ("fg320",
["V3", "U16", "T11", "V16"],
"LVCMOS33", Spartan3A),
"xc3s400an": ("fgg400",
["Y2", "Y19", "W12", "W18"],
"LVCMOS33", Spartan3A),
"xc3s500e": ("cp132",
["M2", "N12", "N2", "N8"],
"LVCMOS33", Spartan3),
"xc3s50a": ("ft256",
["T2", "R14", "P10", "T14"],
"LVCMOS33", Spartan3A),
"xc3s50an": ("ftg256",
["T2", "R14", "P10", "T14"],
"LVCMOS33", Spartan3A),
"xc3s700a": ("fg400",
["Y2", "Y19", "W12", "W18"],
"LVCMOS33", Spartan3A),
"xc3s700an": ("fgg484",
["Y4", "AA20", "AB14", "AB20"],
"LVCMOS33", Spartan3A),
"xc3sd1800a": ("cs484",
["U7", "V17", "V13", "W17"],
"LVCMOS33", Spartan3A),
"xc3sd3400a": ("cs484",
["U7", "V17", "V13", "W17"],
"LVCMOS33", Spartan3A),
"xc6slx100": ("csg484-2", "xc6slx100": ("csg484-2", 1, "LVCMOS33", Spartan6),
["AB5", "W17", "AB17", "Y17", "V13", "W13"], "xc6slx100t": ("csg484-2", 1, "LVCMOS33", Spartan6),
"LVCMOS33", Spartan6), "xc6slx150": ("csg484-2", 1, "LVCMOS33", Spartan6),
"xc6slx100t": ("csg484-2", "xc6slx150t": ("csg484-2", 1, "LVCMOS33", Spartan6),
["AB5", "W17", "AB17", "Y17", "V13", "W13"], "xc6slx16": ("cpg196-2", 1, "LVCMOS33", Spartan6),
"LVCMOS33", Spartan6), "xc6slx25": ("csg324-2", 1, "LVCMOS33", Spartan6),
"xc6slx150": ("csg484-2", "xc6slx25t": ("csg324-2", 1, "LVCMOS33", Spartan6),
["AB5", "W17", "AB17", "Y17", "V13", "W13"], "xc6slx45": ("csg324-2", 1, "LVCMOS33", Spartan6),
"LVCMOS33", Spartan6), "xc6slx45t": ("csg324-2", 1, "LVCMOS33", Spartan6),
"xc6slx150t": ("csg484-2", "xc6slx4": ("cpg196-2", 1, "LVCMOS33", Spartan6),
["AB5", "W17", "AB17", "Y17", "V13", "W13"], "xc6slx4t": ("qg144-2", 1, "LVCMOS33", Spartan6),
"LVCMOS33", Spartan6), "xc6slx75": ("csg484-2", 1, "LVCMOS33", Spartan6),
"xc6slx16": ("cpg196-2", "xc6slx75t": ("csg484-2", 1, "LVCMOS33", Spartan6),
["P2", "N13", "P11", "N11", "N10", "P10"], "xc6slx9": ("cpg196-2", 1, "LVCMOS33", Spartan6),
"LVCMOS33", Spartan6), "xc6slx9t": ("qg144-2", 1, "LVCMOS33", Spartan6),
"xc6slx25": ("csg324-2",
["V3", "R15", "T13", "R13", "T14", "V14"],
"LVCMOS33", Spartan6),
"xc6slx25t": ("csg324-2",
["V3", "R15", "T13", "R13", "T14", "V14"],
"LVCMOS33", Spartan6),
"xc6slx45": ("csg324-2",
["V3", "R15", "T13", "R13", "T14", "V14"],
"LVCMOS33", Spartan6),
"xc6slx45t": ("csg324-2",
["V3", "R15", "T13", "R13", "T14", "V14"],
"LVCMOS33", Spartan6),
"xc6slx4": ("cpg196-2",
["P2", "N13", "P11", "N11", "N10", "P10"],
"LVCMOS33", Spartan6),
"xc6slx4t": ("qg144-2",
["P38", "P70", "P64", "P65", "P62", "P61"],
"LVCMOS33", Spartan6),
"xc6slx75": ("csg484-2",
["AB5", "W17", "AB17", "Y17", "V13", "W13"],
"LVCMOS33", Spartan6),
"xc6slx75t": ("csg484-2",
["AB5", "W17", "AB17", "Y17", "V13", "W13"],
"LVCMOS33", Spartan6),
"xc6slx9": ("cpg196-2",
["P2", "N13", "P11", "N11", "N10", "P10"],
"LVCMOS33", Spartan6),
"xc6slx9t": ("qg144-2",
["P38", "P70", "P64", "P65", "P62", "P61"],
"LVCMOS33", Spartan6),
"xc7a100t": ("csg324-1", "xc7a100t": ("csg324-1", 1, "LVCMOS25", Series7),
["L13", None, "K17", "K18", "L14", "M14"], "xc7a15t": ("cpg236-1", 1, "LVCMOS25", Series7),
"LVCMOS25", Series7), "xc7a200t": ("fbg484-1", 1, "LVCMOS25", Series7),
"xc7a15t": ("cpg236-1", "xc7a35t": ("cpg236-1", 1, "LVCMOS25", Series7),
["K19", None, "D18", "D19", "G18", "F18"], "xc7a50t": ("cpg236-1", 1, "LVCMOS25", Series7),
"LVCMOS25", Series7), "xc7a75t": ("csg324-1", 1, "LVCMOS25", Series7),
"xc7a200t": ("fbg484-1", "xc7k160t": ("fbg484-1", 2, "LVCMOS25", Series7),
["T19", None, "P22", "R22", "P21", "R21"], "xc7k325t": ("fbg676-1", 1, "LVCMOS25", Series7),
"LVCMOS25", Series7), "xc7k355t": ("ffg901-1", 1, "LVCMOS25", Series7),
"xc7a35t": ("cpg236-1", "xc7k410t": ("fbg676-1", 1, "LVCMOS25", Series7),
["K19", None, "D18", "D19", "G18", "F18"], "xc7k420t": ("ffg1156-1", 1, "LVCMOS25", Series7),
"LVCMOS25", Series7), "xc7k480t": ("ffg1156-1", 1, "LVCMOS25", Series7),
"xc7a50t": ("cpg236-1", "xc7k70t": ("fbg484-1", 2, "LVCMOS25", Series7),
["K19", None, "D18", "D19", "G18", "F18"], "xc7v2000t": ("fhg1761-1", 1, "LVCMOS18", Series7),
"LVCMOS25", Series7), "xc7v585t": ("ffg1157-1", 1, "LVCMOS18", Series7),
"xc7a75t": ("csg324-1", "xc7vh580t": ("flg1155-1", 1, "LVCMOS18", Series7),
["L13", None, "K17", "K18", "L14", "M14"], "xc7vh870t": ("flg1932-1", 1, "LVCMOS18", Series7),
"LVCMOS25", Series7), "xc7vx1140t": ("flg1926-1", 1, "LVCMOS18", Series7),
"xc7k160t": ("fbg484-1", "xc7vx330t": ("ffg1157-1", 1, "LVCMOS18", Series7),
["L16", None, "H18", "H19", "G18", "F19"], "xc7vx415t": ("ffg1157-1", 1, "LVCMOS18", Series7),
"LVCMOS25", Series7), "xc7vx485t": ("ffg1157-1", 1, "LVCMOS18", Series7),
"xc7k325t": ("fbg676-1", "xc7vx550t": ("ffg1158-1", 1, "LVCMOS18", Series7),
["C23", None, "B24", "A25", "B22", "A22"], "xc7vx690t": ("ffg1157-1", 1, "LVCMOS18", Series7),
"LVCMOS25", Series7), "xc7vx980t": ("ffg1926-1", 1, "LVCMOS18", Series7),
"xc7k355t": ("ffg901-1",
["V26", None, "R30", "T30", "R28", "T28"],
"LVCMOS25", Series7),
"xc7k410t": ("fbg676-1",
["C23", None, "B24", "A25", "B22", "A22"],
"LVCMOS25", Series7),
"xc7k420t": ("ffg1156-1",
["V30", None, "AA33", "AA34", "Y33", "Y34"],
"LVCMOS25", Series7),
"xc7k480t": ("ffg1156-1",
["V30", None, "AA33", "AA34", "Y33", "Y34"],
"LVCMOS25", Series7),
"xc7k70t": ("fbg484-1",
["L16", None, "H18", "H19", "G18", "F19"],
"LVCMOS25", Series7),
"xc7v2000t": ("fhg1761-1",
["AL36", None, "AM36", "AN36", "AJ36", "AJ37"],
"LVCMOS18", Series7),
"xc7v585t": ("ffg1157-1",
["AL33", None, "AN33", "AN34", "AK34", "AL34"],
"LVCMOS18", Series7),
"xc7vh580t": ("flg1155-1",
["AL28", None, "AE28", "AF28", "AJ29", "AJ30"],
"LVCMOS18", Series7),
"xc7vh870t": ("flg1932-1",
["V32", None, "T33", "R33", "U31", "T31"],
"LVCMOS18", Series7),
"xc7vx1140t": ("flg1926-1",
["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
"LVCMOS18", Series7),
"xc7vx330t": ("ffg1157-1",
["AL33", None, "AN33", "AN34", "AK34", "AL34"],
"LVCMOS18", Series7),
"xc7vx415t": ("ffg1157-1",
["AL33", None, "AN33", "AN34", "AK34", "AL34"],
"LVCMOS18", Series7),
"xc7vx485t": ("ffg1157-1",
["AL33", None, "AN33", "AN34", "AK34", "AL34"],
"LVCMOS18", Series7),
"xc7vx550t": ("ffg1158-1",
["C24", None, "A23", "A24", "B26", "A26"],
"LVCMOS18", Series7),
"xc7vx690t": ("ffg1157-1",
["AL33", None, "AN33", "AN34", "AK34", "AL34"],
"LVCMOS18", Series7),
"xc7vx980t": ("ffg1926-1",
["AK33", None, "AN34", "AN35", "AJ34", "AK34"],
"LVCMOS18", Series7),
} }
def __init__(self, device, pins, std): def __init__(self, device, pins, std, toolchain="ise"):
cs_n, clk, mosi, miso = pins[:4] cs_n, clk, mosi, miso = pins[:4]
io = ["spiflash", 0, io = ["spiflash", 0,
Subsignal("cs_n", Pins(cs_n)), Subsignal("cs_n", Pins(cs_n)),
@ -278,26 +211,21 @@ class XilinxBscanSpi(XilinxPlatform):
io.append(Subsignal("clk", Pins(clk))) io.append(Subsignal("clk", Pins(clk)))
for i, p in enumerate(pins[4:]): for i, p in enumerate(pins[4:]):
io.append(Subsignal("pullup{}".format(i), Pins(p), Misc("PULLUP"))) io.append(Subsignal("pullup{}".format(i), Pins(p), Misc("PULLUP")))
xilinx.XilinxPlatform.__init__(self, device, [io], toolchain=toolchain)
XilinxPlatform.__init__(self, device, [io])
if isinstance(self.toolchain, XilinxVivadoToolchain):
self.toolchain.bitstream_commands.append(
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]"
)
elif isinstance(self.toolchain, XilinxISEToolchain):
self.toolchain.bitgen_opt += " -g compress"
@classmethod @classmethod
def make(cls, device, errors=False): def make(cls, device, errors=False):
pkg, pins, std, Top = cls.pinouts[device] pkg, id, std, Top = cls.pinouts[device]
platform = cls("{}-{}".format(device, pkg), pins, std) pins = cls.packages[(pkg, id)]
platform = cls("{}-{}".format(device, pkg), pins, std, Top.toolchain)
top = Top(platform) top = Top(platform)
name = "bscan_spi_{}".format(device) name = "bscan_spi_{}".format(device)
dir = "build_{}".format(device) dir = "build_{}".format(device)
try: try:
platform.build(top, build_name=name, build_dir=dir) platform.build(top, build_name=name, build_dir=dir)
except Exception as e: except Exception as e:
print("ERROR: build failed for {}: {}".format(device, e)) print(("ERROR: xilinx_bscan_spi build failed "
"for {}: {}").format(device, e))
if errors: if errors:
raise raise

View File

@ -0,0 +1,19 @@
BIN2C = ../../../../src/helper/bin2char.sh
CROSS_COMPILE ?= arm-none-eabi-
AS = $(CROSS_COMPILE)as
OBJCOPY = $(CROSS_COMPILE)objcopy
all: kinetis_flash.inc
%.elf: %.s
$(AS) $< -o $@
%.bin: %.elf
$(OBJCOPY) -Obinary $< $@
%.inc: %.bin
$(BIN2C) < $< > $@
clean:
-rm -f *.elf *.bin *.inc

View File

@ -0,0 +1,6 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
0x16,0x68,0x00,0x2e,0x1f,0xd0,0x55,0x68,0xb5,0x42,0xf9,0xd0,0x60,0x60,0x06,0x27,
0xe7,0x71,0x2f,0x68,0xa7,0x60,0x80,0x27,0x27,0x70,0x04,0x35,0x9d,0x42,0x01,0xd3,
0x15,0x1c,0x08,0x35,0x55,0x60,0x16,0x68,0x00,0x2e,0x0c,0xd0,0x26,0x78,0x3e,0x42,
0xf9,0xd0,0x70,0x27,0x3e,0x42,0x04,0xd1,0x04,0x30,0x01,0x39,0x00,0x29,0xdf,0xd1,
0x01,0xe0,0x00,0x25,0x55,0x60,0x00,0xbe,

View File

@ -0,0 +1,101 @@
/***************************************************************************
* Copyright (C) 2015 by Ivan Meleca *
* ivan@artekit.eu *
* *
* Copyright (C) 2016 by Tomas Vanek *
* vanekt@fbl.cz *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
***************************************************************************/
/* Params:
* r0 = flash destination address in/out
* r1 = longword count
* r2 = workarea start address
* r3 = workarea end address
* r4 = FTFx base
*/
.text
.cpu cortex-m0plus
.code 16
.thumb_func
.align 2
/* r5 = rp
* r6 = wp, tmp
* r7 = tmp
*/
/* old longword algo: 6.680 KiB/s @ adapter_khz 2000
* this async algo: 19.808 KiB/s @ adapter_khz 2000
*/
FTFx_FSTAT = 0
FTFx_FCCOB3 = 4
FTFx_FCCOB0 = 7
FTFx_FCCOB7 = 8
wait_fifo:
ldr r6, [r2, #0] /* read wp */
cmp r6, #0 /* abort if wp == 0 */
beq exit
ldr r5, [r2, #4] /* read rp */
cmp r5, r6 /* wait until rp != wp */
beq wait_fifo
str r0, [r4, #FTFx_FCCOB3] /* set flash address */
mov r7, #6
strb r7, [r4, #FTFx_FCCOB0] /* flash command */
ldr r7, [r5] /* set longword data = *rp */
str r7, [r4, #FTFx_FCCOB7]
mov r7, #128
strb r7, [r4, #FTFx_FSTAT]
add r5, #4 /* rp += 4 */
cmp r5, r3 /* Wrap? */
bcc no_wrap
mov r5, r2
add r5, #8
no_wrap:
str r5, [r2, #4] /* Store rp */
wait_ccif:
ldr r6, [r2, #0] /* read wp */
cmp r6, #0 /* abort if wp == 0 */
beq exit
ldrb r6, [r4, #FTFx_FSTAT]
tst r6, r7
beq wait_ccif
mov r7, #0x70
tst r6, r7
bne error
add r0, #4 /* flash address += 4, do not increment before err check */
sub r1, #1 /* word_count-- */
cmp r1, #0
bne wait_fifo
b exit
error:
mov r5, #0
str r5, [r2, #4] /* set rp = 0 on error */
exit:
bkpt #0

View File

@ -8,6 +8,9 @@
* Copyright (C) 2011 Clement Burin des Roziers * * Copyright (C) 2011 Clement Burin des Roziers *
* clement.burin-des-roziers@hikob.com * * clement.burin-des-roziers@hikob.com *
* * * *
* Copyright (C) 2017 Armin van der Togt *
* armin@otheruse.nl *
* *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@ -28,7 +31,7 @@
// Build : arm-eabi-gcc -c stm32lx.S // Build : arm-eabi-gcc -c stm32lx.S
.text .text
.syntax unified .syntax unified
.cpu cortex-m3 .cpu cortex-m0
.thumb .thumb
.thumb_func .thumb_func
.global write .global write
@ -39,24 +42,21 @@
r2 - count r2 - count
*/ */
// Set 0 to r3 // r2 = source + count * 4
movs r3, #0 lsls r2, r2, #2
adds r2, r1, r2
// Go to compare // Go to compare
b.n test_done b test_done
write_word: write_word:
// Load one word from address in r0, increment by 4 // load word from address in r1 and increase r1 by 4
ldr.w ip, [r1], #4 ldmia r1!, {r3}
// Store the word to address in r1, increment by 4 // store word to address in r0 and increase r0 by 4
str.w ip, [r0], #4 stmia r0!, {r3}
// Increment r3
adds r3, #1
test_done: test_done:
// Compare r3 and r2 // compare r1 and r2
cmp r3, r2 cmp r1, r2
// Loop if not zero // loop if not equal
bcc.n write_word bne write_word
// Set breakpoint to exit // Set breakpoint to exit
bkpt #0x00 bkpt #0x00

View File

@ -0,0 +1,32 @@
/*
* uC/OS-III does not provide a fixed layout for OS_TCB, which makes it
* impossible to determine the appropriate offsets within the structure
* unaided. A priori knowledge of offsets based on os_dbg.c is tied to a
* specific release and thusly, brittle. The constants defined below
* provide the neccessary information OpenOCD needs to provide support
* in the most robust manner possible.
*
* This file should be linked along with the project to enable RTOS
* support for uC/OS-III.
*/
#include <os.h>
#if OS_CFG_DBG_EN == 0
#error "OS_CFG_DBG_EN is required to enable RTOS support for OpenOCD"
#endif
#define OFFSET_OF(type, member) ((CPU_SIZE_T)&(((type *)0)->member))
#ifdef __GNUC__
#define USED __attribute__((used))
#else
#define USED
#endif
const CPU_SIZE_T USED openocd_OS_TCB_StkPtr_offset = OFFSET_OF(OS_TCB, StkPtr);
const CPU_SIZE_T USED openocd_OS_TCB_NamePtr_offset = OFFSET_OF(OS_TCB, NamePtr);
const CPU_SIZE_T USED openocd_OS_TCB_TaskState_offset = OFFSET_OF(OS_TCB, TaskState);
const CPU_SIZE_T USED openocd_OS_TCB_Prio_offset = OFFSET_OF(OS_TCB, Prio);
const CPU_SIZE_T USED openocd_OS_TCB_DbgPrevPtr_offset = OFFSET_OF(OS_TCB, DbgPrevPtr);
const CPU_SIZE_T USED openocd_OS_TCB_DbgNextPtr_offset = OFFSET_OF(OS_TCB, DbgNextPtr);

View File

@ -1,204 +0,0 @@
TODO!!! this should be merged into openocd.texi!!!
Prerequisites
=============
When building with support for FTDI FT2232 based devices, you need at least
one of the following libraries:
- libftdi (http://www.intra2net.com/opensource/ftdi/)
- libftd2xx (http://www.ftdichip.com/Drivers/D2XX.htm)
On Windows, you need either Cygwin or MinGW, but compilation for MinGW is also
possible using a Cygwin host.
Basic Installation
==================
OpenOCD is distributed without autotools generated files, i.e. without a
configure script. Run ./bootstrap in the openocd directory to have all
necessary files generated.
You have to explicitly enable desired JTAG interfaces during configure:
./configure --enable-parport --enable-ft2232-libftdi (OR --enable-ft2232-ftd2xx) \
--enable-amtjtagaccel
Under Windows/Cygwin, only the ftd2xx driver is supported for FT2232 based
devices. You have to specify the location of the FTDI driver package with the
--with-ftd2xx=/full/path/name option.
Under Linux you can choose to build the parport driver with support for
/dev/parportN instead of the default access with direct port I/O using
--enable-parport_ppdev. This has the advantage of running OpenOCD without root
privileges at the expense of a slight performance decrease. This is also
available on FreeBSD using PPI, but the naming of the devices is different.
Generic installation instructions
=================================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Type `make install' to install the programs and any data files and
documentation.
4. You can remove the program binaries and object files from the
source code directory by typing `make clean'.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made.
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@ -1,13 +1,11 @@
info_TEXINFOS = openocd.texi info_TEXINFOS += %D%/openocd.texi
openocd_TEXINFOS = fdl.texi %C%_openocd_TEXINFOS = %D%/fdl.texi
man_MANS = openocd.1
EXTRA_DIST = openocd.1 \
manual \
INSTALL.txt
MAINTAINERCLEANFILES = \ dist_man_MANS += %D%/openocd.1
$(srcdir)/Makefile.in \
$(srcdir)/mdate-sh \ EXTRA_DIST += %D%/manual
$(srcdir)/stamp-vti \
$(srcdir)/version.texi \ MAINTAINERCLEANFILES += \
$(srcdir)/texinfo.tex %D%/mdate-sh \
%D%/stamp-vti \
%D%/version.texi

View File

@ -334,7 +334,7 @@ git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}"
configuring its contents, using them to build a copy of OpenOCD, configuring its contents, using them to build a copy of OpenOCD,
and verifying that the result prints the correct release version and verifying that the result prints the correct release version
in its startup banner. (For example, in its startup banner. (For example,
"configure --enable-ft2232_libftdi --enable-parport" "configure --enable-parport"
then "make" and run "src/openocd -v" as a sanity check.) then "make" and run "src/openocd -v" as a sanity check.)
-# Run <code>make docs</code> to create the -# Run <code>make docs</code> to create the
documentation which will be published. documentation which will be published.

View File

@ -66,7 +66,7 @@ Free Documentation License''.
* Running:: Running OpenOCD * Running:: Running OpenOCD
* OpenOCD Project Setup:: OpenOCD Project Setup * OpenOCD Project Setup:: OpenOCD Project Setup
* Config File Guidelines:: Config File Guidelines * Config File Guidelines:: Config File Guidelines
* Daemon Configuration:: Daemon Configuration * Server Configuration:: Server Configuration
* Debug Adapter Configuration:: Debug Adapter Configuration * Debug Adapter Configuration:: Debug Adapter Configuration
* Reset Configuration:: Reset Configuration * Reset Configuration:: Reset Configuration
* TAP Declaration:: TAP Declaration * TAP Declaration:: TAP Declaration
@ -595,6 +595,9 @@ produced, PDF schematics are easily found and it is easy to make.
@item @b{bcm2835gpio} @item @b{bcm2835gpio}
@* A BCM2835-based board (e.g. Raspberry Pi) using the GPIO pins of the expansion header. @* A BCM2835-based board (e.g. Raspberry Pi) using the GPIO pins of the expansion header.
@item @b{imx_gpio}
@* A NXP i.MX-based board (e.g. Wandboard) using the GPIO pins (should work on any i.MX processor).
@item @b{jtag_vpi} @item @b{jtag_vpi}
@* A JTAG driver acting as a client for the JTAG VPI server interface. @* A JTAG driver acting as a client for the JTAG VPI server interface.
@* Link: @url{http://github.com/fjullien/jtag_vpi} @* Link: @url{http://github.com/fjullien/jtag_vpi}
@ -752,13 +755,13 @@ on the command line or, if there were no @option{-c command} or
At the end of the configuration stage it verifies the JTAG scan At the end of the configuration stage it verifies the JTAG scan
chain defined using those commands; your configuration should chain defined using those commands; your configuration should
ensure that this always succeeds. ensure that this always succeeds.
Normally, OpenOCD then starts running as a daemon. Normally, OpenOCD then starts running as a server.
Alternatively, commands may be used to terminate the configuration Alternatively, commands may be used to terminate the configuration
stage early, perform work (such as updating some flash memory), stage early, perform work (such as updating some flash memory),
and then shut down without acting as a daemon. and then shut down without acting as a server.
Once OpenOCD starts running as a daemon, it waits for connections from Once OpenOCD starts running as a server, it waits for connections from
clients (Telnet, GDB, Other) and processes the commands issued through clients (Telnet, GDB, RPC) and processes the commands issued through
those channels. those channels.
If you are having problems, you can enable internal debug messages via If you are having problems, you can enable internal debug messages via
@ -775,7 +778,7 @@ informational messages, warnings and errors. You can also change this
setting from within a telnet or gdb session using @command{debug_level<n>} setting from within a telnet or gdb session using @command{debug_level<n>}
(@pxref{debuglevel,,debug_level}). (@pxref{debuglevel,,debug_level}).
You can redirect all output from the daemon to a file using the You can redirect all output from the server to a file using the
@option{-l <logfile>} switch. @option{-l <logfile>} switch.
Note! OpenOCD will launch the GDB & telnet server even if it can not Note! OpenOCD will launch the GDB & telnet server even if it can not
@ -898,7 +901,7 @@ using a Signalyzer FT2232-based JTAG adapter to talk to
a board with an Atmel AT91SAM7X256 microcontroller: a board with an Atmel AT91SAM7X256 microcontroller:
@example @example
source [find interface/signalyzer.cfg] source [find interface/ftdi/signalyzer.cfg]
# GDB can also flash my flash! # GDB can also flash my flash!
gdb_memory_map enable gdb_memory_map enable
@ -910,7 +913,7 @@ source [find target/sam7x256.cfg]
Here is the command line equivalent of that configuration: Here is the command line equivalent of that configuration:
@example @example
openocd -f interface/signalyzer.cfg \ openocd -f interface/ftdi/signalyzer.cfg \
-c "gdb_memory_map enable" \ -c "gdb_memory_map enable" \
-c "gdb_flash_program enable" \ -c "gdb_flash_program enable" \
-f target/sam7x256.cfg -f target/sam7x256.cfg
@ -1994,8 +1997,8 @@ proc setc15 @{regs value@} @{
@node Daemon Configuration @node Server Configuration
@chapter Daemon Configuration @chapter Server Configuration
@cindex initialization @cindex initialization
The commands here are commonly found in the openocd.cfg file and are The commands here are commonly found in the openocd.cfg file and are
used to specify what TCP/IP ports are used, and how GDB should be used to specify what TCP/IP ports are used, and how GDB should be
@ -2109,7 +2112,7 @@ communicate via pipes(stdin/out or named pipes). The name
the normal use cases. the normal use cases.
No arguments reports GDB port. "pipe" means listen to stdin No arguments reports GDB port. "pipe" means listen to stdin
output to stdout, an integer is base port number, "disable" output to stdout, an integer is base port number, "disabled"
disables the gdb server. disables the gdb server.
When using "pipe", also use log_output to redirect the log When using "pipe", also use log_output to redirect the log
@ -2403,113 +2406,15 @@ A dummy software-only driver for debugging.
Cirrus Logic EP93xx based single-board computer bit-banging (in development) Cirrus Logic EP93xx based single-board computer bit-banging (in development)
@end deffn @end deffn
@deffn {Interface Driver} {ft2232}
FTDI FT2232 (USB) based devices over one of the userspace libraries.
Note that this driver has several flaws and the @command{ftdi} driver is
recommended as its replacement.
These interfaces have several commands, used to configure the driver
before initializing the JTAG scan chain:
@deffn {Config Command} {ft2232_device_desc} description
Provides the USB device description (the @emph{iProduct string})
of the FTDI FT2232 device. If not
specified, the FTDI default value is used. This setting is only valid
if compiled with FTD2XX support.
@end deffn
@deffn {Config Command} {ft2232_serial} serial-number
Specifies the @var{serial-number} of the FTDI FT2232 device to use,
in case the vendor provides unique IDs and more than one FT2232 device
is connected to the host.
If not specified, serial numbers are not considered.
(Note that USB serial numbers can be arbitrary Unicode strings,
and are not restricted to containing only decimal digits.)
@end deffn
@deffn {Config Command} {ft2232_layout} name
Each vendor's FT2232 device can use different GPIO signals
to control output-enables, reset signals, and LEDs.
Currently valid layout @var{name} values include:
@itemize @minus
@item @b{axm0432_jtag} Axiom AXM-0432
@item @b{comstick} Hitex STR9 comstick
@item @b{cortino} Hitex Cortino JTAG interface
@item @b{evb_lm3s811} TI/Luminary Micro EVB_LM3S811 as a JTAG interface,
either for the local Cortex-M3 (SRST only)
or in a passthrough mode (neither SRST nor TRST)
This layout can not support the SWO trace mechanism, and should be
used only for older boards (before rev C).
@item @b{luminary_icdi} This layout should be used with most TI/Luminary
eval boards, including Rev C LM3S811 eval boards and the eponymous
ICDI boards, to debug either the local Cortex-M3 or in passthrough mode
to debug some other target. It can support the SWO trace mechanism.
@item @b{flyswatter} Tin Can Tools Flyswatter
@item @b{icebear} ICEbear JTAG adapter from Section 5
@item @b{jtagkey} Amontec JTAGkey and JTAGkey-Tiny (and compatibles)
@item @b{jtagkey2} Amontec JTAGkey2 (and compatibles)
@item @b{m5960} American Microsystems M5960
@item @b{olimex-jtag} Olimex ARM-USB-OCD and ARM-USB-Tiny
@item @b{oocdlink} OOCDLink
@c oocdlink ~= jtagkey_prototype_v1
@item @b{redbee-econotag} Integrated with a Redbee development board.
@item @b{redbee-usb} Integrated with a Redbee USB-stick development board.
@item @b{sheevaplug} Marvell Sheevaplug development kit
@item @b{signalyzer} Xverve Signalyzer
@item @b{stm32stick} Hitex STM32 Performance Stick
@item @b{turtelizer2} egnite Software turtelizer2
@item @b{usbjtag} "USBJTAG-1" layout described in the OpenOCD diploma thesis
@end itemize
@end deffn
@deffn {Config Command} {ft2232_vid_pid} [vid pid]+
The vendor ID and product ID of the FTDI FT2232 device. If not specified, the FTDI
default values are used.
Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g.
@example
ft2232_vid_pid 0x0403 0xcff8 0x15ba 0x0003
@end example
@end deffn
@deffn {Config Command} {ft2232_latency} ms
On some systems using FT2232 based JTAG interfaces the FT_Read function call in
ft2232_read() fails to return the expected number of bytes. This can be caused by
USB communication delays and has proved hard to reproduce and debug. Setting the
FT2232 latency timer to a larger value increases delays for short USB packets but it
also reduces the risk of timeouts before receiving the expected number of bytes.
The OpenOCD default value is 2 and for some systems a value of 10 has proved useful.
@end deffn
@deffn {Config Command} {ft2232_channel} channel
Used to select the channel of the ft2232 chip to use (between 1 and 4).
The default value is 1.
@end deffn
For example, the interface config file for a
Turtelizer JTAG Adapter looks something like this:
@example
interface ft2232
ft2232_device_desc "Turtelizer JTAG/RS232 Adapter"
ft2232_layout turtelizer2
ft2232_vid_pid 0x0403 0xbdc8
@end example
@end deffn
@deffn {Interface Driver} {ftdi} @deffn {Interface Driver} {ftdi}
This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial
Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H.
It is a complete rewrite to address a large number of problems with the ft2232
interface driver.
The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device,
bypassing intermediate libraries like libftdi of D2XX. Performance-wise it is bypassing intermediate libraries like libftdi or D2XX.
consistently faster than the ft2232 driver, sometimes several times faster.
A major improvement of this driver is that support for new FTDI based adapters Support for new FTDI based adapters can be added competely through
can be added competely through configuration files, without the need to patch configuration files, without the need to patch and rebuild OpenOCD.
and rebuild OpenOCD.
The driver uses a signal abstraction to enable Tcl configuration files to The driver uses a signal abstraction to enable Tcl configuration files to
define outputs for one or several FTDI GPIO. These outputs can then be define outputs for one or several FTDI GPIO. These outputs can then be
@ -2518,6 +2423,12 @@ are reserved for nTRST, nSRST and LED (for blink) so that they, if defined,
will be used for their customary purpose. Inputs can be read using the will be used for their customary purpose. Inputs can be read using the
@command{ftdi_get_signal} command. @command{ftdi_get_signal} command.
To support SWD, a signal named SWD_EN must be defined. It is set to 1 when the
SWD protocol is selected. When set, the adapter should route the SWDIO pin to
the data input. An SWDIO_OE signal, if defined, will be set to 1 or 0 as
required by the protocol, to tell the adapter to drive the data output onto
the SWDIO pin or keep the SWDIO pin Hi-Z, respectively.
Depending on the type of buffer attached to the FTDI GPIO, the outputs have to Depending on the type of buffer attached to the FTDI GPIO, the outputs have to
be controlled differently. In order to support tristateable signals such as be controlled differently. In order to support tristateable signals such as
nSRST, both a data GPIO and an output-enable GPIO can be specified for each nSRST, both a data GPIO and an output-enable GPIO can be specified for each
@ -2536,9 +2447,8 @@ These interfaces have several commands, used to configure the driver
before initializing the JTAG scan chain: before initializing the JTAG scan chain:
@deffn {Config Command} {ftdi_vid_pid} [vid pid]+ @deffn {Config Command} {ftdi_vid_pid} [vid pid]+
The vendor ID and product ID of the adapter. If not specified, the FTDI The vendor ID and product ID of the adapter. Up to eight
default values are used. [@var{vid}, @var{pid}] pairs may be given, e.g.
Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g.
@example @example
ftdi_vid_pid 0x0403 0xcff8 0x15ba 0x0003 ftdi_vid_pid 0x0403 0xcff8 0x15ba 0x0003
@end example @end example
@ -2721,7 +2631,7 @@ reset_config srst_only
@end example @end example
@end deffn @end deffn
@deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ftd2xx}|@option{ublast2}) @deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ublast2})
Chooses the low level access method for the adapter. If not specified, Chooses the low level access method for the adapter. If not specified,
@option{ftdi} is selected unless it wasn't enabled during the @option{ftdi} is selected unless it wasn't enabled during the
configure stage. USB-Blaster II needs @option{ublast2}. configure stage. USB-Blaster II needs @option{ublast2}.
@ -2799,6 +2709,26 @@ Reset the current configuration.
@deffn {Command} {jlink config write} @deffn {Command} {jlink config write}
Write the current configuration to the internal persistent storage. Write the current configuration to the internal persistent storage.
@end deffn @end deffn
@deffn {Command} {jlink emucom write <channel> <data>}
Write data to an EMUCOM channel. The data needs to be encoded as hexadecimal
pairs.
The following example shows how to write the three bytes 0xaa, 0x0b and 0x23 to
the EMUCOM channel 0x10:
@example
> jlink emucom write 0x10 aa0b23
@end example
@end deffn
@deffn {Command} {jlink emucom read <channel> <length>}
Read data from an EMUCOM channel. The read data is encoded as hexadecimal
pairs.
The following example shows how to read 4 bytes from the EMUCOM channel 0x0:
@example
> jlink emucom read 0x0 4
77a90000
@end example
@end deffn
@deffn {Config} {jlink usb} <@option{0} to @option{3}> @deffn {Config} {jlink usb} <@option{0} to @option{3}>
Set the USB address of the interface, in case more than one adapter is connected Set the USB address of the interface, in case more than one adapter is connected
to the host. If not specified, USB addresses are not considered. Device to the host. If not specified, USB addresses are not considered. Device
@ -2815,6 +2745,62 @@ As a configuration command, it can be used only before 'init'.
@end deffn @end deffn
@end deffn @end deffn
@deffn {Interface Driver} {kitprog}
This driver is for Cypress Semiconductor's KitProg adapters. The KitProg is an
SWD-only adapter that is designed to be used with Cypress's PSoC and PRoC device
families, but it is possible to use it with some other devices. If you are using
this adapter with a PSoC or a PRoC, you may need to add
@command{kitprog_init_acquire_psoc} or @command{kitprog acquire_psoc} to your
configuration script.
Note that this driver is for the proprietary KitProg protocol, not the CMSIS-DAP
mode introduced in firmware 2.14. If the KitProg is in CMSIS-DAP mode, it cannot
be used with this driver, and must either be used with the cmsis-dap driver or
switched back to KitProg mode. See the Cypress KitProg User Guide for
instructions on how to switch KitProg modes.
Known limitations:
@itemize @bullet
@item The frequency of SWCLK cannot be configured, and varies between 1.6 MHz
and 2.7 MHz.
@item For firmware versions below 2.14, "JTAG to SWD" sequences are replaced by
"SWD line reset" in the driver. This is for two reasons. First, the KitProg does
not support sending arbitrary SWD sequences, and only firmware 2.14 and later
implement both "JTAG to SWD" and "SWD line reset" in firmware. Earlier firmware
versions only implement "SWD line reset". Second, due to a firmware quirk, an
SWD sequence must be sent after every target reset in order to re-establish
communications with the target.
@item Due in part to the limitation above, KitProg devices with firmware below
version 2.14 will need to use @command{kitprog_init_acquire_psoc} in order to
communicate with PSoC 5LP devices. This is because, assuming debug is not
disabled on the PSoC, the PSoC 5LP needs its JTAG interface switched to SWD
mode before communication can begin, but prior to firmware 2.14, "JTAG to SWD"
could only be sent with an acquisition sequence.
@end itemize
@deffn {Config Command} {kitprog_init_acquire_psoc}
Indicate that a PSoC acquisition sequence needs to be run during adapter init.
Please be aware that the acquisition sequence hard-resets the target.
@end deffn
@deffn {Config Command} {kitprog_serial} serial
Select a KitProg device by its @var{serial}. If left unspecified, the first
device detected by OpenOCD will be used.
@end deffn
@deffn {Command} {kitprog acquire_psoc}
Run a PSoC acquisition sequence immediately. Typically, this should not be used
outside of the target-specific configuration scripts since it hard-resets the
target as a side-effect.
This is necessary for "reset halt" on some PSoC 4 series devices.
@end deffn
@deffn {Command} {kitprog info}
Display various adapter information, such as the hardware version, firmware
version, and target voltage.
@end deffn
@end deffn
@deffn {Interface Driver} {parport} @deffn {Interface Driver} {parport}
Supports PC parallel port bit-banging cables: Supports PC parallel port bit-banging cables:
Wigglers, PLD download cable, and more. Wigglers, PLD download cable, and more.
@ -3009,6 +2995,39 @@ pinout.
@end deffn @end deffn
@deffn {Interface Driver} {imx_gpio}
i.MX SoC is present in many community boards. Wandboard is an example
of the one which is most popular.
This driver is mostly the same as bcm2835gpio.
See @file{interface/imx-native.cfg} for a sample config and
pinout.
@end deffn
@deffn {Interface Driver} {openjtag}
OpenJTAG compatible USB adapter.
This defines some driver-specific commands:
@deffn {Config Command} {openjtag_variant} variant
Specifies the variant of the OpenJTAG adapter (see @uref{http://www.openjtag.org/}).
Currently valid @var{variant} values include:
@itemize @minus
@item @b{standard} Standard variant (default).
@item @b{cy7c65215} Cypress CY7C65215 Dual Channel USB-Serial Bridge Controller
(see @uref{http://www.cypress.com/?rID=82870}).
@end itemize
@end deffn
@deffn {Config Command} {openjtag_device_desc} string
The USB device description string of the adapter.
This value is only used with the standard variant.
@end deffn
@end deffn
@section Transport Configuration @section Transport Configuration
@cindex Transport @cindex Transport
As noted earlier, depending on the version of OpenOCD you use, As noted earlier, depending on the version of OpenOCD you use,
@ -4056,6 +4075,7 @@ At this writing, the supported CPU types are:
@item @code{cortex_a} -- this is an ARMv7 core with an MMU @item @code{cortex_a} -- this is an ARMv7 core with an MMU
@item @code{cortex_m} -- this is an ARMv7 core, supporting only the @item @code{cortex_m} -- this is an ARMv7 core, supporting only the
compact Thumb2 instruction set. compact Thumb2 instruction set.
@item @code{aarch64} -- this is an ARMv8-A core with an MMU
@item @code{dragonite} -- resembles arm966e @item @code{dragonite} -- resembles arm966e
@item @code{dsp563xx} -- implements Freescale's 24-bit DSP. @item @code{dsp563xx} -- implements Freescale's 24-bit DSP.
(Support for this is still incomplete.) (Support for this is still incomplete.)
@ -4088,7 +4108,7 @@ The CPU name used by OpenOCD will reflect the CPU design that was
licenced, not a vendor brand which incorporates that design. licenced, not a vendor brand which incorporates that design.
Name prefixes like arm7, arm9, arm11, and cortex Name prefixes like arm7, arm9, arm11, and cortex
reflect design generations; reflect design generations;
while names like ARMv4, ARMv5, ARMv6, and ARMv7 while names like ARMv4, ARMv5, ARMv6, ARMv7 and ARMv8
reflect an architecture version implemented by a CPU design. reflect an architecture version implemented by a CPU design.
@anchor{targetconfiguration} @anchor{targetconfiguration}
@ -4219,10 +4239,23 @@ The value should normally correspond to a static mapping for the
@anchor{rtostype} @anchor{rtostype}
@item @code{-rtos} @var{rtos_type} -- enable rtos support for target, @item @code{-rtos} @var{rtos_type} -- enable rtos support for target,
@var{rtos_type} can be one of @option{auto}|@option{eCos}|@option{ThreadX}| @var{rtos_type} can be one of @option{auto}, @option{eCos},
@option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx} @option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS},
@option{embKernel}, @option{mqx}, @option{uCOS-III}
@xref{gdbrtossupport,,RTOS Support}. @xref{gdbrtossupport,,RTOS Support}.
@item @code{-defer-examine} -- skip target examination at initial JTAG chain
scan and after a reset. A manual call to arp_examine is required to
access the target for debugging.
@item @code{-ap-num} @var{ap_number} -- set DAP access port for target,
@var{ap_number} is the numeric index of the DAP AP the target is connected to.
Use this option with systems where multiple, independent cores are connected
to separate access ports of the same DAP.
@item @code{-ctibase} @var{address} -- set base address of Cross-Trigger interface (CTI) connected
to the target. Currently, only the @code{aarch64} target makes use of this option, where it is
a mandatory configuration for the target run control.
@end itemize @end itemize
@end deffn @end deffn
@ -4259,7 +4292,7 @@ omap3530.cpu mww 0x5555 123
The commands supported by OpenOCD target objects are: The commands supported by OpenOCD target objects are:
@deffn Command {$target_name arp_examine} @deffn Command {$target_name arp_examine} @option{allow-defer}
@deffnx Command {$target_name arp_halt} @deffnx Command {$target_name arp_halt}
@deffnx Command {$target_name arp_poll} @deffnx Command {$target_name arp_poll}
@deffnx Command {$target_name arp_reset} @deffnx Command {$target_name arp_reset}
@ -4694,9 +4727,10 @@ and write the contents to the binary @file{filename}.
The @var{num} parameter is a value shown by @command{flash banks}. The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn @end deffn
@deffn Command {flash verify_bank} num filename offset @deffn Command {flash verify_bank} num filename [offset]
Compare the contents of the binary file @var{filename} with the contents of the Compare the contents of the binary file @var{filename} with the contents of the
flash @var{num} starting at @var{offset}. Fails if the contents do not match. flash bank @var{num} starting at @var{offset}. If @var{offset} is omitted,
start at the beginning of the flash bank. Fail if the contents do not match.
The @var{num} parameter is a value shown by @command{flash banks}. The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn @end deffn
@ -4757,12 +4791,15 @@ and possibly stale information.
@anchor{flashprotect} @anchor{flashprotect}
@deffn Command {flash protect} num first last (@option{on}|@option{off}) @deffn Command {flash protect} num first last (@option{on}|@option{off})
Enable (@option{on}) or disable (@option{off}) protection of flash sectors Enable (@option{on}) or disable (@option{off}) protection of flash blocks
in flash bank @var{num}, starting at sector @var{first} in flash bank @var{num}, starting at protection block @var{first}
and continuing up to and including @var{last}. and continuing up to and including @var{last}.
Providing a @var{last} sector of @option{last} Providing a @var{last} block of @option{last}
specifies "to the end of the flash bank". specifies "to the end of the flash bank".
The @var{num} parameter is a value shown by @command{flash banks}. The @var{num} parameter is a value shown by @command{flash banks}.
The protection block is usually identical to a flash sector.
Some devices may utilize a protection block distinct from flash sector.
See @command{flash info} for a list of protection blocks.
@end deffn @end deffn
@deffn Command {flash padded_value} num value @deffn Command {flash padded_value} num value
@ -4799,8 +4836,10 @@ the flash bank defined at address 0x1fc00000. Any cmds executed on
the virtual banks are actually performed on the physical banks. the virtual banks are actually performed on the physical banks.
@example @example
flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME
flash bank vbank0 virtual 0xbfc00000 0 0 0 $_TARGETNAME $_FLASHNAME flash bank vbank0 virtual 0xbfc00000 0 0 0 \
flash bank vbank1 virtual 0x9fc00000 0 0 0 $_TARGETNAME $_FLASHNAME $_TARGETNAME $_FLASHNAME
flash bank vbank1 virtual 0x9fc00000 0 0 0 \
$_TARGETNAME $_FLASHNAME
@end example @end example
@end deffn @end deffn
@ -4866,8 +4905,8 @@ Since signaling between JTAG and SPI is compatible, all that is required for
a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate
the flash chip select when the JTAG state machine is in SHIFT-DR. Such the flash chip select when the JTAG state machine is in SHIFT-DR. Such
a bitstream for several Xilinx FPGAs can be found in a bitstream for several Xilinx FPGAs can be found in
@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires migen @file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires
(@url{http://github.com/m-labs/migen}) and a Xilinx toolchain to build. @uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build.
This flash bank driver requires a target on a JTAG tap and will access that This flash bank driver requires a target on a JTAG tap and will access that
tap directly. Since no support from the target is needed, the target can be a tap directly. Since no support from the target is needed, the target can be a
@ -4890,7 +4929,8 @@ For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the
target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga
set _XILINX_USER1 0x02 set _XILINX_USER1 0x02
set _DR_LENGTH 1 set _DR_LENGTH 1
flash bank $_FLASHNAME spi 0x0 0 0 0 $_TARGETNAME $_XILINX_USER1 $_DR_LENGTH flash bank $_FLASHNAME spi 0x0 0 0 0 \
$_TARGETNAME $_XILINX_USER1 $_DR_LENGTH
@end example @end example
@end deffn @end deffn
@ -4959,6 +4999,45 @@ flash bank $_FLASHNAME mrvlqspi 0x0 0 0 0 $_TARGETNAME 0x46010000
@end deffn @end deffn
@deffn {Flash Driver} ath79
@cindex Atheros ath79 SPI driver
@cindex ath79
Members of ATH79 SoC family from Atheros include a SPI interface with 3
chip selects.
On reset a SPI flash connected to the first chip select (CS0) is made
directly read-accessible in the CPU address space (up to 16MBytes)
and is usually used to store the bootloader and operating system.
Normal OpenOCD commands like @command{mdw} can be used to display
the flash content while it is in memory-mapped mode (only the first
4MBytes are accessible without additional configuration on reset).
The setup command only requires the @var{base} parameter in order
to identify the memory bank. The actual value for the base address
is not otherwise used by the driver. However the mapping is passed
to gdb. Thus for the memory mapped flash (chipselect CS0) the base
address should be the actual memory mapped base address. For unmapped
chipselects (CS1 and CS2) care should be taken to use a base address
that does not overlap with real memory regions.
Additional information, like flash size, are detected automatically.
An optional additional parameter sets the chipselect for the bank,
with the default CS0.
CS1 and CS2 require additional GPIO setup before they can be used
since the alternate function must be enabled on the GPIO pin
CS1/CS2 is routed to on the given SoC.
@example
flash bank $_FLASHNAME ath79 0 0 0 0 $_TARGETNAME
# When using multiple chipselects the base should be different for each,
# otherwise the write_image command is not able to distinguish the
# banks.
flash bank flash0 ath79 0x00000000 0 0 0 $_TARGETNAME cs0
flash bank flash1 ath79 0x10000000 0 0 0 $_TARGETNAME cs1
flash bank flash2 ath79 0x20000000 0 0 0 $_TARGETNAME cs2
@end example
@end deffn
@subsection Internal Flash (Microcontrollers) @subsection Internal Flash (Microcontrollers)
@deffn {Flash Driver} aduc702x @deffn {Flash Driver} aduc702x
@ -4996,7 +5075,8 @@ and the second bank starts after the first.
# Flash bank 0 # Flash bank 0
flash bank $_FLASHNAME ambiqmicro 0 0x00040000 0 0 $_TARGETNAME flash bank $_FLASHNAME ambiqmicro 0 0x00040000 0 0 $_TARGETNAME
# Flash bank 1 - same size as bank0, starts after bank 0. # Flash bank 1 - same size as bank0, starts after bank 0.
flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 $_TARGETNAME flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 \
$_TARGETNAME
@end example @end example
Flash is programmed using custom entry points into the bootloader. Flash is programmed using custom entry points into the bootloader.
@ -5270,8 +5350,10 @@ with @code{x} treated as wildcard and otherwise case (and any trailing
characters) ignored. characters) ignored.
@example @example
flash bank $@{_FLASHNAME@}0 fm4 0x00000000 0 0 0 $_TARGETNAME S6E2CCAJ0A flash bank $@{_FLASHNAME@}0 fm4 0x00000000 0 0 0 \
flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 $_TARGETNAME S6E2CCAJ0A $_TARGETNAME S6E2CCAJ0A
flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 \
$_TARGETNAME S6E2CCAJ0A
@end example @end example
@emph{The current implementation is incomplete. Protection is not supported, @emph{The current implementation is incomplete. Protection is not supported,
nor is Chip Erase (only Sector Erase is implemented).} nor is Chip Erase (only Sector Erase is implemented).}
@ -6715,7 +6797,7 @@ port is 5555.
@end itemize @end itemize
@section Daemon Commands @section Server Commands
@deffn {Command} exit @deffn {Command} exit
Exits the current telnet session. Exits the current telnet session.
@ -6741,7 +6823,7 @@ Useful in connection with script files
@end deffn @end deffn
@deffn Command shutdown [@option{error}] @deffn Command shutdown [@option{error}]
Close the OpenOCD daemon, disconnecting all clients (GDB, telnet, Close the OpenOCD server, disconnecting all clients (GDB, telnet,
other). If option @option{error} is used, OpenOCD will return a other). If option @option{error} is used, OpenOCD will return a
non-zero exit code to the parent process. non-zero exit code to the parent process.
@end deffn @end deffn
@ -7077,6 +7159,13 @@ The file format may optionally be specified
This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare.
@end deffn @end deffn
@deffn Command {verify_image_checksum} filename address [@option{bin}|@option{ihex}|@option{elf}]
Verify @var{filename} against target memory starting at @var{address}.
The file format may optionally be specified
(@option{bin}, @option{ihex}, or @option{elf})
This perform a comparison using a CRC checksum only
@end deffn
@section Breakpoint and Watchpoint commands @section Breakpoint and Watchpoint commands
@cindex breakpoint @cindex breakpoint
@ -7489,6 +7578,17 @@ requests by using a special SVC instruction that is trapped at the
Supervisor Call vector by OpenOCD. Supervisor Call vector by OpenOCD.
@end deffn @end deffn
@deffn Command {arm semihosting_fileio} [@option{enable}|@option{disable}]
@cindex ARM semihosting
Display status of semihosting fileio, after optionally changing that
status.
Enabling this option forwards semihosting I/O to GDB process using the
File-I/O remote protocol extension. This is especially useful for
interacting with remote files or displaying console messages in the
debugger.
@end deffn
@section ARMv4 and ARMv5 Architecture @section ARMv4 and ARMv5 Architecture
@cindex ARMv4 @cindex ARMv4
@cindex ARMv5 @cindex ARMv5
@ -7870,13 +7970,14 @@ coprocessor 14 register 7 itself) but all current ARM11
cores @emph{except the ARM1176} use the same six bits. cores @emph{except the ARM1176} use the same six bits.
@end deffn @end deffn
@section ARMv7 Architecture @section ARMv7 and ARMv8 Architecture
@cindex ARMv7 @cindex ARMv7
@cindex ARMv8
@subsection ARMv7 Debug Access Port (DAP) specific commands @subsection ARMv7 and ARMv8 Debug Access Port (DAP) specific commands
@cindex Debug Access Port @cindex Debug Access Port
@cindex DAP @cindex DAP
These commands are specific to ARM architecture v7 Debug Access Port (DAP), These commands are specific to ARM architecture v7 and v8 Debug Access Port (DAP),
included on Cortex-M and Cortex-A systems. included on Cortex-M and Cortex-A systems.
They are available in addition to other core-specific commands that may be available. They are available in addition to other core-specific commands that may be available.
@ -8130,6 +8231,29 @@ the peripherals.
@xref{targetevents,,Target Events}. @xref{targetevents,,Target Events}.
@end deffn @end deffn
@subsection ARMv8-A specific commands
@cindex ARMv8-A
@cindex aarch64
@deffn Command {aarch64 cache_info}
Display information about target caches
@end deffn
@deffn Command {aarch64 dbginit}
This command enables debugging by clearing the OS Lock and sticky power-down and reset
indications. It also establishes the expected, basic cross-trigger configuration the aarch64
target code relies on. In a configuration file, the command would typically be called from a
@code{reset-end} or @code{reset-deassert-post} handler, to re-enable debugging after a system reset.
However, normally it is not necessary to use the command at all.
@end deffn
@deffn Command {aarch64 smp_on|smp_off}
Enable and disable SMP handling. The state of SMP handling influences the way targets in an SMP group
are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger
halting or resuming of all cores in the group. The command @code{target smp} defines which targets are in the SMP
group. With SMP handling disabled, all targets need to be treated individually.
@end deffn
@section Intel Architecture @section Intel Architecture
Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32 Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32
@ -8900,7 +9024,11 @@ end
@anchor{gdbrtossupport} @anchor{gdbrtossupport}
OpenOCD includes RTOS support, this will however need enabling as it defaults to disabled. OpenOCD includes RTOS support, this will however need enabling as it defaults to disabled.
It can be enabled by passing @option{-rtos} arg to the target @xref{rtostype,,RTOS Type}. It can be enabled by passing @option{-rtos} arg to the target. @xref{rtostype,,RTOS Type}.
@xref{Threads, Debugging Programs with Multiple Threads,
Debugging Programs with Multiple Threads, gdb, GDB manual}, for details about relevant
GDB commands.
@* An example setup is below: @* An example setup is below:
@ -8919,6 +9047,7 @@ Currently supported rtos's include:
@item @option{ChibiOS} @item @option{ChibiOS}
@item @option{embKernel} @item @option{embKernel}
@item @option{mqx} @item @option{mqx}
@item @option{uCOS-III}
@end itemize @end itemize
@quotation Note @quotation Note
@ -8952,10 +9081,12 @@ Rtos::sCurrentTask, Rtos::sListReady, Rtos::sListSleep,
Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount. Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount.
@item mqx symbols @item mqx symbols
_mqx_kernel_data, MQX_init_struct. _mqx_kernel_data, MQX_init_struct.
@item uC/OS-III symbols
OSRunning, OSTCBCurPtr, OSTaskDbgListPtr, OSTaskQty
@end table @end table
For most RTOS supported the above symbols will be exported by default. However for For most RTOS supported the above symbols will be exported by default. However for
some, eg. FreeRTOS, extra steps must be taken. some, eg. FreeRTOS and uC/OS-III, extra steps must be taken.
These RTOSes may require additional OpenOCD-specific file to be linked These RTOSes may require additional OpenOCD-specific file to be linked
along with the project: along with the project:
@ -8963,6 +9094,8 @@ along with the project:
@table @code @table @code
@item FreeRTOS @item FreeRTOS
contrib/rtos-helpers/FreeRTOS-openocd.c contrib/rtos-helpers/FreeRTOS-openocd.c
@item uC/OS-III
contrib/rtos-helpers/uCOS-III-openocd.c
@end table @end table
@node Tcl Scripting API @node Tcl Scripting API
@ -9344,16 +9477,6 @@ supply stable enough for the Amontec JTAGkey to be operated.
@b{Laptops running on battery have this problem too...} @b{Laptops running on battery have this problem too...}
@item @b{USB Power} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the
following error messages: "Error: ft2232.c:201 ft2232_read(): FT_Read returned:
4" and "Error: ft2232.c:365 ft2232_send_and_recv(): couldn't read from FT2232".
What does that mean and what might be the reason for this?
First of all, the reason might be the USB power supply. Try using a self-powered
hub instead of a direct connection to your computer. Secondly, the error code 4
corresponds to an FT_IO_ERROR, which means that the driver for the FTDI USB
chip ran into some sort of error - this points us to a USB problem.
@item @b{GDB Disconnects} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following @item @b{GDB Disconnects} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following
error message: "Error: gdb_server.c:101 gdb_get_char(): read: 10054". error message: "Error: gdb_server.c:101 gdb_get_char(): read: 10054".
What does that mean and what might be the reason for this? What does that mean and what might be the reason for this?

View File

@ -1,60 +1,41 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libopenocd.la
bin_PROGRAMS += %D%/openocd
SUBDIRS = \ %C%_openocd_SOURCES = \
jtag \ %D%/main.c
helper \
target \
transport \
flash \
svf \
xsvf \
pld \
server \
rtos
noinst_LTLIBRARIES = libopenocd.la %C%_libopenocd_la_SOURCES = \
bin_PROGRAMS = openocd %D%/hello.c %D%/hello.h \
%D%/openocd.c %D%/openocd.h
MAINFILE = main.c %C%_openocd_LDADD = %D%/libopenocd.la
openocd_SOURCES = $(MAINFILE) %C%_openocd_LDADD += $(MINGWLDADD)
openocd_LDADD = libopenocd.la
if INTERNAL_JIMTCL if INTERNAL_JIMTCL
openocd_LDADD += $(top_builddir)/jimtcl/libjim.a %C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
else else
openocd_LDADD += -ljim %C%_openocd_LDADD += -ljim
endif endif
if ULINK %C%_libopenocd_la_CPPFLAGS =
openocd_LDADD += -lm
endif
libopenocd_la_SOURCES = \
hello.c \
openocd.c
noinst_HEADERS = \
hello.h \
openocd.h
libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
# banner output includes RELSTR appended to $VERSION from the configure script # banner output includes RELSTR appended to $VERSION from the configure script
# guess-rev.sh returns either a repository version ID or "-snapshot" # guess-rev.sh returns either a repository version ID or "-snapshot"
if RELEASE if RELEASE
libopenocd_la_CPPFLAGS += -DRELSTR=\"\" %C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" %C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"\"
else else
libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" %C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" %C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\"
%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\"
endif endif
# add default CPPFLAGS # add default CPPFLAGS
libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) %C%_libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS)
# the library search path. # the library search path.
libopenocd_la_LDFLAGS = $(all_libraries) %C%_libopenocd_la_LDFLAGS = $(all_libraries)
if IS_MINGW if IS_MINGW
MINGWLDADD = -lws2_32 MINGWLDADD = -lws2_32
@ -62,55 +43,43 @@ else
MINGWLDADD = MINGWLDADD =
endif endif
libopenocd_la_LIBADD = \ %C%_libopenocd_la_LIBADD = \
$(top_builddir)/src/xsvf/libxsvf.la \ %D%/xsvf/libxsvf.la \
$(top_builddir)/src/svf/libsvf.la \ %D%/svf/libsvf.la \
$(top_builddir)/src/pld/libpld.la \ %D%/pld/libpld.la \
$(top_builddir)/src/jtag/libjtag.la \ %D%/jtag/libjtag.la \
$(top_builddir)/src/transport/libtransport.la \ %D%/transport/libtransport.la \
$(top_builddir)/src/flash/libflash.la \ %D%/flash/libflash.la \
$(top_builddir)/src/target/libtarget.la \ %D%/target/libtarget.la \
$(top_builddir)/src/server/libserver.la \ %D%/server/libserver.la \
$(top_builddir)/src/rtos/librtos.la \ %D%/rtos/librtos.la \
$(top_builddir)/src/helper/libhelper.la \ %D%/helper/libhelper.la
$(LIBFTDI_LIBS) $(MINGWLDADD) \
$(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS)
STARTUP_TCL_SRCS = \ BIN2C = $(srcdir)/%D%/helper/bin2char.sh
$(srcdir)/helper/startup.tcl \
$(srcdir)/jtag/startup.tcl \
$(srcdir)/target/startup.tcl \
$(srcdir)/flash/startup.tcl \
$(srcdir)/server/startup.tcl
EXTRA_DIST = $(STARTUP_TCL_SRCS) STARTUP_TCL_SRCS =
EXTRA_DIST += $(STARTUP_TCL_SRCS)
BUILT_SOURCES = startup_tcl.inc BUILT_SOURCES += %D%/startup_tcl.inc
startup.tcl: $(STARTUP_TCL_SRCS)
cat $^ > $@
BIN2C = $(top_srcdir)/src/helper/bin2char.sh
# Convert .tcl to c-array # Convert .tcl to c-array
startup_tcl.inc: startup.tcl $(BIN2C) %D%/startup_tcl.inc: $(STARTUP_TCL_SRCS)
$(BIN2C) < $< > $@ || { rm -f $@; false; } cat $^ | $(BIN2C) > $@ || { rm -f $@; false; }
# add generated files to make clean list # add generated files to make clean list
CLEANFILES = startup.tcl startup_tcl.inc CLEANFILES += %D%/startup_tcl.inc
# we do not want generated file in the dist # we do not want generated file in the dist
dist-hook: #dist-hook:
rm -f $(distdir)/startup_tcl.inc # rm -f $(distdir)/%D%/startup_tcl.inc
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
# The "quick" target builds executables & reinstalls the executables
# Primary use: developer types to quicken the edit/compile/debug
# cycle. by not requiring a "full build and full install". Note the
# assumption is: You are only rebuilding the EXE.... and everything
# else is/was previously installed.
#
# use at your own risk
quick: all install-binPROGRAMS
include %D%/helper/Makefile.am
include %D%/jtag/Makefile.am
include %D%/transport/Makefile.am
include %D%/xsvf/Makefile.am
include %D%/svf/Makefile.am
include %D%/target/Makefile.am
include %D%/rtos/Makefile.am
include %D%/server/Makefile.am
include %D%/flash/Makefile.am
include %D%/pld/Makefile.am

View File

@ -1,23 +1,13 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libflash.la
%C%_libflash_la_SOURCES = \
%D%/common.c %D%/common.h \
%D%/mflash.c %D%/mflash.h
SUBDIRS = \ %C%_libflash_la_LIBADD = \
nor \ %D%/nor/libocdflashnor.la \
nand %D%/nand/libocdflashnand.la
METASOURCES = AUTO STARTUP_TCL_SRCS += %D%/startup.tcl
noinst_LTLIBRARIES = libflash.la
libflash_la_SOURCES = \
common.c \
mflash.c
libflash_la_LIBADD = \ include %D%/nor/Makefile.am
$(top_builddir)/src/flash/nor/libocdflashnor.la \ include %D%/nand/Makefile.am
$(top_builddir)/src/flash/nand/libocdflashnand.la
noinst_HEADERS = \
common.h \
mflash.h
EXTRA_DIST = startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -44,5 +44,6 @@ bool flash_driver_name_matches(const char *name, const char *expected);
#define ERROR_FLASH_SECTOR_NOT_ERASED (-906) #define ERROR_FLASH_SECTOR_NOT_ERASED (-906)
#define ERROR_FLASH_BANK_NOT_PROBED (-907) #define ERROR_FLASH_BANK_NOT_PROBED (-907)
#define ERROR_FLASH_OPER_UNSUPPORTED (-908) #define ERROR_FLASH_OPER_UNSUPPORTED (-908)
#define ERROR_FLASH_PROTECTED (-909)
#endif /* OPENOCD_FLASH_COMMON_H */ #endif /* OPENOCD_FLASH_COMMON_H */

View File

@ -1,46 +1,43 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdflashnand.la
noinst_LTLIBRARIES = libocdflashnand.la %C%_libocdflashnand_la_SOURCES = \
%D%/ecc.c \
libocdflashnand_la_SOURCES = \ %D%/ecc_kw.c \
ecc.c \ %D%/core.c \
ecc_kw.c \ %D%/fileio.c \
core.c \ %D%/tcl.c \
fileio.c \ %D%/arm_io.c \
tcl.c \
arm_io.c \
$(NAND_DRIVERS) \ $(NAND_DRIVERS) \
driver.c %D%/driver.c \
$(NANDHEADERS)
NAND_DRIVERS = \ NAND_DRIVERS = \
nonce.c \ %D%/nonce.c \
davinci.c \ %D%/davinci.c \
lpc3180.c \ %D%/lpc3180.c \
lpc32xx.c \ %D%/lpc32xx.c \
mxc.c \ %D%/mxc.c \
mx3.c \ %D%/mx3.c \
orion.c \ %D%/orion.c \
s3c24xx.c \ %D%/s3c24xx.c \
s3c2410.c \ %D%/s3c2410.c \
s3c2412.c \ %D%/s3c2412.c \
s3c2440.c \ %D%/s3c2440.c \
s3c2443.c \ %D%/s3c2443.c \
s3c6400.c \ %D%/s3c6400.c \
at91sam9.c \ %D%/at91sam9.c \
nuc910.c %D%/nuc910.c
noinst_HEADERS = \ NANDHEADERS = \
arm_io.h \ %D%/arm_io.h \
core.h \ %D%/core.h \
driver.h \ %D%/driver.h \
fileio.h \ %D%/fileio.h \
imp.h \ %D%/imp.h \
lpc3180.h \ %D%/lpc3180.h \
lpc32xx.h \ %D%/lpc32xx.h \
mxc.h \ %D%/mxc.h \
mx3.h \ %D%/mx3.h \
s3c24xx.h \ %D%/s3c24xx.h \
s3c24xx_regs.h \ %D%/s3c24xx_regs.h \
nuc910.h %D%/nuc910.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -254,7 +254,8 @@ COMMAND_HANDLER(handle_nand_write_command)
int bytes_read = nand_fileio_read(nand, &s); int bytes_read = nand_fileio_read(nand, &s);
if (bytes_read <= 0) { if (bytes_read <= 0) {
command_print(CMD_CTX, "error while reading file"); command_print(CMD_CTX, "error while reading file");
return nand_fileio_cleanup(&s); nand_fileio_cleanup(&s);
return ERROR_FAIL;
} }
s.size -= bytes_read; s.size -= bytes_read;
@ -264,7 +265,8 @@ COMMAND_HANDLER(handle_nand_write_command)
command_print(CMD_CTX, "failed writing file %s " command_print(CMD_CTX, "failed writing file %s "
"to NAND flash %s at offset 0x%8.8" PRIx32, "to NAND flash %s at offset 0x%8.8" PRIx32,
CMD_ARGV[1], CMD_ARGV[0], s.address); CMD_ARGV[1], CMD_ARGV[0], s.address);
return nand_fileio_cleanup(&s); nand_fileio_cleanup(&s);
return retval;
} }
s.address += s.page_size; s.address += s.page_size;
} }

View File

@ -1,70 +1,68 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdflashnor.la
%C%_libocdflashnor_la_SOURCES = \
noinst_LTLIBRARIES = libocdflashnor.la %D%/core.c \
libocdflashnor_la_SOURCES = \ %D%/tcl.c \
core.c \
tcl.c \
$(NOR_DRIVERS) \ $(NOR_DRIVERS) \
drivers.c %D%/drivers.c \
$(NORHEADERS)
NOR_DRIVERS = \ NOR_DRIVERS = \
aduc702x.c \ %D%/aduc702x.c \
aducm360.c \ %D%/aducm360.c \
ambiqmicro.c \ %D%/ambiqmicro.c \
at91sam4.c \ %D%/at91sam4.c \
at91sam4l.c \ %D%/at91sam4l.c \
at91samd.c \ %D%/at91samd.c \
at91sam3.c \ %D%/at91sam3.c \
at91sam7.c \ %D%/at91sam7.c \
atsamv.c \ %D%/ath79.c \
avrf.c \ %D%/atsamv.c \
cfi.c \ %D%/avrf.c \
dsp5680xx_flash.c \ %D%/cfi.c \
efm32.c \ %D%/dsp5680xx_flash.c \
em357.c \ %D%/efm32.c \
fespi.c \ %D%/em357.c \
faux.c \ %D%/fespi.c \
fm3.c \ %D%/faux.c \
fm4.c \ %D%/fm3.c \
jtagspi.c \ %D%/fm4.c \
kinetis.c \ %D%/jtagspi.c \
kinetis_ke.c \ %D%/kinetis.c \
lpc2000.c \ %D%/kinetis_ke.c \
lpc288x.c \ %D%/lpc2000.c \
lpc2900.c \ %D%/lpc288x.c \
lpcspifi.c \ %D%/lpc2900.c \
mdr.c \ %D%/lpcspifi.c \
mrvlqspi.c \ %D%/mdr.c \
niietcm4.c \ %D%/mrvlqspi.c \
non_cfi.c \ %D%/niietcm4.c \
nrf51.c \ %D%/non_cfi.c \
numicro.c \ %D%/nrf51.c \
ocl.c \ %D%/numicro.c \
pic32mx.c \ %D%/ocl.c \
psoc4.c \ %D%/pic32mx.c \
sim3x.c \ %D%/psoc4.c \
spi.c \ %D%/sim3x.c \
stmsmi.c \ %D%/spi.c \
stellaris.c \ %D%/stmsmi.c \
stm32f1x.c \ %D%/stellaris.c \
stm32f2x.c \ %D%/stm32f1x.c \
stm32lx.c \ %D%/stm32f2x.c \
stm32l4x.c \ %D%/stm32lx.c \
str7x.c \ %D%/stm32l4x.c \
str9x.c \ %D%/str7x.c \
str9xpec.c \ %D%/str9x.c \
tms470.c \ %D%/str9xpec.c \
virtual.c \ %D%/tms470.c \
xmc1xxx.c \ %D%/virtual.c \
xmc4xxx.c %D%/xmc1xxx.c \
%D%/xmc4xxx.c
noinst_HEADERS = \ NORHEADERS = \
core.h \ %D%/core.h \
cfi.h \ %D%/cfi.h \
driver.h \ %D%/driver.h \
imp.h \ %D%/imp.h \
non_cfi.h \ %D%/non_cfi.h \
ocl.h \ %D%/ocl.h \
spi.h %D%/spi.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -65,8 +65,9 @@
#define REG_NAME_WIDTH (12) #define REG_NAME_WIDTH (12)
/* at91sam4s/at91sam4e series (has always one flash bank)*/ /* at91sam4s/at91sam4e/at91sam4c series (has always one flash bank)*/
#define FLASH_BANK_BASE_S 0x00400000 #define FLASH_BANK_BASE_S 0x00400000
#define FLASH_BANK_BASE_C 0x01000000
/* at91sam4sd series (two one flash banks), first bank address */ /* at91sam4sd series (two one flash banks), first bank address */
#define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
@ -75,6 +76,10 @@
/* at91sam4sd32x, second bank address */ /* at91sam4sd32x, second bank address */
#define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2)) #define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2))
/* at91sam4c32x, first and second bank address */
#define FLASH_BANK0_BASE_C32 FLASH_BANK_BASE_C
#define FLASH_BANK1_BASE_C32 (FLASH_BANK_BASE_C+(2048*1024/2))
#define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
#define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
#define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
@ -258,6 +263,188 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
/* these are used to *initialize* the "pChip->details" structure. */ /* these are used to *initialize* the "pChip->details" structure. */
static const struct sam4_chip_details all_sam4_details[] = { static const struct sam4_chip_details all_sam4_details[] = {
/* Start at91sam4c* series */
/* at91sam4c32e - LQFP144 */
{
.chipid_cidr = 0xA66D0EE0,
.name = "at91sam4c32e",
.total_flash_size = 2024 * 1024,
.total_sram_size = 256 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_C32,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_C32,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/* at91sam4c32c - LQFP100 */
{
.chipid_cidr = 0xA64D0EE0,
.name = "at91sam4c32c",
.total_flash_size = 2024 * 1024,
.total_sram_size = 256 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_C32,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_C32,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/* at91sam4c16c - LQFP100 */
{
.chipid_cidr = 0xA64C0CE0,
.name = "at91sam4c16c",
.total_flash_size = 1024 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* at91sam4c8c - LQFP100 */
{
.chipid_cidr = 0xA64C0AE0,
.name = "at91sam4c8c",
.total_flash_size = 512 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* at91sam4c4c (rev B) - LQFP100 */
{
.chipid_cidr = 0xA64C0CE5,
.name = "at91sam4c4c",
.total_flash_size = 256 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* Start at91sam4e* series */ /* Start at91sam4e* series */
/*atsam4e16e - LQFP144/LFBGA144*/ /*atsam4e16e - LQFP144/LFBGA144*/
@ -479,7 +666,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -495,7 +682,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
}, },
}, },
}, },
/*atsam4s16b - LQFP64/QFN64*/ /*atsam4s16b - LQFP64/QFN64/WLCSP64*/
{ {
.chipid_cidr = 0x289C0CE0, .chipid_cidr = 0x289C0CE0,
.name = "at91sam4s16b", .name = "at91sam4s16b",
@ -512,7 +699,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -545,7 +732,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -578,7 +765,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -611,7 +798,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 512 * 1024, .size_bytes = 512 * 1024,
.nsectors = 64, .nsectors = 64,
@ -627,7 +814,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
}, },
}, },
}, },
/*atsam4s8b - LQFP64/BGA64*/ /*atsam4s8b - LQFP64/QFN64/WLCSP64*/
{ {
.chipid_cidr = 0x289C0AE0, .chipid_cidr = 0x289C0AE0,
.name = "at91sam4s8b", .name = "at91sam4s8b",
@ -644,7 +831,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 512 * 1024, .size_bytes = 512 * 1024,
.nsectors = 64, .nsectors = 64,
@ -677,7 +864,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 512 * 1024, .size_bytes = 512 * 1024,
.nsectors = 64, .nsectors = 64,
@ -694,10 +881,10 @@ static const struct sam4_chip_details all_sam4_details[] = {
}, },
}, },
/*atsam4s4a - LQFP48/BGA48*/ /*atsam4s4c - LQFP100/BGA100*/
{ {
.chipid_cidr = 0x288b09e0, .chipid_cidr = 0x28ab09e0,
.name = "at91sam4s4a", .name = "at91sam4s4c",
.total_flash_size = 256 * 1024, .total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024, .total_sram_size = 64 * 1024,
.n_gpnvms = 2, .n_gpnvms = 2,
@ -711,7 +898,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK_BASE_S, .base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 256 * 1024, .size_bytes = 256 * 1024,
.nsectors = 32, .nsectors = 32,
@ -728,7 +915,177 @@ static const struct sam4_chip_details all_sam4_details[] = {
}, },
}, },
/*at91sam4sd32c*/ /*atsam4s4b - LQFP64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289b09e0,
.name = "at91sam4s4b",
.total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s4a - LQFP48/QFN48*/
{
.chipid_cidr = 0x288b09e0,
.name = "at91sam4s4a",
.total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2c - LQFP100/BGA100*/
{
.chipid_cidr = 0x28ab07e0,
.name = "at91sam4s2c",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2b - LQPF64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289b07e0,
.name = "at91sam4s2b",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2a - LQFP48/QFN48*/
{
.chipid_cidr = 0x288b07e0,
.name = "at91sam4s2a",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*at91sam4sd32c - LQFP100/BGA100*/
{ {
.chipid_cidr = 0x29a70ee0, .chipid_cidr = 0x29a70ee0,
.name = "at91sam4sd32c", .name = "at91sam4sd32c",
@ -746,7 +1103,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD, .base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -762,7 +1119,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 1, .bank_number = 1,
.base_address = FLASH_BANK1_BASE_2048K_SD, .base_address = FLASH_BANK1_BASE_2048K_SD,
.controller_address = 0x400e0c00, .controller_address = 0x400e0c00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 1024 * 1024, .size_bytes = 1024 * 1024,
.nsectors = 128, .nsectors = 128,
@ -772,7 +1129,51 @@ static const struct sam4_chip_details all_sam4_details[] = {
}, },
}, },
/*at91sam4sd16c*/ /*at91sam4sd32b - LQFP64/BGA64*/
{
.chipid_cidr = 0x29970ee0,
.name = "at91sam4sd32b",
.total_flash_size = 2048 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_2048K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/*at91sam4sd16c - LQFP100/BGA100*/
{ {
.chipid_cidr = 0x29a70ce0, .chipid_cidr = 0x29a70ce0,
.name = "at91sam4sd16c", .name = "at91sam4sd16c",
@ -790,7 +1191,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0, .bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD, .base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00, .controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 512 * 1024, .size_bytes = 512 * 1024,
.nsectors = 64, .nsectors = 64,
@ -806,7 +1207,51 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 1, .bank_number = 1,
.base_address = FLASH_BANK1_BASE_1024K_SD, .base_address = FLASH_BANK1_BASE_1024K_SD,
.controller_address = 0x400e0c00, .controller_address = 0x400e0c00,
.flash_wait_states = 6, /* workaround silicon bug */ .flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
},
},
/*at91sam4sd16b - LQFP64/BGA64*/
{
.chipid_cidr = 0x29970ce0,
.name = "at91sam4sd16b",
.total_flash_size = 1024 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_1024K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1, .present = 1,
.size_bytes = 512 * 1024, .size_bytes = 512 * 1024,
.nsectors = 64, .nsectors = 64,
@ -895,6 +1340,74 @@ static const struct sam4_chip_details all_sam4_details[] = {
} }
}, },
/* atsamg55g19 */
{
.chipid_cidr = 0x24470ae0,
.name = "atsamg55g19",
.total_flash_size = 512 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = */
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
}
},
/* atsamg55j19 */
{
.chipid_cidr = 0x24570ae0,
.name = "atsamg55j19",
.total_flash_size = 512 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = */
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
}
},
/* terminate */ /* terminate */
{ {
.chipid_cidr = 0, .chipid_cidr = 0,
@ -1402,7 +1915,7 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip,
static const char _unknown[] = "unknown"; static const char _unknown[] = "unknown";
static const char *const eproc_names[] = { static const char *const eproc_names[] = {
_unknown, /* 0 */ "Cortex-M7", /* 0 */
"arm946es", /* 1 */ "arm946es", /* 1 */
"arm7tdmi", /* 2 */ "arm7tdmi", /* 2 */
"Cortex-M3", /* 3 */ "Cortex-M3", /* 3 */
@ -1430,7 +1943,7 @@ static const char *const nvpsize[] = {
"64K bytes", /* 5 */ "64K bytes", /* 5 */
_unknown, /* 6 */ _unknown, /* 6 */
"128K bytes", /* 7 */ "128K bytes", /* 7 */
_unknown, /* 8 */ "160K bytes", /* 8 */
"256K bytes", /* 9 */ "256K bytes", /* 9 */
"512K bytes", /* 10 */ "512K bytes", /* 10 */
_unknown, /* 11 */ _unknown, /* 11 */
@ -1472,12 +1985,16 @@ static const struct archnames { unsigned value; const char *name; } archnames[]
{ 0x42, "AT91x42 Series" }, { 0x42, "AT91x42 Series" },
{ 0x43, "SAMG51 Series" { 0x43, "SAMG51 Series"
}, },
{ 0x44, "SAMG55 Series (49-pin WLCSP)" },
{ 0x45, "SAMG55 Series (64-pin)" },
{ 0x47, "SAMG53 Series" { 0x47, "SAMG53 Series"
}, },
{ 0x55, "AT91x55 Series" }, { 0x55, "AT91x55 Series" },
{ 0x60, "AT91SAM7Axx Series" }, { 0x60, "AT91SAM7Axx Series" },
{ 0x61, "AT91SAM7AQxx Series" }, { 0x61, "AT91SAM7AQxx Series" },
{ 0x63, "AT91x63 Series" }, { 0x63, "AT91x63 Series" },
{ 0x64, "SAM4CxxC (100-pin version)" },
{ 0x66, "SAM4CxxE (144-pin version)" },
{ 0x70, "AT91SAM7Sxx Series" }, { 0x70, "AT91SAM7Sxx Series" },
{ 0x71, "AT91SAM7XCxx Series" }, { 0x71, "AT91SAM7XCxx Series" },
{ 0x72, "AT91SAM7SExx Series" }, { 0x72, "AT91SAM7SExx Series" },
@ -1975,15 +2492,17 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
/* at91sam4s series only has bank 0*/ /* at91sam4s series only has bank 0*/
/* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/ /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
case FLASH_BANK_BASE_S: case FLASH_BANK_BASE_S:
case FLASH_BANK_BASE_C:
bank->driver_priv = &(pChip->details.bank[0]); bank->driver_priv = &(pChip->details.bank[0]);
bank->bank_number = 0; bank->bank_number = 0;
pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pChip = pChip;
pChip->details.bank[0].pBank = bank; pChip->details.bank[0].pBank = bank;
break; break;
/* Bank 1 of at91sam4sd series */ /* Bank 1 of at91sam4sd/at91sam4c32 series */
case FLASH_BANK1_BASE_1024K_SD: case FLASH_BANK1_BASE_1024K_SD:
case FLASH_BANK1_BASE_2048K_SD: case FLASH_BANK1_BASE_2048K_SD:
case FLASH_BANK1_BASE_C32:
bank->driver_priv = &(pChip->details.bank[1]); bank->driver_priv = &(pChip->details.bank[1]);
bank->bank_number = 1; bank->bank_number = 1;
pChip->details.bank[1].pChip = pChip; pChip->details.bank[1].pChip = pChip;

View File

@ -645,10 +645,15 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer,
COMMAND_HANDLER(sam4l_handle_reset_deassert) COMMAND_HANDLER(sam4l_handle_reset_deassert)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
struct armv7m_common *armv7m = target_to_armv7m(target);
int retval = ERROR_OK; int retval = ERROR_OK;
enum reset_types jtag_reset_config = jtag_get_reset_config(); enum reset_types jtag_reset_config = jtag_get_reset_config();
/* If the target has been unresponsive before, try to re-establish
* communication now - CPU is held in reset by DSU, DAP is working */
if (!target_was_examined(target))
target_examine_one(target);
target_poll(target);
/* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
* so we just release reset held by SMAP * so we just release reset held by SMAP
* *
@ -657,14 +662,14 @@ COMMAND_HANDLER(sam4l_handle_reset_deassert)
* After vectreset SMAP release is not needed however makes no harm * After vectreset SMAP release is not needed however makes no harm
*/ */
if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
if (retval == ERROR_OK) if (retval == ERROR_OK)
retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, retval = target_write_u32(target, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
/* do not return on error here, releasing SMAP reset is more important */ /* do not return on error here, releasing SMAP reset is more important */
} }
int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR); int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR);
if (retval2 != ERROR_OK) if (retval2 != ERROR_OK)
return retval2; return retval2;

View File

@ -661,7 +661,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
retval = target_blank_check_memory(target, retval = target_blank_check_memory(target,
bank->base + bank->sectors[nSector].offset, bank->base + bank->sectors[nSector].offset,
bank->sectors[nSector].size, bank->sectors[nSector].size,
&blank); &blank, bank->erased_value);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
fast_check = 0; fast_check = 0;
break; break;

View File

@ -36,6 +36,7 @@
#define SAMD_DSU_STATUSA 1 /* DSU status register */ #define SAMD_DSU_STATUSA 1 /* DSU status register */
#define SAMD_DSU_DID 0x18 /* Device ID register */ #define SAMD_DSU_DID 0x18 /* Device ID register */
#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */ #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */ #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
@ -423,39 +424,43 @@ static int samd_probe(struct flash_bank *bank)
return ERROR_OK; return ERROR_OK;
} }
static bool samd_check_error(struct target *target) static int samd_check_error(struct target *target)
{ {
int ret; int ret, ret2;
bool error;
uint16_t status; uint16_t status;
ret = target_read_u16(target, ret = target_read_u16(target,
SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status); SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Can't read NVM status"); LOG_ERROR("Can't read NVM status");
return true; return ret;
} }
if (status & 0x001C) { if ((status & 0x001C) == 0)
if (status & (1 << 4)) /* NVME */ return ERROR_OK;
LOG_ERROR("SAMD: NVM Error");
if (status & (1 << 3)) /* LOCKE */
LOG_ERROR("SAMD: NVM lock error");
if (status & (1 << 2)) /* PROGE */
LOG_ERROR("SAMD: NVM programming error");
error = true; if (status & (1 << 4)) { /* NVME */
} else { LOG_ERROR("SAMD: NVM Error");
error = false; ret = ERROR_FLASH_OPERATION_FAILED;
}
if (status & (1 << 3)) { /* LOCKE */
LOG_ERROR("SAMD: NVM lock error");
ret = ERROR_FLASH_PROTECTED;
}
if (status & (1 << 2)) { /* PROGE */
LOG_ERROR("SAMD: NVM programming error");
ret = ERROR_FLASH_OPER_UNSUPPORTED;
} }
/* Clear the error conditions by writing a one to them */ /* Clear the error conditions by writing a one to them */
ret = target_write_u16(target, ret2 = target_write_u16(target,
SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status); SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
if (ret != ERROR_OK) if (ret2 != ERROR_OK)
LOG_ERROR("Can't clear NVM error conditions"); LOG_ERROR("Can't clear NVM error conditions");
return error; return ret;
} }
static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
@ -474,10 +479,7 @@ static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
return res; return res;
/* Check to see if the NVM command resulted in an error condition. */ /* Check to see if the NVM command resulted in an error condition. */
if (samd_check_error(target)) return samd_check_error(target);
return ERROR_FAIL;
return ERROR_OK;
} }
static int samd_erase_row(struct target *target, uint32_t address) static int samd_erase_row(struct target *target, uint32_t address)
@ -531,12 +533,19 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
uint8_t startb, uint8_t endb) uint8_t startb, uint8_t endb)
{ {
int res; int res;
uint32_t nvm_ctrlb;
bool manual_wp = true;
if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) { if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) {
LOG_ERROR("Can't modify bits in the requested range"); LOG_ERROR("Can't modify bits in the requested range");
return ERROR_FAIL; return ERROR_FAIL;
} }
/* Check if we need to do manual page write commands */
res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb);
if (res == ERROR_OK)
manual_wp = (nvm_ctrlb & SAMD_NVM_CTRLB_MANW) != 0;
/* Retrieve the MCU's page size, in bytes. This is also the size of the /* Retrieve the MCU's page size, in bytes. This is also the size of the
* entire User Row. */ * entire User Row. */
uint32_t page_size; uint32_t page_size;
@ -559,8 +568,8 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
if (!buf) if (!buf)
return ERROR_FAIL; return ERROR_FAIL;
/* Read the user row (comprising one page) by half-words. */ /* Read the user row (comprising one page) by words. */
res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf); res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
if (res != ERROR_OK) if (res != ERROR_OK)
goto out_user_row; goto out_user_row;
@ -579,20 +588,18 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
/* Modify */ /* Modify */
buf_set_u32(buf, startb, endb - startb + 1, value); buf_set_u32(buf, startb, endb - startb + 1, value);
/* Write the page buffer back out to the target. A Flash write will be /* Write the page buffer back out to the target. */
* triggered automatically. */
res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
if (res != ERROR_OK) if (res != ERROR_OK)
goto out_user_row; goto out_user_row;
if (samd_check_error(target)) { if (manual_wp) {
res = ERROR_FAIL; /* Trigger flash write */
goto out_user_row; res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_WAP);
} else {
res = samd_check_error(target);
} }
/* Success */
res = ERROR_OK;
out_user_row: out_user_row:
free(buf); free(buf);
@ -784,18 +791,15 @@ static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
* then issue CMD_WP always */ * then issue CMD_WP always */
if (manual_wp || pg_offset + 4 * nw < chip->page_size) { if (manual_wp || pg_offset + 4 * nw < chip->page_size) {
res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP); res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP);
if (res != ERROR_OK) { } else {
LOG_ERROR("%s: %d", __func__, __LINE__);
goto free_pb;
}
}
/* Access through AHB is stalled while flash is being programmed */ /* Access through AHB is stalled while flash is being programmed */
usleep(200); usleep(200);
if (samd_check_error(bank->target)) { res = samd_check_error(bank->target);
}
if (res != ERROR_OK) {
LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address); LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
res = ERROR_FAIL;
goto free_pb; goto free_pb;
} }
@ -856,18 +860,23 @@ COMMAND_HANDLER(samd_handle_info_command)
COMMAND_HANDLER(samd_handle_chip_erase_command) COMMAND_HANDLER(samd_handle_chip_erase_command)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
int res = ERROR_FAIL;
if (target) { if (target) {
/* Enable access to the DSU by disabling the write protect bit */ /* Enable access to the DSU by disabling the write protect bit */
target_write_u32(target, SAMD_PAC1, (1<<1)); target_write_u32(target, SAMD_PAC1, (1<<1));
/* intentionally without error checking - not accessible on secured chip */
/* Tell the DSU to perform a full chip erase. It takes about 240ms to /* Tell the DSU to perform a full chip erase. It takes about 240ms to
* perform the erase. */ * perform the erase. */
target_write_u8(target, SAMD_DSU, (1<<4)); res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
if (res == ERROR_OK)
command_print(CMD_CTX, "chip erased"); command_print(CMD_CTX, "chip erase started");
else
command_print(CMD_CTX, "write to DSU CTRL failed");
} }
return ERROR_OK; return res;
} }
COMMAND_HANDLER(samd_handle_set_security_command) COMMAND_HANDLER(samd_handle_set_security_command)
@ -1018,10 +1027,15 @@ COMMAND_HANDLER(samd_handle_bootloader_command)
COMMAND_HANDLER(samd_handle_reset_deassert) COMMAND_HANDLER(samd_handle_reset_deassert)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
struct armv7m_common *armv7m = target_to_armv7m(target);
int retval = ERROR_OK; int retval = ERROR_OK;
enum reset_types jtag_reset_config = jtag_get_reset_config(); enum reset_types jtag_reset_config = jtag_get_reset_config();
/* If the target has been unresponsive before, try to re-establish
* communication now - CPU is held in reset by DSU, DAP is working */
if (!target_was_examined(target))
target_examine_one(target);
target_poll(target);
/* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
* so we just release reset held by DSU * so we just release reset held by DSU
* *
@ -1030,9 +1044,9 @@ COMMAND_HANDLER(samd_handle_reset_deassert)
* After vectreset DSU release is not needed however makes no harm * After vectreset DSU release is not needed however makes no harm
*/ */
if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
if (retval == ERROR_OK) if (retval == ERROR_OK)
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, retval = target_write_u32(target, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
/* do not return on error here, releasing DSU reset is more important */ /* do not return on error here, releasing DSU reset is more important */
} }

901
src/flash/nor/ath79.c Normal file
View File

@ -0,0 +1,901 @@
/***************************************************************************
* Copyright (C) 2015 by Tobias Diedrich *
* <ranma+openwrt@tdiedrich.de> *
* *
* based on the stmsmi code written by Antonio Borneo *
* <borneo.antonio@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc. *
* *
***************************************************************************/
/*
* Driver for the Atheros AR7xxx/AR9xxx SPI flash interface.
*
* Since no SPI mode register is present, presumably only
* SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
*
* The SPI interface supports up to 3 chip selects, however the SPI flash
* used for booting the system must be connected to CS0.
*
* On boot, the first 4MiB of flash space are memory-mapped into the
* area bf000000 - bfffffff (4 copies), so the MIPS bootstrap
* vector bfc00000 is mapped to the beginning of the flash.
*
* By writing a 1 to the REMAP_DISABLE bit in the SPI_CONTROL register,
* the full area of 16MiB is mapped.
*
* By writing a 0 to the SPI_FUNCTION_SELECT register (write-only dword
* register @bf000000), memory mapping is disabled and the SPI registers
* are exposed to the CPU instead:
* bf000000 SPI_FUNCTION_SELECT
* bf000004 SPI_CONTROL
* bf000008 SPI_IO_CONTROL
* bf00000c SPI_READ_DATA
*
* When not memory-mapped, the SPI interface is essentially bitbanged
* using SPI_CONTROL and SPI_IO_CONTROL with the only hardware-assistance
* being the 32bit read-only shift-register SPI_READ_DATA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "spi.h"
#include <jtag/jtag.h>
#include <helper/time_support.h>
#include <helper/types.h>
#include <target/mips32.h>
#include <target/mips32_pracc.h>
#include <target/target.h>
#define BITS_PER_BYTE 8
#define ATH79_REG_FS 0
#define ATH79_REG_CLOCK 4
#define ATH79_REG_WRITE 8
#define ATH79_REG_DATA 12
#define ATH79_SPI_CS_ALLHI 0x70000
#define ATH79_SPI_CS0_HI 0x10000
#define ATH79_SPI_CS1_HI 0x20000
#define ATH79_SPI_CS2_HI 0x40000
#define ATH79_SPI_CE_HI 0x00100
#define ATH79_SPI_DO_HI 0x00001
#define ATH79_XFER_FINAL 0x00000001
#define ATH79_XFER_PARTIAL 0x00000000
/* Timeout in ms */
#define ATH79_MAX_TIMEOUT (3000)
struct ath79_spi_ctx {
uint8_t *page_buf;
int pre_deselect;
int post_deselect;
};
struct ath79_flash_bank {
int probed;
int chipselect;
uint32_t io_base;
const struct flash_device *dev;
struct ath79_spi_ctx spi;
};
struct ath79_target {
char *name;
uint32_t tap_idcode;
uint32_t io_base;
};
static const struct ath79_target target_devices[] = {
/* name, tap_idcode, io_base */
{ "ATH79", 0x00000001, 0xbf000000 },
{ NULL, 0, 0 }
};
static const uint32_t ath79_chipselects[] = {
(~ATH79_SPI_CS0_HI & ATH79_SPI_CS_ALLHI),
(~ATH79_SPI_CS1_HI & ATH79_SPI_CS_ALLHI),
(~ATH79_SPI_CS2_HI & ATH79_SPI_CS_ALLHI),
};
static void ath79_pracc_addn(struct pracc_queue_info *ctx,
const uint32_t *instr,
int n)
{
for (int i = 0; i < n; i++)
pracc_add(ctx, 0, instr[i]);
}
static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info,
struct pracc_queue_info *ctx,
uint8_t *data, int len,
int partial_xfer)
{
uint32_t cs_high = ATH79_SPI_CS_ALLHI;
uint32_t cs_low = ath79_chipselects[ath79_info->chipselect];
uint32_t clock_high = cs_low | ATH79_SPI_CE_HI;
uint32_t clock_low = cs_low;
uint32_t pracc_out = 0;
uint32_t io_base = ath79_info->io_base;
const uint32_t preamble1[] = {
/* $15 = MIPS32_PRACC_BASE_ADDR */
MIPS32_LUI(0, 15, PRACC_UPPER_BASE_ADDR),
/* $1 = io_base */
MIPS32_LUI(0, 1, UPPER16(io_base)),
};
ath79_pracc_addn(ctx, preamble1, ARRAY_SIZE(preamble1));
if (ath79_info->spi.pre_deselect) {
/* Clear deselect flag so we don't deselect again if
* this is a partial xfer.
*/
ath79_info->spi.pre_deselect = 0;
const uint32_t pre_deselect[] = {
/* [$1 + FS] = 1 (enable flash io register access) */
MIPS32_LUI(0, 2, UPPER16(1)),
MIPS32_ORI(0, 2, 2, LOWER16(1)),
MIPS32_SW(0, 2, ATH79_REG_FS, 1),
/* deselect flash just in case */
/* $2 = SPI_CS_DIS */
MIPS32_LUI(0, 2, UPPER16(cs_high)),
MIPS32_ORI(0, 2, 2, LOWER16(cs_high)),
/* [$1 + WRITE] = $2 */
MIPS32_SW(0, 2, ATH79_REG_WRITE, 1),
};
ath79_pracc_addn(ctx, pre_deselect, ARRAY_SIZE(pre_deselect));
}
const uint32_t preamble2[] = {
/* t0 = CLOCK_LOW + 0-bit */
MIPS32_LUI(0, 8, UPPER16((clock_low + 0))),
MIPS32_ORI(0, 8, 8, LOWER16((clock_low + 0))),
/* t1 = CLOCK_LOW + 1-bit */
MIPS32_LUI(0, 9, UPPER16((clock_low + 1))),
MIPS32_ORI(0, 9, 9, LOWER16((clock_low + 1))),
/* t2 = CLOCK_HIGH + 0-bit */
MIPS32_LUI(0, 10, UPPER16((clock_high + 0))),
MIPS32_ORI(0, 10, 10, LOWER16((clock_high + 0))),
/* t3 = CLOCK_HIGH + 1-bit */
MIPS32_LUI(0, 11, UPPER16((clock_high + 1))),
MIPS32_ORI(0, 11, 11, LOWER16((clock_high + 1))),
};
ath79_pracc_addn(ctx, preamble2, ARRAY_SIZE(preamble2));
for (int i = 0; i < len; i++) {
uint8_t x = data[i];
/* Generate bitbang code for one byte, highest bit first .*/
for (int j = BITS_PER_BYTE - 1; j >= 0; j--) {
int bit = ((x >> j) & 1);
if (bit) {
/* [$1 + WRITE] = t1 */
pracc_add(ctx, 0,
MIPS32_SW(0, 9, ATH79_REG_WRITE, 1));
/* [$1 + WRITE] = t3 */
pracc_add(ctx, 0,
MIPS32_SW(0, 11, ATH79_REG_WRITE, 1));
} else {
/* [$1 + WRITE] = t0 */
pracc_add(ctx, 0,
MIPS32_SW(0, 8, ATH79_REG_WRITE, 1));
/* [$1 + WRITE] = t2 */
pracc_add(ctx, 0,
MIPS32_SW(0, 10, ATH79_REG_WRITE, 1));
}
}
if (i % 4 == 3) {
/* $3 = [$1 + DATA] */
pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1));
/* [OUTi] = $3 */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out,
MIPS32_SW(0, 3, PRACC_OUT_OFFSET +
pracc_out, 15));
pracc_out += 4;
}
}
if (len & 3) { /* not a multiple of 4 bytes */
/* $3 = [$1 + DATA] */
pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1));
/* [OUTi] = $3 */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out,
MIPS32_SW(0, 3, PRACC_OUT_OFFSET + pracc_out, 15));
pracc_out += 4;
}
if (ath79_info->spi.post_deselect && !partial_xfer) {
const uint32_t post_deselect[] = {
/* $2 = SPI_CS_DIS */
MIPS32_LUI(0, 2, UPPER16(cs_high)),
MIPS32_ORI(0, 2, 2, LOWER16(cs_high)),
/* [$1 + WRITE] = $2 */
MIPS32_SW(0, 2, ATH79_REG_WRITE, 1),
/* [$1 + FS] = 0 (disable flash io register access) */
MIPS32_XORI(0, 2, 2, 0),
MIPS32_SW(0, 2, ATH79_REG_FS, 1),
};
ath79_pracc_addn(ctx, post_deselect, ARRAY_SIZE(post_deselect));
}
/* common pracc epilogue */
/* jump to start */
pracc_add(ctx, 0, MIPS32_B(0, NEG16(ctx->code_count + 1)));
/* restore $15 from DeSave */
pracc_add(ctx, 0, MIPS32_MFC0(0, 15, 31, 0));
return pracc_out / 4;
}
static int ath79_spi_bitbang_chunk(struct flash_bank *bank,
uint8_t *data, int len, int *transferred)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
int pracc_words;
/*
* These constants must match the worst case in the above code
* generator function ath79_spi_bitbang_codegen.
*/
const int pracc_pre_post = 26;
const int pracc_loop_byte = 8 * 2 + 2;
struct pracc_queue_info ctx = {
.ejtag_info = ejtag_info
};
int max_len = (PRACC_MAX_INSTRUCTIONS - pracc_pre_post) / pracc_loop_byte;
int to_xfer = len > max_len ? max_len : len;
int partial_xfer = len != to_xfer;
int padded_len = (to_xfer + 3) & ~3;
uint32_t *out = malloc(padded_len);
if (!out) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
*transferred = 0;
pracc_queue_init(&ctx);
LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)",
target, ath79_info->io_base, data, len);
LOG_DEBUG("max code %d => max len %d. to_xfer %d",
PRACC_MAX_INSTRUCTIONS, max_len, to_xfer);
pracc_words = ath79_spi_bitbang_codegen(
ath79_info, &ctx, data, to_xfer, partial_xfer);
LOG_DEBUG("Assembled %d instructions, %d stores",
ctx.code_count, ctx.store_count);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out, 1);
if (ctx.retval != ERROR_OK)
goto exit;
if (to_xfer & 3) { /* Not a multiple of 4 bytes. */
/*
* Need to realign last word since we didn't shift the
* full 32 bits.
*/
int missed_bytes = 4 - (to_xfer & 3);
out[pracc_words - 1] <<= BITS_PER_BYTE * missed_bytes;
}
/*
* pracc reads return uint32_t in host endianness, convert to
* target endianness.
* Since we know the ATH79 target is big endian and the SPI
* shift register has the bytes in highest to lowest bit order,
* this will ensure correct memory byte order regardless of host
* endianness.
*/
target_buffer_set_u32_array(target, (uint8_t *)out, pracc_words, out);
if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
for (int i = 0; i < to_xfer; i++) {
LOG_DEBUG("bitbang %02x => %02x",
data[i], ((uint8_t *)out)[i]);
}
}
memcpy(data, out, to_xfer);
*transferred = to_xfer;
exit:
pracc_queue_free(&ctx);
free(out);
return ctx.retval;
}
static void ath79_spi_bitbang_prepare(struct flash_bank *bank)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
ath79_info->spi.pre_deselect = 1;
}
static int ath79_spi_bitbang_bytes(struct flash_bank *bank,
uint8_t *data, int len, uint32_t flags)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
int retval;
int transferred;
ath79_info->spi.post_deselect = !!(flags & ATH79_XFER_FINAL);
do {
transferred = 0;
retval = ath79_spi_bitbang_chunk(
bank, data, len, &transferred);
if (retval != ERROR_OK)
return retval;
data += transferred;
len -= transferred;
} while (len > 0);
return ERROR_OK;
}
FLASH_BANK_COMMAND_HANDLER(ath79_flash_bank_command)
{
struct ath79_flash_bank *ath79_info;
int chipselect = 0;
LOG_DEBUG("%s", __func__);
if (CMD_ARGC < 6 || CMD_ARGC > 7)
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 7) {
if (strcmp(CMD_ARGV[6], "cs0") == 0)
chipselect = 0; /* default */
else if (strcmp(CMD_ARGV[6], "cs1") == 0)
chipselect = 1;
else if (strcmp(CMD_ARGV[6], "cs2") == 0)
chipselect = 2;
else {
LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
}
ath79_info = calloc(1, sizeof(struct ath79_flash_bank));
if (!ath79_info) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
ath79_info->chipselect = chipselect;
bank->driver_priv = ath79_info;
return ERROR_OK;
}
/* Read the status register of the external SPI flash chip. */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
uint8_t spi_bytes[] = {SPIFLASH_READ_STATUS, 0};
int retval;
/* Send SPI command "read STATUS" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
*status = spi_bytes[1];
return retval;
}
/* check for WIP (write in progress) bit in status register */
/* timeout in ms */
static int wait_till_ready(struct flash_bank *bank, int timeout)
{
uint32_t status;
int retval;
long long endtime;
endtime = timeval_ms() + timeout;
do {
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;
if ((status & SPIFLASH_BSY_BIT) == 0)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
LOG_ERROR("timeout");
return ERROR_FAIL;
}
/* Send "write enable" command to SPI flash chip. */
static int ath79_write_enable(struct flash_bank *bank)
{
uint32_t status;
int retval;
uint8_t spi_bytes[] = {SPIFLASH_WRITE_ENABLE};
/* Send SPI command "write enable" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
if (retval != ERROR_OK)
return retval;
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;
/* Check write enabled */
if ((status & SPIFLASH_WE_BIT) == 0) {
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32,
status);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int erase_command(struct flash_bank *bank, int sector)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
uint32_t offset = bank->sectors[sector].offset;
uint8_t spi_bytes[] = {
ath79_info->dev->erase_cmd,
offset >> 16,
offset >> 8,
offset
};
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
return ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
}
static int ath79_erase_sector(struct flash_bank *bank, int sector)
{
int retval = ath79_write_enable(bank);
if (retval != ERROR_OK)
return retval;
/* send SPI command "block erase" */
retval = erase_command(bank, sector);
if (retval != ERROR_OK)
return retval;
/* poll WIP for end of self timed Sector Erase cycle */
return wait_till_ready(bank, ATH79_MAX_TIMEOUT);
}
static int ath79_erase(struct flash_bank *bank, int first, int last)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
int retval = ERROR_OK;
int sector;
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID;
}
if (!ath79_info->probed) {
LOG_ERROR("Flash bank not probed");
return ERROR_FLASH_BANK_NOT_PROBED;
}
for (sector = first; sector <= last; sector++) {
if (bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
for (sector = first; sector <= last; sector++) {
retval = ath79_erase_sector(bank, sector);
if (retval != ERROR_OK)
break;
keep_alive();
}
return retval;
}
static int ath79_protect(struct flash_bank *bank, int set,
int first, int last)
{
int sector;
for (sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
uint32_t address, uint32_t len)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
uint8_t spi_bytes[] = {
SPIFLASH_PAGE_PROGRAM,
address >> 16,
address >> 8,
address,
};
int retval;
uint32_t i;
if (address & 0xff) {
LOG_ERROR("ath79_write_page: unaligned write address: %08x",
address);
return ERROR_FAIL;
}
if (!ath79_info->spi.page_buf) {
LOG_ERROR("ath79_write_page: page buffer not initialized");
return ERROR_FAIL;
}
if (len > ath79_info->dev->pagesize) {
LOG_ERROR("ath79_write_page: len bigger than page size %d: %d",
ath79_info->dev->pagesize, len);
return ERROR_FAIL;
}
for (i = 0; i < len; i++) {
if (buffer[i] != 0xff)
break;
}
if (i == len) /* all 0xff, no need to program. */
return ERROR_OK;
LOG_INFO("writing %d bytes to flash page @0x%08x", len, address);
memcpy(ath79_info->spi.page_buf, buffer, len);
/* unlock writes */
retval = ath79_write_enable(bank);
if (retval != ERROR_OK)
return retval;
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_PARTIAL);
if (retval != ERROR_OK)
return retval;
/* write data */
return ath79_spi_bitbang_bytes(
bank, ath79_info->spi.page_buf, len,
ATH79_XFER_FINAL);
}
static int ath79_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
uint32_t address, uint32_t len)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
const uint32_t page_size = ath79_info->dev->pagesize;
int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__func__, address, len);
while (len > 0) {
int page_len = len > page_size ? page_size : len;
retval = ath79_write_page(
bank, buffer, address, page_len);
if (retval != ERROR_OK)
return retval;
buffer += page_size;
address += page_size;
len -= page_len;
}
return ERROR_OK;
}
static int ath79_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
int sector;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
count = bank->size - offset;
}
/* Check sector protection */
for (sector = 0; sector < bank->num_sectors; sector++) {
/* Start offset in or before this sector? */
/* End offset in or behind this sector? */
struct flash_sector *bs = &bank->sectors[sector];
if ((offset < (bs->offset + bs->size)) &&
((offset + count - 1) >= bs->offset) &&
bs->is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
return ath79_write_buffer(bank, buffer, offset, count);
}
static int ath79_read_buffer(struct flash_bank *bank, uint8_t *buffer,
uint32_t address, uint32_t len)
{
uint8_t spi_bytes[] = {
SPIFLASH_READ,
address >> 16,
address >> 8,
address,
};
int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__func__, address, len);
if (address & 0xff) {
LOG_ERROR("ath79_read_buffer: unaligned read address: %08x",
address);
return ERROR_FAIL;
}
LOG_INFO("reading %d bytes from flash @0x%08x", len, address);
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_PARTIAL);
if (retval != ERROR_OK)
return retval;
/* read data */
return ath79_spi_bitbang_bytes(
bank, buffer, len, ATH79_XFER_FINAL);
}
static int ath79_read(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Reads past end of flash. Extra data discarded.");
count = bank->size - offset;
}
return ath79_read_buffer(bank, buffer, offset, count);
}
/* Return ID of flash device */
static int read_flash_id(struct flash_bank *bank, uint32_t *id)
{
struct target *target = bank->target;
int retval;
uint8_t spi_bytes[] = {SPIFLASH_READ_ID, 0, 0, 0};
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* Send SPI command "read ID" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_FINAL);
if (retval != ERROR_OK)
return retval;
*id = (spi_bytes[1] << 0)
| (spi_bytes[2] << 8)
| (spi_bytes[3] << 16);
if (*id == 0xffffff) {
LOG_ERROR("No SPI flash found");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int ath79_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
const struct ath79_target *target_device;
int retval;
if (ath79_info->probed) {
free(bank->sectors);
free(ath79_info->spi.page_buf);
}
ath79_info->probed = 0;
for (target_device = target_devices; target_device->name;
++target_device)
if (target_device->tap_idcode == target->tap->idcode)
break;
if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known",
target->tap->idcode);
return ERROR_FAIL;
}
ath79_info->io_base = target_device->io_base;
LOG_DEBUG("Found device %s at address 0x%" PRIx32,
target_device->name, bank->base);
retval = read_flash_id(bank, &id);
if (retval != ERROR_OK)
return retval;
ath79_info->dev = NULL;
for (const struct flash_device *p = flash_devices; p->name; p++)
if (p->device_id == id) {
ath79_info->dev = p;
break;
}
if (!ath79_info->dev) {
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
return ERROR_FAIL;
}
LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
ath79_info->dev->name, ath79_info->dev->device_id);
/* Set correct size value */
bank->size = ath79_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
ath79_info->dev->size_in_bytes / ath79_info->dev->sectorsize;
sectors = calloc(1, sizeof(struct flash_sector) * bank->num_sectors);
if (!sectors) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
ath79_info->spi.page_buf = malloc(ath79_info->dev->pagesize);
if (!ath79_info->spi.page_buf) {
LOG_ERROR("not enough memory");
free(sectors);
return ERROR_FAIL;
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * ath79_info->dev->sectorsize;
sectors[sector].size = ath79_info->dev->sectorsize;
sectors[sector].is_erased = 0;
sectors[sector].is_protected = 1;
}
bank->sectors = sectors;
ath79_info->probed = 1;
return ERROR_OK;
}
static int ath79_auto_probe(struct flash_bank *bank)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
if (ath79_info->probed)
return ERROR_OK;
return ath79_probe(bank);
}
static int ath79_flash_blank_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int ath79_protect_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int get_ath79_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
if (!ath79_info->probed) {
snprintf(buf, buf_size,
"\nATH79 flash bank not probed yet\n");
return ERROR_OK;
}
snprintf(buf, buf_size, "\nATH79 flash information:\n"
" Device \'%s\' (ID 0x%08" PRIx32 ")\n",
ath79_info->dev->name, ath79_info->dev->device_id);
return ERROR_OK;
}
struct flash_driver ath79_flash = {
.name = "ath79",
.flash_bank_command = ath79_flash_bank_command,
.erase = ath79_erase,
.protect = ath79_protect,
.write = ath79_write,
.read = ath79_read,
.probe = ath79_probe,
.auto_probe = ath79_auto_probe,
.erase_check = ath79_flash_blank_check,
.protect_check = ath79_protect_check,
.info = get_ath79_info,
};

View File

@ -363,6 +363,9 @@ static int samv_probe(struct flash_bank *bank)
uint8_t nvm_size_code = (device_id >> 8) & 0xf; uint8_t nvm_size_code = (device_id >> 8) & 0xf;
switch (nvm_size_code) { switch (nvm_size_code) {
case 10:
bank->size = 512 * 1024;
break;
case 12: case 12:
bank->size = 1024 * 1024; bank->size = 1024 * 1024;
break; break;

View File

@ -66,6 +66,7 @@ static const struct avrf_type avft_chips_info[] = {
* eeprom_page_size, eeprom_page_num * eeprom_page_size, eeprom_page_num
*/ */
{"atmega128", 0x9702, 256, 512, 8, 512}, {"atmega128", 0x9702, 256, 512, 8, 512},
{"atmega128rfa1", 0xa701, 128, 512, 8, 512},
{"at90can128", 0x9781, 256, 512, 8, 512}, {"at90can128", 0x9781, 256, 512, 8, 512},
{"at90usb128", 0x9782, 256, 512, 8, 512}, {"at90usb128", 0x9782, 256, 512, 8, 512},
{"atmega164p", 0x940a, 128, 128, 4, 128}, {"atmega164p", 0x940a, 128, 128, 4, 128},

View File

@ -1312,7 +1312,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer,
busy_pattern_val = cfi_command_val(bank, 0x80); busy_pattern_val = cfi_command_val(bank, 0x80);
error_pattern_val = cfi_command_val(bank, 0x7e); error_pattern_val = cfi_command_val(bank, 0x7e);
LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, LOG_DEBUG("Using target buffer at " TARGET_ADDR_FMT " and of size 0x%04" PRIx32,
source->address, buffer_size); source->address, buffer_size);
/* Programming main loop */ /* Programming main loop */
@ -1424,50 +1424,50 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t
static const uint32_t mips_word_16_code[] = { static const uint32_t mips_word_16_code[] = {
/* start: */ /* start: */
MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ MIPS32_LHU(0, 9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */
MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ MIPS32_ADDI(0, 4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */
MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ MIPS32_SH(0, 13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */
MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ MIPS32_SH(0, 15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */
MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ MIPS32_SH(0, 7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */
MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ MIPS32_SH(0, 9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
/* busy: */ /* busy: */
MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_BNE(0, 11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ MIPS32_SRL(0, 10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */
MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ MIPS32_AND(0, 11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */
MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ MIPS32_BNE(0, 11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_BNE(0, 11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ MIPS32_XOR(0, 9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */
MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ MIPS32_BEQ(0, 9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
/* cont: */ /* cont: */
MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ MIPS32_ADDI(0, 6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */
MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ MIPS32_BNE(0, 6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
MIPS32_LUI(9, 0), /* lui $t1, 0 */ MIPS32_LUI(0, 9, 0), /* lui $t1, 0 */
MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ MIPS32_ORI(0, 9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */
MIPS32_B(4), /* b done ; goto done */ MIPS32_B(0, 4), /* b done ; goto done */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
/* cont2: */ /* cont2: */
MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ MIPS32_ADDI(0, 5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */
MIPS32_B(NEG16(33)), /* b start ; goto start */ MIPS32_B(0, NEG16(33)), /* b start ; goto start */
MIPS32_NOP, /* nop */ MIPS32_NOP, /* nop */
/* done: */ /* done: */
MIPS32_SDBBP, /* sdbbp ; break(); */ MIPS32_SDBBP(0), /* sdbbp ; break(); */
}; };
mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.common_magic = MIPS32_COMMON_MAGIC;

View File

@ -50,10 +50,17 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)
int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
{ {
int retval; int retval;
int num_blocks;
if (bank->num_prot_blocks)
num_blocks = bank->num_prot_blocks;
else
num_blocks = bank->num_sectors;
/* callers may not supply illegal parameters ... */ /* callers may not supply illegal parameters ... */
if (first < 0 || first > last || last >= bank->num_sectors) { if (first < 0 || first > last || last >= num_blocks) {
LOG_ERROR("illegal sector range"); LOG_ERROR("illegal protection block range");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -69,11 +76,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
* the target could have reset, power cycled, been hot plugged, * the target could have reset, power cycled, been hot plugged,
* the application could have run, etc. * the application could have run, etc.
* *
* Drivers only receive valid sector range. * Drivers only receive valid protection block range.
*/ */
retval = bank->driver->protect(bank, set, first, last); retval = bank->driver->protect(bank, set, first, last);
if (retval != ERROR_OK) if (retval != ERROR_OK)
LOG_ERROR("failed setting protection for areas %d to %d", first, last); LOG_ERROR("failed setting protection for blocks %d to %d", first, last);
return retval; return retval;
} }
@ -288,7 +295,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank)
goto done; goto done;
for (nBytes = 0; nBytes < chunk; nBytes++) { for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0xFF) { if (buffer[nBytes] != bank->erased_value) {
bank->sectors[i].is_erased = 0; bank->sectors[i].is_erased = 0;
break; break;
} }
@ -319,12 +326,12 @@ int default_flash_blank_check(struct flash_bank *bank)
uint32_t address = bank->base + bank->sectors[i].offset; uint32_t address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size; uint32_t size = bank->sectors[i].size;
retval = target_blank_check_memory(target, address, size, &blank); retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
fast_check = 0; fast_check = 0;
break; break;
} }
if (blank == 0xFF) if (blank == bank->erased_value)
bank->sectors[i].is_erased = 1; bank->sectors[i].is_erased = 1;
else else
bank->sectors[i].is_erased = 0; bank->sectors[i].is_erased = 0;

View File

@ -90,6 +90,9 @@ struct flash_bank {
int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */
int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */
/** Erased value. Defaults to 0xFF. */
uint8_t erased_value;
/** Default padded value used, normally this matches the flash /** Default padded value used, normally this matches the flash
* erased value. Defaults to 0xFF. */ * erased value. Defaults to 0xFF. */
uint8_t default_padded_value; uint8_t default_padded_value;

View File

@ -28,6 +28,7 @@ extern struct flash_driver at91sam4_flash;
extern struct flash_driver at91sam4l_flash; extern struct flash_driver at91sam4l_flash;
extern struct flash_driver at91sam7_flash; extern struct flash_driver at91sam7_flash;
extern struct flash_driver at91samd_flash; extern struct flash_driver at91samd_flash;
extern struct flash_driver ath79_flash;
extern struct flash_driver atsamv_flash; extern struct flash_driver atsamv_flash;
extern struct flash_driver avr_flash; extern struct flash_driver avr_flash;
extern struct flash_driver cfi_flash; extern struct flash_driver cfi_flash;
@ -81,6 +82,7 @@ static struct flash_driver *flash_drivers[] = {
&at91sam4l_flash, &at91sam4l_flash,
&at91sam7_flash, &at91sam7_flash,
&at91samd_flash, &at91samd_flash,
&ath79_flash,
&atsamv_flash, &atsamv_flash,
&avr_flash, &avr_flash,
&cfi_flash, &cfi_flash,

View File

@ -456,10 +456,10 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
uint32_t *ptr = NULL; uint32_t *ptr = NULL;
int ret = 0; int ret = 0;
assert(!(bank->num_sectors & 0x1f)); assert(bank->num_sectors > 0);
data_size = bank->num_sectors / 8; /* number of data bytes */ /* calculate the number of 32-bit words to read (one lock bit per sector) */
data_size /= 4; /* ...and data dwords */ data_size = (bank->num_sectors + 31) / 32;
ptr = efm32x_info->lb_page; ptr = efm32x_info->lb_page;

View File

@ -702,6 +702,11 @@ static int em357_probe(struct flash_bank *bank)
num_pages = 128; num_pages = 128;
page_size = 2048; page_size = 2048;
break; break;
case 0x80000:
/* 512k -- 256 2k pages */
num_pages = 256;
page_size = 2048;
break;
default: default:
LOG_WARNING("No size specified for em357 flash driver, assuming 192k!"); LOG_WARNING("No size specified for em357 flash driver, assuming 192k!");
num_pages = 96; num_pages = 96;

View File

@ -272,7 +272,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2); uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
uint32_t addr = bank->base + offset; uint32_t addr = bank->base + offset;
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32, LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
MIN(halfwords * 2, byte_count), data_workarea->address); MIN(halfwords * 2, byte_count), data_workarea->address);
retval = target_write_buffer(target, data_workarea->address, retval = target_write_buffer(target, data_workarea->address,

View File

@ -102,6 +102,7 @@
#define WDOG_STCTRH 0x40052000 #define WDOG_STCTRH 0x40052000
#define SMC_PMCTRL 0x4007E001 #define SMC_PMCTRL 0x4007E001
#define SMC_PMSTAT 0x4007E003 #define SMC_PMSTAT 0x4007E003
#define MCM_PLACR 0xF000300C
/* Values */ /* Values */
#define PM_STAT_RUN 0x01 #define PM_STAT_RUN 0x01
@ -206,6 +207,7 @@
#define KINETIS_SDID_FAMILYID_K4X 0x40000000 #define KINETIS_SDID_FAMILYID_K4X 0x40000000
#define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K6X 0x60000000
#define KINETIS_SDID_FAMILYID_K7X 0x70000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000
#define KINETIS_SDID_FAMILYID_K8X 0x80000000
struct kinetis_flash_bank { struct kinetis_flash_bank {
bool probed; bool probed;
@ -231,7 +233,8 @@ struct kinetis_flash_bank {
FS_PROGRAM_SECTOR = 1, FS_PROGRAM_SECTOR = 1,
FS_PROGRAM_LONGWORD = 2, FS_PROGRAM_LONGWORD = 2,
FS_PROGRAM_PHRASE = 4, /* Unsupported */ FS_PROGRAM_PHRASE = 4, /* Unsupported */
FS_INVALIDATE_CACHE = 8, FS_INVALIDATE_CACHE_K = 8,
FS_INVALIDATE_CACHE_L = 0x10,
} flash_support; } flash_support;
}; };
@ -609,6 +612,9 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
return ERROR_OK; return ERROR_OK;
} }
if (!dap->ops)
return ERROR_OK; /* too early to check, in JTAG mode ops may not be initialised */
uint32_t val; uint32_t val;
int retval; int retval;
@ -623,7 +629,7 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
} }
if (val == 0) if (val == 0)
return ERROR_OK; return ERROR_OK; /* dap not yet initialised */
bool found = false; bool found = false;
for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) { for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) {
@ -862,65 +868,7 @@ static int kinetis_ftfx_prepare(struct target *target)
/* Kinetis Program-LongWord Microcodes */ /* Kinetis Program-LongWord Microcodes */
static const uint8_t kinetis_flash_write_code[] = { static const uint8_t kinetis_flash_write_code[] = {
/* Params: #include "../../../contrib/loaders/flash/kinetis/kinetis_flash.inc"
* r0 - workarea buffer
* r1 - target address
* r2 - wordcount
* Clobbered:
* r4 - tmp
* r5 - tmp
* r6 - tmp
* r7 - tmp
*/
/* .L1: */
/* for(register uint32_t i=0;i<wcount;i++){ */
0x04, 0x1C, /* mov r4, r0 */
0x00, 0x23, /* mov r3, #0 */
/* .L2: */
0x0E, 0x1A, /* sub r6, r1, r0 */
0xA6, 0x19, /* add r6, r4, r6 */
0x93, 0x42, /* cmp r3, r2 */
0x16, 0xD0, /* beq .L9 */
/* .L5: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x0B, 0x4D, /* ldr r5, .L10 */
0x2F, 0x78, /* ldrb r7, [r5] */
0x7F, 0xB2, /* sxtb r7, r7 */
0x00, 0x2F, /* cmp r7, #0 */
0xFA, 0xDA, /* bge .L5 */
/* FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCO */
0x70, 0x27, /* mov r7, #112 */
0x2F, 0x70, /* strb r7, [r5] */
/* FTFx_FCCOB3 = faddr; */
0x09, 0x4F, /* ldr r7, .L10+4 */
0x3E, 0x60, /* str r6, [r7] */
0x06, 0x27, /* mov r7, #6 */
/* FTFx_FCCOB0 = 0x06; */
0x08, 0x4E, /* ldr r6, .L10+8 */
0x37, 0x70, /* strb r7, [r6] */
/* FTFx_FCCOB7 = *pLW; */
0x80, 0xCC, /* ldmia r4!, {r7} */
0x08, 0x4E, /* ldr r6, .L10+12 */
0x37, 0x60, /* str r7, [r6] */
/* FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK; */
0x80, 0x27, /* mov r7, #128 */
0x2F, 0x70, /* strb r7, [r5] */
/* .L4: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x2E, 0x78, /* ldrb r6, [r5] */
0x77, 0xB2, /* sxtb r7, r6 */
0x00, 0x2F, /* cmp r7, #0 */
0xFB, 0xDA, /* bge .L4 */
0x01, 0x33, /* add r3, r3, #1 */
0xE4, 0xE7, /* b .L2 */
/* .L9: */
0x00, 0xBE, /* bkpt #0 */
/* .L10: */
0x00, 0x00, 0x02, 0x40, /* .word 1073872896 */
0x04, 0x00, 0x02, 0x40, /* .word 1073872900 */
0x07, 0x00, 0x02, 0x40, /* .word 1073872903 */
0x08, 0x00, 0x02, 0x40, /* .word 1073872904 */
}; };
/* Program LongWord Block Write */ /* Program LongWord Block Write */
@ -933,20 +881,11 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
struct working_area *source; struct working_area *source;
struct kinetis_flash_bank *kinfo = bank->driver_priv; struct kinetis_flash_bank *kinfo = bank->driver_priv;
uint32_t address = kinfo->prog_base + offset; uint32_t address = kinfo->prog_base + offset;
struct reg_param reg_params[3]; uint32_t end_address;
struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info; struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK; int retval;
uint8_t fstat;
/* Params:
* r0 - workarea buffer
* r1 - target address
* r2 - wordcount
* Clobbered:
* r4 - tmp
* r5 - tmp
* r6 - tmp
* r7 - tmp
*/
/* Increase buffer_size if needed */ /* Increase buffer_size if needed */
if (buffer_size < (target->working_area_size/2)) if (buffer_size < (target->working_area_size/2))
@ -979,35 +918,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD; armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */ init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* address */
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */ init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* word count */
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
/* write code buffer and use Flash programming code within kinetis */ buf_set_u32(reg_params[0].value, 0, 32, address);
/* Set breakpoint to 0 with time-out of 1000 ms */ buf_set_u32(reg_params[1].value, 0, 32, wcount);
while (wcount > 0) { buf_set_u32(reg_params[2].value, 0, 32, source->address);
uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT);
retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
if (retval != ERROR_OK) 0, NULL,
break; 5, reg_params,
source->address, source->size,
write_algorithm->address, 0,
&armv7m_info);
buf_set_u32(reg_params[0].value, 0, 32, source->address); if (retval == ERROR_FLASH_OPERATION_FAILED) {
buf_set_u32(reg_params[1].value, 0, 32, address); end_address = buf_get_u32(reg_params[0].value, 0, 32);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
retval = target_run_algorithm(target, 0, NULL, 3, reg_params, LOG_ERROR("Error writing flash at %08" PRIx32, end_address);
write_algorithm->address, 0, 100000, &armv7m_info);
if (retval != ERROR_OK) { retval = target_read_u8(target, FTFx_FSTAT, &fstat);
if (retval == ERROR_OK) {
retval = kinetis_ftfx_decode_error(fstat);
/* reset error flags */
target_write_u8(target, FTFx_FSTAT, 0x70);
}
} else if (retval != ERROR_OK)
LOG_ERROR("Error executing kinetis Flash programming algorithm"); LOG_ERROR("Error executing kinetis Flash programming algorithm");
retval = ERROR_FLASH_OPERATION_FAILED;
break;
}
buffer += thisrun_count * 4;
address += thisrun_count * 4;
wcount -= thisrun_count;
}
target_free_working_area(target, source); target_free_working_area(target, source);
target_free_working_area(target, write_algorithm); target_free_working_area(target, write_algorithm);
@ -1015,6 +958,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
destroy_reg_param(&reg_params[0]); destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]); destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]); destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_params[4]);
return retval; return retval;
} }
@ -1236,12 +1181,13 @@ static int kinetis_check_run_mode(struct target *target)
static void kinetis_invalidate_flash_cache(struct flash_bank *bank) static void kinetis_invalidate_flash_cache(struct flash_bank *bank)
{ {
struct kinetis_flash_bank *kinfo = bank->driver_priv; struct kinetis_flash_bank *kinfo = bank->driver_priv;
uint8_t pfb01cr_byte2 = 0xf0;
if (!(kinfo->flash_support & FS_INVALIDATE_CACHE)) if (kinfo->flash_support & FS_INVALIDATE_CACHE_K)
return; target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0);
else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L)
target_write_u8(bank->target, MCM_PLACR + 1, 0x04);
target_write_memory(bank->target, FMC_PFB01CR + 2, 1, 1, &pfb01cr_byte2);
return; return;
} }
@ -1425,7 +1371,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) {
/* fallback to longword write */ /* fallback to longword write */
fallback = 1; fallback = 1;
LOG_WARNING("This device supports Program Longword execution only."); LOG_INFO("This device supports Program Longword execution only.");
} else { } else {
result = kinetis_make_ram_ready(bank->target); result = kinetis_make_ram_ready(bank->target);
if (result != ERROR_OK) { if (result != ERROR_OK) {
@ -1604,7 +1550,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 1<<10; pflash_sector_size_bytes = 1<<10;
nvm_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K10_M72:
case KINETIS_K_SDID_K20_M72: case KINETIS_K_SDID_K20_M72:
@ -1617,7 +1563,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
nvm_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
break; break;
case KINETIS_K_SDID_K10_M100: case KINETIS_K_SDID_K10_M100:
@ -1633,7 +1579,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
nvm_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 2<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K21_M120:
case KINETIS_K_SDID_K22_M120: case KINETIS_K_SDID_K22_M120:
@ -1642,7 +1588,7 @@ static int kinetis_probe(struct flash_bank *bank)
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
nvm_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K10_M120:
case KINETIS_K_SDID_K20_M120: case KINETIS_K_SDID_K20_M120:
@ -1652,7 +1598,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 4<<10; pflash_sector_size_bytes = 4<<10;
nvm_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10;
num_blocks = 4; num_blocks = 4;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
default: default:
LOG_ERROR("Unsupported K-family FAMID"); LOG_ERROR("Unsupported K-family FAMID");
@ -1666,7 +1612,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* K02FN64, K02FN128: FTFA, 2kB sectors */ /* K02FN64, K02FN128: FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
num_blocks = 1; num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
@ -1681,7 +1627,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* MK24FN1M */ /* MK24FN1M */
pflash_sector_size_bytes = 4<<10; pflash_sector_size_bytes = 4<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
break; break;
} }
@ -1691,7 +1637,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
/* autodetect 1 or 2 blocks */ /* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break; break;
} }
LOG_ERROR("Unsupported Kinetis K22 DIEID"); LOG_ERROR("Unsupported Kinetis K22 DIEID");
@ -1702,12 +1648,12 @@ static int kinetis_probe(struct flash_bank *bank)
if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) {
/* K24FN256 - smaller pflash with FTFA */ /* K24FN256 - smaller pflash with FTFA */
num_blocks = 1; num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break; break;
} }
/* K24FN1M without errata 7534 */ /* K24FN1M without errata 7534 */
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
break; break;
@ -1721,7 +1667,7 @@ static int kinetis_probe(struct flash_bank *bank)
nvm_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10;
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
num_blocks = 2; num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6:
@ -1732,8 +1678,18 @@ static int kinetis_probe(struct flash_bank *bank)
nvm_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10;
kinfo->max_flash_prog_size = 1<<10; kinfo->max_flash_prog_size = 1<<10;
num_blocks = 4; num_blocks = 4;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0:
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1:
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2:
/* K80FN256, K81FN256, K82FN256 */
pflash_sector_size_bytes = 4<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
default: default:
LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID");
} }
@ -1744,7 +1700,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 1<<10; pflash_sector_size_bytes = 1<<10;
nvm_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10;
/* autodetect 1 or 2 blocks */ /* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break; break;
case KINETIS_SDID_SERIESID_KV: case KINETIS_SDID_SERIESID_KV:
@ -1754,14 +1710,14 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV10: FTFA, 1kB sectors */ /* KV10: FTFA, 1kB sectors */
pflash_sector_size_bytes = 1<<10; pflash_sector_size_bytes = 1<<10;
num_blocks = 1; num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break; break;
case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1: case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1:
/* KV11: FTFA, 2kB sectors */ /* KV11: FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
num_blocks = 1; num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break; break;
case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0:
@ -1770,7 +1726,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV31: FTFA, 2kB sectors, 2 blocks */ /* KV31: FTFA, 2kB sectors, 2 blocks */
pflash_sector_size_bytes = 2<<10; pflash_sector_size_bytes = 2<<10;
/* autodetect 1 or 2 blocks */ /* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break; break;
case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2:
@ -1779,7 +1735,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV4x: FTFA, 4kB sectors */ /* KV4x: FTFA, 4kB sectors */
pflash_sector_size_bytes = 4<<10; pflash_sector_size_bytes = 4<<10;
num_blocks = 1; num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break; break;
default: default:

View File

@ -259,6 +259,8 @@
#define IAP_CODE_LEN 0x34 #define IAP_CODE_LEN 0x34
#define LPC11xx_REG_SECTORS 24
typedef enum { typedef enum {
lpc2000_v1, lpc2000_v1,
lpc2000_v2, lpc2000_v2,
@ -554,14 +556,21 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
exit(-1); exit(-1);
} }
lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */ lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */
bank->num_sectors = bank->size / 4096; unsigned int large_sectors = 0;
unsigned int normal_sectors = bank->size / 4096;
if (normal_sectors > LPC11xx_REG_SECTORS) {
large_sectors = (normal_sectors - LPC11xx_REG_SECTORS) / 8;
normal_sectors = LPC11xx_REG_SECTORS;
}
bank->num_sectors = normal_sectors + large_sectors;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (int i = 0; i < bank->num_sectors; i++) { for (int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = offset; bank->sectors[i].offset = offset;
/* all sectors are 4kB-sized */ bank->sectors[i].size = (i < LPC11xx_REG_SECTORS ? 4 : 32) * 1024;
bank->sectors[i].size = 4 * 1024;
offset += bank->sectors[i].size; offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1; bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1; bank->sectors[i].is_protected = 1;
@ -679,7 +688,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working
int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate); int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", LOG_ERROR("Write memory at address 0x%8.8" TARGET_PRIxADDR " failed (check work_area definition)",
(*iap_working_area)->address); (*iap_working_area)->address);
target_free_working_area(target, *iap_working_area); target_free_working_area(target, *iap_working_area);
} }

View File

@ -186,7 +186,7 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank)
return retval; return retval;
} }
LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32, LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR,
spifi_init_algorithm->address); spifi_init_algorithm->address);
/* Write algorithm to working area */ /* Write algorithm to working area */
retval = target_write_buffer(target, retval = target_write_buffer(target,

View File

@ -171,7 +171,8 @@ static int mdr_erase(struct flash_bank *bank, int first, int last)
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto reset_pg_and_lock; goto reset_pg_and_lock;
if ((first == 0) && (last == (bank->num_sectors - 1))) { if ((first == 0) && (last == (bank->num_sectors - 1)) &&
!mdr_info->mem_type) {
retval = mdr_mass_erase(bank); retval = mdr_mass_erase(bank);
goto reset_pg_and_lock; goto reset_pg_and_lock;
} }

View File

@ -108,7 +108,6 @@ enum nrf51_nvmc_config_bits {
struct nrf51_info { struct nrf51_info {
uint32_t code_page_size; uint32_t code_page_size;
uint32_t code_memory_size;
struct { struct {
bool probed; bool probed;
@ -121,6 +120,7 @@ struct nrf51_info {
struct nrf51_device_spec { struct nrf51_device_spec {
uint16_t hwid; uint16_t hwid;
const char *part;
const char *variant; const char *variant;
const char *build_code; const char *build_code;
unsigned int flash_size_kb; unsigned int flash_size_kb;
@ -142,30 +142,35 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 1). */ /* nRF51822 Devices (IC rev 1). */
{ {
.hwid = 0x001D, .hwid = 0x001D,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "CA/C0", .build_code = "CA/C0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0026, .hwid = 0x0026,
.part = "51822",
.variant = "QFAB", .variant = "QFAB",
.build_code = "AA", .build_code = "AA",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0027, .hwid = 0x0027,
.part = "51822",
.variant = "QFAB", .variant = "QFAB",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0020, .hwid = 0x0020,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "BA", .build_code = "BA",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x002F, .hwid = 0x002F,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "B0", .build_code = "B0",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -174,54 +179,63 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 2). */ /* nRF51822 Devices (IC rev 2). */
{ {
.hwid = 0x002A, .hwid = 0x002A,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "FA0", .build_code = "FA0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0044, .hwid = 0x0044,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "GC0", .build_code = "GC0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x003C, .hwid = 0x003C,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "G0", .build_code = "G0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0057, .hwid = 0x0057,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "G2", .build_code = "G2",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0058, .hwid = 0x0058,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "G3", .build_code = "G3",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x004C, .hwid = 0x004C,
.part = "51822",
.variant = "QFAB", .variant = "QFAB",
.build_code = "B0", .build_code = "B0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0040, .hwid = 0x0040,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "CA0", .build_code = "CA0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0047, .hwid = 0x0047,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "DA0", .build_code = "DA0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x004D, .hwid = 0x004D,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "D00", .build_code = "D00",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -230,62 +244,79 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 3). */ /* nRF51822 Devices (IC rev 3). */
{ {
.hwid = 0x0072, .hwid = 0x0072,
.part = "51822",
.variant = "QFAA", .variant = "QFAA",
.build_code = "H0", .build_code = "H0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x007B, .hwid = 0x007B,
.part = "51822",
.variant = "QFAB", .variant = "QFAB",
.build_code = "C0", .build_code = "C0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0083, .hwid = 0x0083,
.part = "51822",
.variant = "QFAC", .variant = "QFAC",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0084, .hwid = 0x0084,
.part = "51822",
.variant = "QFAC", .variant = "QFAC",
.build_code = "A1", .build_code = "A1",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x007D, .hwid = 0x007D,
.part = "51822",
.variant = "CDAB", .variant = "CDAB",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0079, .hwid = 0x0079,
.part = "51822",
.variant = "CEAA", .variant = "CEAA",
.build_code = "E0", .build_code = "E0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0087, .hwid = 0x0087,
.part = "51822",
.variant = "CFAC", .variant = "CFAC",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{
.hwid = 0x008F,
.part = "51822",
.variant = "QFAA",
.build_code = "H1",
.flash_size_kb = 256,
},
/* nRF51422 Devices (IC rev 1). */ /* nRF51422 Devices (IC rev 1). */
{ {
.hwid = 0x001E, .hwid = 0x001E,
.part = "51422",
.variant = "QFAA", .variant = "QFAA",
.build_code = "CA", .build_code = "CA",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0024, .hwid = 0x0024,
.part = "51422",
.variant = "QFAA", .variant = "QFAA",
.build_code = "C0", .build_code = "C0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0031, .hwid = 0x0031,
.part = "51422",
.variant = "CEAA", .variant = "CEAA",
.build_code = "A0A", .build_code = "A0A",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -294,24 +325,28 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51422 Devices (IC rev 2). */ /* nRF51422 Devices (IC rev 2). */
{ {
.hwid = 0x002D, .hwid = 0x002D,
.part = "51422",
.variant = "QFAA", .variant = "QFAA",
.build_code = "DAA", .build_code = "DAA",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x002E, .hwid = 0x002E,
.part = "51422",
.variant = "QFAA", .variant = "QFAA",
.build_code = "E0", .build_code = "E0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0061, .hwid = 0x0061,
.part = "51422",
.variant = "QFAB", .variant = "QFAB",
.build_code = "A00", .build_code = "A00",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0050, .hwid = 0x0050,
.part = "51422",
.variant = "CEAA", .variant = "CEAA",
.build_code = "B0", .build_code = "B0",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -320,42 +355,49 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51422 Devices (IC rev 3). */ /* nRF51422 Devices (IC rev 3). */
{ {
.hwid = 0x0073, .hwid = 0x0073,
.part = "51422",
.variant = "QFAA", .variant = "QFAA",
.build_code = "F0", .build_code = "F0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x007C, .hwid = 0x007C,
.part = "51422",
.variant = "QFAB", .variant = "QFAB",
.build_code = "B0", .build_code = "B0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x0085, .hwid = 0x0085,
.part = "51422",
.variant = "QFAC", .variant = "QFAC",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0086, .hwid = 0x0086,
.part = "51422",
.variant = "QFAC", .variant = "QFAC",
.build_code = "A1", .build_code = "A1",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x007E, .hwid = 0x007E,
.part = "51422",
.variant = "CDAB", .variant = "CDAB",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 128, .flash_size_kb = 128,
}, },
{ {
.hwid = 0x007A, .hwid = 0x007A,
.part = "51422",
.variant = "CEAA", .variant = "CEAA",
.build_code = "C0", .build_code = "C0",
.flash_size_kb = 256, .flash_size_kb = 256,
}, },
{ {
.hwid = 0x0088, .hwid = 0x0088,
.part = "51422",
.variant = "CFAC", .variant = "CFAC",
.build_code = "A0", .build_code = "A0",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -366,6 +408,7 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
in the nRF51 Series Compatibility Matrix V1.0. */ in the nRF51 Series Compatibility Matrix V1.0. */
{ {
.hwid = 0x0071, .hwid = 0x0071,
.part = "51822",
.variant = "QFAC", .variant = "QFAC",
.build_code = "AB", .build_code = "AB",
.flash_size_kb = 256, .flash_size_kb = 256,
@ -627,22 +670,24 @@ static int nrf51_probe(struct flash_bank *bank)
* bytes of the CONFIGID register */ * bytes of the CONFIGID register */
const struct nrf51_device_spec *spec = NULL; const struct nrf51_device_spec *spec = NULL;
for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) {
if (hwid == nrf51_known_devices_table[i].hwid) { if (hwid == nrf51_known_devices_table[i].hwid) {
spec = &nrf51_known_devices_table[i]; spec = &nrf51_known_devices_table[i];
break; break;
} }
}
if (!chip->bank[0].probed && !chip->bank[1].probed) { if (!chip->bank[0].probed && !chip->bank[1].probed) {
if (spec) if (spec)
LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash", LOG_INFO("nRF%s-%s(build code: %s) %ukB Flash",
spec->variant, spec->build_code, spec->flash_size_kb); spec->part, spec->variant, spec->build_code,
spec->flash_size_kb);
else else
LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid); LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid);
} }
if (bank->base == NRF51_FLASH_BASE) { if (bank->base == NRF51_FLASH_BASE) {
/* The value stored in NRF51_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE, res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE,
&chip->code_page_size); &chip->code_page_size);
if (res != ERROR_OK) { if (res != ERROR_OK) {
@ -650,20 +695,21 @@ static int nrf51_probe(struct flash_bank *bank)
return res; return res;
} }
res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, /* Note the register name is misleading,
&chip->code_memory_size); * NRF51_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
uint32_t num_sectors;
res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, &num_sectors);
if (res != ERROR_OK) { if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code memory size"); LOG_ERROR("Couldn't read code memory size");
return res; return res;
} }
if (spec && chip->code_memory_size != spec->flash_size_kb) { bank->num_sectors = num_sectors;
LOG_ERROR("Chip's reported Flash capacity does not match expected one"); bank->size = num_sectors * chip->code_page_size;
return ERROR_FAIL;
} if (spec && bank->size / 1024 != spec->flash_size_kb)
LOG_WARNING("Chip's reported Flash capacity does not match expected one");
bank->size = chip->code_memory_size * 1024;
bank->num_sectors = bank->size / chip->code_page_size;
bank->sectors = calloc(bank->num_sectors, bank->sectors = calloc(bank->num_sectors,
sizeof((bank->sectors)[0])); sizeof((bank->sectors)[0]));
if (!bank->sectors) if (!bank->sectors)
@ -1272,7 +1318,7 @@ static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size)
"reset value for XTALFREQ: %"PRIx32"\n" "reset value for XTALFREQ: %"PRIx32"\n"
"firmware id: 0x%04"PRIx32, "firmware id: 0x%04"PRIx32,
ficr[0].value, ficr[0].value,
ficr[1].value, (ficr[1].value * ficr[0].value) / 1024,
(ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024, (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present", ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
ficr[4].value, ficr[4].value,

View File

@ -879,7 +879,6 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
COMMAND_HANDLER(pic32mx_handle_unlock_command) COMMAND_HANDLER(pic32mx_handle_unlock_command)
{ {
uint32_t mchip_cmd;
struct target *target = NULL; struct target *target = NULL;
struct mips_m4k_common *mips_m4k; struct mips_m4k_common *mips_m4k;
struct mips_ejtag *ejtag_info; struct mips_ejtag *ejtag_info;
@ -904,7 +903,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
/* first check status of device */ /* first check status of device */
mchip_cmd = MCHP_STATUS; uint8_t mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (mchip_cmd & (1 << 7)) { if (mchip_cmd & (1 << 7)) {
/* device is not locked */ /* device is not locked */

View File

@ -110,6 +110,9 @@
#define FLASH_ERASE_TIMEOUT 10000 #define FLASH_ERASE_TIMEOUT 10000
#define FLASH_WRITE_TIMEOUT 5 #define FLASH_WRITE_TIMEOUT 5
/* Mass erase time can be as high as 32 s in x8 mode. */
#define FLASH_MASS_ERASE_TIMEOUT 33000
#define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_BASE 0x40023c00
#define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_ACR 0x40023c00
#define STM32_FLASH_KEYR 0x40023c04 #define STM32_FLASH_KEYR 0x40023c04
@ -399,8 +402,8 @@ static int stm32x_write_options(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* wait for completion */ /* wait for completion, this might trigger a security erase and take a while */
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1257,7 +1260,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = stm32x_wait_status_busy(bank, 30000); retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;

View File

@ -27,18 +27,22 @@
/* STM32L4xxx series for reference. /* STM32L4xxx series for reference.
* *
* RM0351 * RM0351 (STM32L4x5/STM32L4x6)
* http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf * http://www.st.com/resource/en/reference_manual/dm00083560.pdf
*
* RM0394 (STM32L43x/44x/45x/46x)
* http://www.st.com/resource/en/reference_manual/dm00151940.pdf
* *
* STM32L476RG Datasheet (for erase timing) * STM32L476RG Datasheet (for erase timing)
* http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf * http://www.st.com/resource/en/datasheet/stm32l476rg.pdf
* *
* * The RM0351 devices have normally two banks, but on 512 and 256 kiB devices
* The device has normally two banks, but on 512 and 256 kiB devices an * an option byte is available to map all sectors to the first bank.
* option byte is available to map all sectors to the first bank.
* Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices * Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices
* handlers do! * handlers do!
* *
* RM0394 devices have a single bank only.
*
*/ */
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */ /* Erase time can be as high as 25ms, 10x this and assume it's toast... */
@ -614,9 +618,16 @@ static int stm32l4_probe(struct flash_bank *bank)
/* set max flash size depending on family */ /* set max flash size depending on family */
switch (device_id & 0xfff) { switch (device_id & 0xfff) {
case 0x461:
case 0x415: case 0x415:
max_flash_size_in_kb = 1024; max_flash_size_in_kb = 1024;
break; break;
case 0x462:
max_flash_size_in_kb = 512;
break;
case 0x435:
max_flash_size_in_kb = 256;
break;
default: default:
LOG_WARNING("Cannot identify target as a STM32L4 family."); LOG_WARNING("Cannot identify target as a STM32L4 family.");
return ERROR_FAIL; return ERROR_FAIL;
@ -698,7 +709,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
uint16_t device_id = dbgmcu_idcode & 0xffff; uint16_t device_id = dbgmcu_idcode & 0xfff;
uint8_t rev_id = dbgmcu_idcode >> 28; uint8_t rev_id = dbgmcu_idcode >> 28;
uint8_t rev_minor = 0; uint8_t rev_minor = 0;
int i; int i;
@ -713,8 +724,20 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
const char *device_str; const char *device_str;
switch (device_id) { switch (device_id) {
case 0x6415: case 0x461:
device_str = "STM32L4xx"; device_str = "STM32L496/4A6";
break;
case 0x415:
device_str = "STM32L475/476/486";
break;
case 0x462:
device_str = "STM32L45x/46x";
break;
case 0x435:
device_str = "STM32L43x/44x";
break; break;
default: default:

View File

@ -105,6 +105,7 @@ static int stm32lx_lock(struct flash_bank *bank);
static int stm32lx_unlock(struct flash_bank *bank); static int stm32lx_unlock(struct flash_bank *bank);
static int stm32lx_mass_erase(struct flash_bank *bank); static int stm32lx_mass_erase(struct flash_bank *bank);
static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout); static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout);
static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb);
struct stm32lx_rev { struct stm32lx_rev {
uint16_t rev; uint16_t rev;
@ -132,7 +133,7 @@ struct stm32lx_flash_bank {
uint32_t user_bank_size; uint32_t user_bank_size;
uint32_t flash_base; uint32_t flash_base;
const struct stm32lx_part_info *part_info; struct stm32lx_part_info part_info;
}; };
static const struct stm32lx_rev stm32_416_revs[] = { static const struct stm32lx_rev stm32_416_revs[] = {
@ -245,7 +246,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.page_size = 256, .page_size = 256,
.pages_per_sector = 16, .pages_per_sector = 16,
.max_flash_size_kb = 512, .max_flash_size_kb = 512,
.first_bank_size_kb = 256, .first_bank_size_kb = 0, /* determined in runtime */
.has_dual_banks = true, .has_dual_banks = true,
.flash_base = 0x40023C00, .flash_base = 0x40023C00,
.fsize_base = 0x1FF800CC, .fsize_base = 0x1FF800CC,
@ -258,8 +259,8 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.page_size = 128, .page_size = 128,
.pages_per_sector = 32, .pages_per_sector = 32,
.max_flash_size_kb = 192, .max_flash_size_kb = 192,
.first_bank_size_kb = 128, .first_bank_size_kb = 0, /* determined in runtime */
.has_dual_banks = true, .has_dual_banks = false, /* determined in runtime */
.flash_base = 0x40022000, .flash_base = 0x40022000,
.fsize_base = 0x1FF8007C, .fsize_base = 0x1FF8007C,
}, },
@ -300,7 +301,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
stm32lx_info->user_bank_size = bank->size; stm32lx_info->user_bank_size = bank->size;
/* the stm32l erased value is 0x00 */ /* the stm32l erased value is 0x00 */
bank->default_padded_value = 0x00; bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK; return ERROR_OK;
} }
@ -436,7 +437,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
struct target *target = bank->target; struct target *target = bank->target;
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; uint32_t hp_nb = stm32lx_info->part_info.page_size / 2;
uint32_t buffer_size = 16384; uint32_t buffer_size = 16384;
struct working_area *write_algorithm; struct working_area *write_algorithm;
struct working_area *source; struct working_area *source;
@ -450,19 +451,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
/* see contib/loaders/flash/stm32lx.S for src */ /* see contib/loaders/flash/stm32lx.S for src */
static const uint8_t stm32lx_flash_write_code[] = { static const uint8_t stm32lx_flash_write_code[] = {
/* write_word: */ 0x92, 0x00, 0x8A, 0x18, 0x01, 0xE0, 0x08, 0xC9, 0x08, 0xC0, 0x91, 0x42, 0xFB, 0xD1, 0x00, 0xBE
0x00, 0x23, /* movs r3, #0 */
0x04, 0xe0, /* b test_done */
/* write_word: */
0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */
0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */
0x01, 0x33, /* adds r3, #1 */
/* test_done: */
0x93, 0x42, /* cmp r3, r2 */
0xf8, 0xd3, /* bcc write_word */
0x00, 0xbe, /* bkpt 0 */
}; };
/* Make sure we're performing a half-page aligned write. */ /* Make sure we're performing a half-page aligned write. */
@ -495,7 +484,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
else else
buffer_size /= 2; buffer_size /= 2;
if (buffer_size <= stm32lx_info->part_info->page_size) { if (buffer_size <= stm32lx_info->part_info.page_size) {
/* we already allocated the writing code, but failed to get a /* we already allocated the writing code, but failed to get a
* buffer, free the algorithm */ * buffer, free the algorithm */
target_free_working_area(target, write_algorithm); target_free_working_area(target, write_algorithm);
@ -588,7 +577,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
* is reduced by 50% using this slower method. * is reduced by 50% using this slower method.
*/ */
LOG_WARNING("couldn't use loader, falling back to page memory writes"); LOG_WARNING("Couldn't use loader, falling back to page memory writes");
while (count > 0) { while (count > 0) {
uint32_t this_count; uint32_t this_count;
@ -629,7 +618,7 @@ static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer,
struct target *target = bank->target; struct target *target = bank->target;
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; uint32_t hp_nb = stm32lx_info->part_info.page_size / 2;
uint32_t halfpages_number; uint32_t halfpages_number;
uint32_t bytes_remaining = 0; uint32_t bytes_remaining = 0;
uint32_t address = bank->base + offset; uint32_t address = bank->base + offset;
@ -759,9 +748,9 @@ static int stm32lx_probe(struct flash_bank *bank)
uint32_t device_id; uint32_t device_id;
uint32_t base_address = FLASH_BANK0_ADDRESS; uint32_t base_address = FLASH_BANK0_ADDRESS;
uint32_t second_bank_base; uint32_t second_bank_base;
unsigned int n;
stm32lx_info->probed = 0; stm32lx_info->probed = 0;
stm32lx_info->part_info = NULL;
int retval = stm32lx_read_id_code(bank->target, &device_id); int retval = stm32lx_read_id_code(bank->target, &device_id);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -771,22 +760,24 @@ static int stm32lx_probe(struct flash_bank *bank)
LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id); LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { for (n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) {
if ((device_id & 0xfff) == stm32lx_parts[n].id) if ((device_id & 0xfff) == stm32lx_parts[n].id) {
stm32lx_info->part_info = &stm32lx_parts[n]; stm32lx_info->part_info = stm32lx_parts[n];
break;
}
} }
if (!stm32lx_info->part_info) { if (n == ARRAY_SIZE(stm32lx_parts)) {
LOG_WARNING("Cannot identify target as a STM32L family."); LOG_WARNING("Cannot identify target as a STM32L family.");
return ERROR_FAIL; return ERROR_FAIL;
} else { } else {
LOG_INFO("Device: %s", stm32lx_info->part_info->device_str); LOG_INFO("Device: %s", stm32lx_info->part_info.device_str);
} }
stm32lx_info->flash_base = stm32lx_info->part_info->flash_base; stm32lx_info->flash_base = stm32lx_info->part_info.flash_base;
/* Get the flash size from target. */ /* Get the flash size from target. */
retval = target_read_u16(target, stm32lx_info->part_info->fsize_base, retval = target_read_u16(target, stm32lx_info->part_info.fsize_base,
&flash_size_in_kb); &flash_size_in_kb);
/* 0x436 devices report their flash size as a 0 or 1 code indicating 384K /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K
@ -803,29 +794,34 @@ static int stm32lx_probe(struct flash_bank *bank)
* default to max target family */ * default to max target family */
if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash", LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash",
stm32lx_info->part_info->max_flash_size_kb); stm32lx_info->part_info.max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb;
} else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) { } else if (flash_size_in_kb > stm32lx_info->part_info.max_flash_size_kb) {
LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash", LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash",
flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb, flash_size_in_kb, stm32lx_info->part_info.max_flash_size_kb,
stm32lx_info->part_info->max_flash_size_kb); stm32lx_info->part_info.max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb;
} }
if (stm32lx_info->part_info->has_dual_banks) { /* Overwrite default dual-bank configuration */
retval = stm32lx_update_part_info(bank, flash_size_in_kb);
if (retval != ERROR_OK)
return ERROR_FAIL;
if (stm32lx_info->part_info.has_dual_banks) {
/* Use the configured base address to determine if this is the first or second flash bank. /* Use the configured base address to determine if this is the first or second flash bank.
* Verify that the base address is reasonably correct and determine the flash bank size * Verify that the base address is reasonably correct and determine the flash bank size
*/ */
second_bank_base = base_address + second_bank_base = base_address +
stm32lx_info->part_info->first_bank_size_kb * 1024; stm32lx_info->part_info.first_bank_size_kb * 1024;
if (bank->base == second_bank_base || !bank->base) { if (bank->base == second_bank_base || !bank->base) {
/* This is the second bank */ /* This is the second bank */
base_address = second_bank_base; base_address = second_bank_base;
flash_size_in_kb = flash_size_in_kb - flash_size_in_kb = flash_size_in_kb -
stm32lx_info->part_info->first_bank_size_kb; stm32lx_info->part_info.first_bank_size_kb;
} else if (bank->base == base_address) { } else if (bank->base == base_address) {
/* This is the first bank */ /* This is the first bank */
flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb; flash_size_in_kb = stm32lx_info->part_info.first_bank_size_kb;
} else { } else {
LOG_WARNING("STM32L flash bank base address config is incorrect." LOG_WARNING("STM32L flash bank base address config is incorrect."
" 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32,
@ -884,60 +880,13 @@ static int stm32lx_auto_probe(struct flash_bank *bank)
return stm32lx_probe(bank); return stm32lx_probe(bank);
} }
static int stm32lx_erase_check(struct flash_bank *bank)
{
struct target *target = bank->target;
const int buffer_size = 4096;
int i;
uint32_t nBytes;
int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
uint8_t *buffer = malloc(buffer_size);
if (buffer == NULL) {
LOG_ERROR("failed to allocate read buffer");
return ERROR_FAIL;
}
for (i = 0; i < bank->num_sectors; i++) {
uint32_t j;
bank->sectors[i].is_erased = 1;
/* Loop chunk by chunk over the sector */
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size))
chunk = (j - bank->sectors[i].size);
retval = target_read_memory(target, bank->base
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
if (retval != ERROR_OK)
break;
for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0x00) {
bank->sectors[i].is_erased = 0;
break;
}
}
}
if (retval != ERROR_OK)
break;
}
free(buffer);
return retval;
}
/* This method must return a string displaying information about the bank */ /* This method must return a string displaying information about the bank */
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
{ {
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
const struct stm32lx_part_info *info = &stm32lx_info->part_info;
uint16_t rev_id = stm32lx_info->idcode >> 16;
const char *rev_str = NULL;
if (!stm32lx_info->probed) { if (!stm32lx_info->probed) {
int retval = stm32lx_probe(bank); int retval = stm32lx_probe(bank);
@ -948,12 +897,6 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
} }
} }
const struct stm32lx_part_info *info = stm32lx_info->part_info;
if (info) {
const char *rev_str = NULL;
uint16_t rev_id = stm32lx_info->idcode >> 16;
for (unsigned int i = 0; i < info->num_revs; i++) for (unsigned int i = 0; i < info->num_revs; i++)
if (rev_id == info->revs[i].rev) if (rev_id == info->revs[i].rev)
rev_str = info->revs[i].str; rev_str = info->revs[i].str;
@ -961,19 +904,14 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
if (rev_str != NULL) { if (rev_str != NULL) {
snprintf(buf, buf_size, snprintf(buf, buf_size,
"%s - Rev: %s", "%s - Rev: %s",
stm32lx_info->part_info->device_str, rev_str); info->device_str, rev_str);
} else { } else {
snprintf(buf, buf_size, snprintf(buf, buf_size,
"%s - Rev: unknown (0x%04x)", "%s - Rev: unknown (0x%04x)",
stm32lx_info->part_info->device_str, rev_id); info->device_str, rev_id);
} }
return ERROR_OK; return ERROR_OK;
} else {
snprintf(buf, buf_size, "Cannot identify target as a STM32Lx");
return ERROR_FAIL;
}
} }
static const struct command_registration stm32lx_exec_command_handlers[] = { static const struct command_registration stm32lx_exec_command_handlers[] = {
@ -1022,7 +960,7 @@ struct flash_driver stm32lx_flash = {
.read = default_flash_read, .read = default_flash_read,
.probe = stm32lx_probe, .probe = stm32lx_probe,
.auto_probe = stm32lx_auto_probe, .auto_probe = stm32lx_auto_probe,
.erase_check = stm32lx_erase_check, .erase_check = default_flash_blank_check,
.protect_check = stm32lx_protect_check, .protect_check = stm32lx_protect_check,
.info = stm32lx_get_info, .info = stm32lx_get_info,
}; };
@ -1182,7 +1120,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector; for (int page = 0; page < (int)stm32lx_info->part_info.pages_per_sector;
page++) { page++) {
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE; reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
retval = target_write_u32(target, retval = target_write_u32(target,
@ -1195,7 +1133,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
return retval; return retval;
uint32_t addr = bank->base + bank->sectors[sector].offset + (page uint32_t addr = bank->base + bank->sectors[sector].offset + (page
* stm32lx_info->part_info->page_size); * stm32lx_info->part_info.page_size);
retval = target_write_u32(target, addr, 0x0); retval = target_write_u32(target, addr, 0x0);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1419,3 +1357,22 @@ static int stm32lx_mass_erase(struct flash_bank *bank)
return ERROR_OK; return ERROR_OK;
} }
static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb)
{
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
switch (stm32lx_info->part_info.id) {
case 0x447: /* STM32L0xx (Cat.5) devices */
if (flash_size_in_kb == 192 || flash_size_in_kb == 128) {
stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2;
stm32lx_info->part_info.has_dual_banks = true;
}
break;
case 0x437: /* STM32L1xx (Cat.5/Cat.6) */
stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2;
break;
}
return ERROR_OK;
}

View File

@ -297,8 +297,8 @@ static int flash_check_sector_parameters(struct command_context *cmd_ctx,
} }
if (!(last <= (num_sectors - 1))) { if (!(last <= (num_sectors - 1))) {
command_print(cmd_ctx, "ERROR: last sector must be <= %d", command_print(cmd_ctx, "ERROR: last sector must be <= %" PRIu32,
(int) num_sectors - 1); num_sectors - 1);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -341,7 +341,7 @@ COMMAND_HANDLER(handle_flash_erase_command)
"in %fs", first, last, p->bank_number, duration_elapsed(&bench)); "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
} }
return ERROR_OK; return retval;
} }
COMMAND_HANDLER(handle_flash_protect_command) COMMAND_HANDLER(handle_flash_protect_command)
@ -380,10 +380,9 @@ COMMAND_HANDLER(handle_flash_protect_command)
retval = flash_driver_protect(p, set, first, last); retval = flash_driver_protect(p, set, first, last);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
command_print(CMD_CTX, "%s protection for sectors %i " command_print(CMD_CTX, "%s protection for sectors %" PRIu32
"through %i on flash bank %d", " through %" PRIu32 " on flash bank %d",
(set) ? "set" : "cleared", (int) first, (set) ? "set" : "cleared", first, last, p->bank_number);
(int) last, p->bank_number);
} }
return retval; return retval;
@ -600,7 +599,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
return ERROR_OK; return ERROR_FAIL;
size_t filesize; size_t filesize;
retval = fileio_size(fileio, &filesize); retval = fileio_size(fileio, &filesize);
@ -619,7 +618,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
free(buffer); free(buffer);
fileio_close(fileio); fileio_close(fileio);
return ERROR_OK; return ERROR_FAIL;
} }
retval = flash_driver_write(p, buffer, offset, buf_cnt); retval = flash_driver_write(p, buffer, offset, buf_cnt);
@ -690,9 +689,9 @@ COMMAND_HANDLER(handle_flash_read_bank_command)
} }
if (duration_measure(&bench) == ERROR_OK) if (duration_measure(&bench) == ERROR_OK)
command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u" command_print(CMD_CTX, "wrote %zd bytes to file %s from flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)written, CMD_ARGV[1], p->bank_number, offset, written, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, written)); duration_elapsed(&bench), duration_kbps(&bench, written));
return retval; return retval;
@ -708,7 +707,7 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
size_t filesize; size_t filesize;
int differ; int differ;
if (CMD_ARGC != 3) if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
struct duration bench; struct duration bench;
@ -719,8 +718,17 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
if (ERROR_OK != retval) if (ERROR_OK != retval)
return retval; return retval;
offset = 0;
if (CMD_ARGC > 2)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
if (offset > p->size) {
LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
offset);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY); retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Could not open file"); LOG_ERROR("Could not open file");
@ -770,9 +778,9 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
} }
if (duration_measure(&bench) == ERROR_OK) if (duration_measure(&bench) == ERROR_OK)
command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u" command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)read_cnt, CMD_ARGV[1], p->bank_number, offset, read_cnt, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, read_cnt)); duration_elapsed(&bench), duration_kbps(&bench, read_cnt));
differ = memcmp(buffer_file, buffer_flash, read_cnt); differ = memcmp(buffer_file, buffer_flash, read_cnt);
@ -927,19 +935,20 @@ static const struct command_registration flash_exec_command_handlers[] = {
.name = "verify_bank", .name = "verify_bank",
.handler = handle_flash_verify_bank_command, .handler = handle_flash_verify_bank_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "bank_id filename offset", .usage = "bank_id filename [offset]",
.help = "Read binary data from flash bank and file, " .help = "Compare the contents of a file with the contents of the "
"starting at specified byte offset from the " "flash bank. Allow optional offset from beginning of the bank "
"beginning of the bank. Compare the contents.", "(defaults to zero).",
}, },
{ {
.name = "protect", .name = "protect",
.handler = handle_flash_protect_command, .handler = handle_flash_protect_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "bank_id first_sector [last_sector|'last'] " .usage = "bank_id first_block [last_block|'last'] "
"('on'|'off')", "('on'|'off')",
.help = "Turn protection on or off for a range of sectors " .help = "Turn protection on or off for a range of protection "
"in a given flash bank.", "blocks or sectors in a given flash bank. "
"See 'flash info' output for a list of blocks.",
}, },
{ {
.name = "padded_value", .name = "padded_value",
@ -1012,7 +1021,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
c->default_padded_value = 0xff; c->default_padded_value = c->erased_value = 0xff;
c->num_sectors = 0; c->num_sectors = 0;
c->sectors = NULL; c->sectors = NULL;
c->num_prot_blocks = 0; c->num_prot_blocks = 0;

View File

@ -44,6 +44,7 @@ static void virtual_update_bank_info(struct flash_bank *bank)
bank->size = master_bank->size; bank->size = master_bank->size;
bank->chip_width = master_bank->chip_width; bank->chip_width = master_bank->chip_width;
bank->bus_width = master_bank->bus_width; bank->bus_width = master_bank->bus_width;
bank->erased_value = master_bank->erased_value;
bank->default_padded_value = master_bank->default_padded_value; bank->default_padded_value = master_bank->default_padded_value;
bank->num_sectors = master_bank->num_sectors; bank->num_sectors = master_bank->num_sectors;
bank->sectors = master_bank->sectors; bank->sectors = master_bank->sectors;

View File

@ -305,7 +305,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE); uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
uint32_t addr = bank->base + offset; uint32_t addr = bank->base + offset;
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32, LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
MIN(blocks * NVM_BLOCK_SIZE, byte_count), MIN(blocks * NVM_BLOCK_SIZE, byte_count),
data_workarea->address); data_workarea->address);

View File

@ -183,7 +183,7 @@
/* Flash controller configuration values */ /* Flash controller configuration values */
#define FLASH_ID_XMC4500 0xA2 #define FLASH_ID_XMC4500 0xA2
#define FLASH_ID_XMC4700_4800 0x92 #define FLASH_ID_XMC4300_XMC4700_4800 0x92
#define FLASH_ID_XMC4100_4200 0x9C #define FLASH_ID_XMC4100_4200 0x9C
#define FLASH_ID_XMC4400 0x9F #define FLASH_ID_XMC4400 0x9F
@ -319,8 +319,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
} }
/* This part doesn't follow the typical standard of 0xff /* This part doesn't follow the typical standard of 0xff
* being the default padding value.*/ * being the erased value.*/
bank->default_padded_value = 0x00; bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK; return ERROR_OK;
} }
@ -383,7 +383,7 @@ static int xmc4xxx_probe(struct flash_bank *bank)
bank->num_sectors = 12; bank->num_sectors = 12;
LOG_DEBUG("XMC4xxx: XMC4500 detected."); LOG_DEBUG("XMC4xxx: XMC4500 detected.");
break; break;
case FLASH_ID_XMC4700_4800: case FLASH_ID_XMC4300_XMC4700_4800:
bank->num_sectors = 16; bank->num_sectors = 16;
LOG_DEBUG("XMC4xxx: XMC4700/4800 detected."); LOG_DEBUG("XMC4xxx: XMC4700/4800 detected.");
break; break;
@ -617,99 +617,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank)
return res; return res;
} }
/* The logical erase value of an xmc4xxx memory cell is 0x00,
* therefore, we cannot use the built in flash blank check and must
* implement our own */
/** Checks whether a memory region is zeroed. */
static int xmc4xxx_blank_check_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *blank)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[3];
struct armv7m_algorithm armv7m_info;
int retval;
static const uint8_t erase_check_code[] = {
#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
};
/* make sure we have a working area */
if (target_alloc_working_area(target, sizeof(erase_check_code),
&erase_check_algorithm) != ERROR_OK)
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
retval = target_write_buffer(target, erase_check_algorithm->address,
sizeof(erase_check_code), (uint8_t *)erase_check_code);
if (retval != ERROR_OK)
goto cleanup;
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, 0x00);
retval = target_run_algorithm(target,
0,
NULL,
3,
reg_params,
erase_check_algorithm->address,
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
10000,
&armv7m_info);
if (retval == ERROR_OK)
*blank = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
cleanup:
target_free_working_area(target, erase_check_algorithm);
return retval;
}
static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
{
struct target *target = bank->target;
int i;
int retval = ERROR_OK;
uint32_t blank;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
for (i = 0; i < bank->num_sectors; i++) {
uint32_t address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size;
LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
if (retval != ERROR_OK)
break;
if (blank == 0x00)
bank->sectors[i].is_erased = 1;
else
bank->sectors[i].is_erased = 0;
}
return retval;
}
static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf, static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
uint32_t offset, bool user_config) uint32_t offset, bool user_config)
{ {
@ -944,6 +851,14 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
break; break;
} }
break; break;
case 0x300:
dev_str = "XMC4300";
switch (rev_id) {
case 0x1:
rev_str = "AA";
}
break;
case 0x400: case 0x400:
dev_str = "XMC4400"; dev_str = "XMC4400";
@ -1437,7 +1352,7 @@ struct flash_driver xmc4xxx_flash = {
.read = default_flash_read, .read = default_flash_read,
.probe = xmc4xxx_probe, .probe = xmc4xxx_probe,
.auto_probe = xmc4xxx_probe, .auto_probe = xmc4xxx_probe,
.erase_check = xmc4xxx_flash_blank_check, .erase_check = default_flash_blank_check,
.info = xmc4xxx_get_info_command, .info = xmc4xxx_get_info_command,
.protect_check = xmc4xxx_protect_check, .protect_check = xmc4xxx_protect_check,
.protect = xmc4xxx_protect, .protect = xmc4xxx_protect,

View File

@ -1,56 +1,49 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libhelper.la
METASOURCES = AUTO %C%_libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
noinst_LTLIBRARIES = libhelper.la
CONFIGFILES = options.c time_support_common.c %C%_libhelper_la_SOURCES = \
%D%/binarybuffer.c \
libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) %D%/options.c \
%D%/time_support_common.c \
libhelper_la_SOURCES = \ %D%/configuration.c \
binarybuffer.c \ %D%/log.c \
$(CONFIGFILES) \ %D%/command.c \
configuration.c \ %D%/time_support.c \
log.c \ %D%/replacements.c \
command.c \ %D%/fileio.c \
time_support.c \ %D%/util.c \
replacements.c \ %D%/jep106.c \
fileio.c \ %D%/jim-nvp.c \
util.c \ %D%/binarybuffer.h \
jep106.c \ %D%/configuration.h \
jim-nvp.c %D%/ioutil.h \
%D%/list.h \
%D%/util.h \
%D%/types.h \
%D%/log.h \
%D%/command.h \
%D%/time_support.h \
%D%/replacements.h \
%D%/fileio.h \
%D%/system.h \
%D%/jep106.h \
%D%/jep106.inc \
%D%/jim-nvp.h
if IOUTIL if IOUTIL
libhelper_la_SOURCES += ioutil.c %C%_libhelper_la_SOURCES += %D%/ioutil.c
else else
libhelper_la_SOURCES += ioutil_stubs.c %C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c
endif endif
libhelper_la_CFLAGS = %C%_libhelper_la_CFLAGS = $(AM_CFLAGS)
if IS_MINGW if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform # FD_* macros are sloppy with their signs on MinGW32 platform
libhelper_la_CFLAGS += -Wno-sign-compare %C%_libhelper_la_CFLAGS += -Wno-sign-compare
endif endif
noinst_HEADERS = \ STARTUP_TCL_SRCS += %D%/startup.tcl
binarybuffer.h \ EXTRA_DIST += \
configuration.h \ %D%/bin2char.sh \
ioutil.h \ %D%/update_jep106.pl
list.h \
util.h \
types.h \
log.h \
command.h \
time_support.h \
replacements.h \
fileio.h \
system.h \
bin2char.sh \
jep106.h \
jep106.inc \
update_jep106.pl \
jim-nvp.h
EXTRA_DIST = startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -45,6 +45,11 @@ static const unsigned char bit_reverse_table256[] = {
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
}; };
static const char hex_digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'
};
void *buf_cpy(const void *from, void *_to, unsigned size) void *buf_cpy(const void *from, void *_to, unsigned size)
{ {
if (NULL == from || NULL == _to) if (NULL == from || NULL == _to)
@ -369,31 +374,72 @@ void bit_copy_discard(struct bit_copy_queue *q)
} }
} }
int unhexify(char *bin, const char *hex, int count) /**
* Convert a string of hexadecimal pairs into its binary
* representation.
*
* @param[out] bin Buffer to store binary representation. The buffer size must
* be at least @p count.
* @param[in] hex String with hexadecimal pairs to convert into its binary
* representation.
* @param[in] count Number of hexadecimal pairs to convert.
*
* @return The number of converted hexadecimal pairs.
*/
size_t unhexify(uint8_t *bin, const char *hex, size_t count)
{ {
int i, tmp; size_t i;
char tmp;
for (i = 0; i < count; i++) { if (!bin || !hex)
if (sscanf(hex + (2 * i), "%02x", &tmp) != 1) return 0;
return i;
bin[i] = tmp; memset(bin, 0, count);
for (i = 0; i < 2 * count; i++) {
if (hex[i] >= 'a' && hex[i] <= 'f')
tmp = hex[i] - 'a' + 10;
else if (hex[i] >= 'A' && hex[i] <= 'F')
tmp = hex[i] - 'A' + 10;
else if (hex[i] >= '0' && hex[i] <= '9')
tmp = hex[i] - '0';
else
return i / 2;
bin[i / 2] |= tmp << (4 * ((i + 1) % 2));
} }
return i; return i / 2;
} }
int hexify(char *hex, const char *bin, int count, int out_maxlen) /**
* Convert binary data into a string of hexadecimal pairs.
*
* @param[out] hex Buffer to store string of hexadecimal pairs. The buffer size
* must be at least @p length.
* @param[in] bin Buffer with binary data to convert into hexadecimal pairs.
* @param[in] count Number of bytes to convert.
* @param[in] length Maximum number of characters, including null-terminator,
* to store into @p hex.
*
* @returns The length of the converted string excluding null-terminator.
*/
size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length)
{ {
int i, cmd_len = 0; size_t i;
uint8_t tmp;
/* May use a length, or a null-terminated string as input. */ if (!length)
if (count == 0) return 0;
count = strlen(bin);
for (i = 0; i < count; i++) for (i = 0; i < length - 1 && i < 2 * count; i++) {
cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff); tmp = (bin[i / 2] >> (4 * ((i + 1) % 2))) & 0x0f;
hex[i] = hex_digits[tmp];
}
return cmd_len; hex[i] = 0;
return i;
} }
void buffer_shr(void *_buf, unsigned buf_len, unsigned count) void buffer_shr(void *_buf, unsigned buf_len, unsigned count)

View File

@ -234,8 +234,8 @@ void bit_copy_discard(struct bit_copy_queue *q);
/* functions to convert to/from hex encoded buffer /* functions to convert to/from hex encoded buffer
* used in ti-icdi driver and gdb server */ * used in ti-icdi driver and gdb server */
int unhexify(char *bin, const char *hex, int count); size_t unhexify(uint8_t *bin, const char *hex, size_t count);
int hexify(char *hex, const char *bin, int count, int out_maxlen); size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen);
void buffer_shr(void *_buf, unsigned buf_len, unsigned count); void buffer_shr(void *_buf, unsigned buf_len, unsigned count);
#endif /* OPENOCD_HELPER_BINARYBUFFER_H */ #endif /* OPENOCD_HELPER_BINARYBUFFER_H */

View File

@ -1410,6 +1410,8 @@ DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX)
DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX)
DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX) DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX)
DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX)
#define DEFINE_PARSE_LONGLONG(name, type, min, max) \ #define DEFINE_PARSE_LONGLONG(name, type, min, max) \
DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong) DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong)
DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX) DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX)

View File

@ -357,10 +357,13 @@ DECLARE_PARSE_WRAPPER(_u16, uint16_t);
DECLARE_PARSE_WRAPPER(_u8, uint8_t); DECLARE_PARSE_WRAPPER(_u8, uint8_t);
DECLARE_PARSE_WRAPPER(_int, int); DECLARE_PARSE_WRAPPER(_int, int);
DECLARE_PARSE_WRAPPER(_s64, int64_t);
DECLARE_PARSE_WRAPPER(_s32, int32_t); DECLARE_PARSE_WRAPPER(_s32, int32_t);
DECLARE_PARSE_WRAPPER(_s16, int16_t); DECLARE_PARSE_WRAPPER(_s16, int16_t);
DECLARE_PARSE_WRAPPER(_s8, int8_t); DECLARE_PARSE_WRAPPER(_s8, int8_t);
DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t);
/** /**
* @brief parses the string @a in into @a out as a @a type, or prints * @brief parses the string @a in into @a out as a @a type, or prints
* a command error and passes the error code to the caller. If an error * a command error and passes the error code to the caller. If an error
@ -382,6 +385,9 @@ DECLARE_PARSE_WRAPPER(_s8, int8_t);
} \ } \
} while (0) } while (0)
#define COMMAND_PARSE_ADDRESS(in, out) \
COMMAND_PARSE_NUMBER(target_addr, in, out)
/** /**
* Parse the string @c as a binary parameter, storing the boolean value * Parse the string @c as a binary parameter, storing the boolean value
* in @c out. The strings @c on and @c off are used to match different * in @c out. The strings @c on and @c off are used to match different

View File

@ -884,7 +884,7 @@
[7][0x01 - 1] = "Siklu Communication Ltd.", [7][0x01 - 1] = "Siklu Communication Ltd.",
[7][0x02 - 1] = "A Force Manufacturing Ltd.", [7][0x02 - 1] = "A Force Manufacturing Ltd.",
[7][0x03 - 1] = "Strontium", [7][0x03 - 1] = "Strontium",
[7][0x04 - 1] = "Abilis Systems", [7][0x04 - 1] = "ALi Corp (Abilis Systems)",
[7][0x05 - 1] = "Siglead, Inc.", [7][0x05 - 1] = "Siglead, Inc.",
[7][0x06 - 1] = "Ubicom, Inc.", [7][0x06 - 1] = "Ubicom, Inc.",
[7][0x07 - 1] = "Unifosa Corporation", [7][0x07 - 1] = "Unifosa Corporation",
@ -893,7 +893,7 @@
[7][0x0a - 1] = "Visipro.", [7][0x0a - 1] = "Visipro.",
[7][0x0b - 1] = "EKMemory", [7][0x0b - 1] = "EKMemory",
[7][0x0c - 1] = "Microelectronics Institute ZTE", [7][0x0c - 1] = "Microelectronics Institute ZTE",
[7][0x0d - 1] = "Cognovo Ltd.", [7][0x0d - 1] = "u-blox AG",
[7][0x0e - 1] = "Carry Technology Co. Ltd.", [7][0x0e - 1] = "Carry Technology Co. Ltd.",
[7][0x0f - 1] = "Nokia", [7][0x0f - 1] = "Nokia",
[7][0x10 - 1] = "King Tiger Technology", [7][0x10 - 1] = "King Tiger Technology",
@ -1101,12 +1101,12 @@
[8][0x5c - 1] = "Vitesse Enterprise Co.", [8][0x5c - 1] = "Vitesse Enterprise Co.",
[8][0x5d - 1] = "Foxtronn International Corporation", [8][0x5d - 1] = "Foxtronn International Corporation",
[8][0x5e - 1] = "Bretelon Inc.", [8][0x5e - 1] = "Bretelon Inc.",
[8][0x5f - 1] = "Zbit Semiconductor, Inc.", [8][0x5f - 1] = "Graphcore",
[8][0x60 - 1] = "Eoplex Inc", [8][0x60 - 1] = "Eoplex Inc",
[8][0x61 - 1] = "MaxLinear, Inc.", [8][0x61 - 1] = "MaxLinear, Inc.",
[8][0x62 - 1] = "ETA Devices", [8][0x62 - 1] = "ETA Devices",
[8][0x63 - 1] = "LOKI", [8][0x63 - 1] = "LOKI",
[8][0x64 - 1] = "IMS Semiconductor Co., Ltd", [8][0x64 - 1] = "IMS Electronics Co., Ltd.",
[8][0x65 - 1] = "Dosilicon Co., Ltd.", [8][0x65 - 1] = "Dosilicon Co., Ltd.",
[8][0x66 - 1] = "Dolphin Integration", [8][0x66 - 1] = "Dolphin Integration",
[8][0x67 - 1] = "Shenzhen Mic Electronics Technology", [8][0x67 - 1] = "Shenzhen Mic Electronics Technology",
@ -1116,4 +1116,41 @@
[8][0x6b - 1] = "Kingred Electronic Technology Ltd.", [8][0x6b - 1] = "Kingred Electronic Technology Ltd.",
[8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.", [8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.",
[8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.", [8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.",
[8][0x6e - 1] = "Crocus Technology Inc.",
[8][0x6f - 1] = "Creative Chips GmbH",
[8][0x70 - 1] = "GE Aviation Systems LLC.",
[8][0x71 - 1] = "Asgard",
[8][0x72 - 1] = "Good Wealth Technology Ltd.",
[8][0x73 - 1] = "TriCor Technologies",
[8][0x74 - 1] = "Nova-Systems GmbH",
[8][0x75 - 1] = "JUHOR",
[8][0x76 - 1] = "Zhuhai Douke Commerce Co. Ltd.",
[8][0x77 - 1] = "DSL Memory",
[8][0x78 - 1] = "Anvo-Systems Dresden GmbH",
[8][0x79 - 1] = "Realtek",
[8][0x7a - 1] = "AltoBeam",
[8][0x7b - 1] = "Wave Computing",
[8][0x7c - 1] = "Beijing TrustNet Technology Co. Ltd.",
[8][0x7d - 1] = "Innovium, Inc.",
[8][0x7e - 1] = "Starsway Technology Limited",
[9][0x01 - 1] = "Weltronics Co. LTD",
[9][0x02 - 1] = "VMware, Inc.",
[9][0x03 - 1] = "Hewlett Packard Enterprise",
[9][0x04 - 1] = "INTENSO",
[9][0x05 - 1] = "Puya Semiconductor",
[9][0x06 - 1] = "MEMORFI",
[9][0x07 - 1] = "MSC Technologies GmbH",
[9][0x08 - 1] = "Txrui",
[9][0x09 - 1] = "SiFive, Inc.",
[9][0x0a - 1] = "Spreadtrum Communications",
[9][0x0b - 1] = "Paragon Technology (Shenzhen) Ltd.",
[9][0x0c - 1] = "UMAX Technology",
[9][0x0d - 1] = "Shenzhen Yong Sheng Technology",
[9][0x0e - 1] = "SNOAMOO (Shenzhen Kai Zhuo Yue)",
[9][0x0f - 1] = "Daten Tecnologia LTDA",
[9][0x10 - 1] = "Shenzhen XinRuiYan Electronics",
[9][0x11 - 1] = "Eta Compute",
[9][0x12 - 1] = "Energous",
[9][0x13 - 1] = "Raspberry Pi Trading Ltd.",
[9][0x14 - 1] = "Shenzhen Chixingzhe Tech Co. Ltd.",
/* EOF */ /* EOF */

View File

@ -191,6 +191,30 @@ void log_printf(enum log_levels level,
va_end(ap); va_end(ap);
} }
void log_vprintf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, va_list args)
{
char *tmp;
count++;
if (level > debug_level)
return;
tmp = alloc_vprintf(format, args);
if (!tmp)
return;
/*
* Note: alloc_vprintf() guarantees that the buffer is at least one
* character longer.
*/
strcat(tmp, "\n");
log_puts(level, file, line, function, tmp);
free(tmp);
}
void log_printf_lf(enum log_levels level, void log_printf_lf(enum log_levels level,
const char *file, const char *file,
unsigned line, unsigned line,
@ -198,23 +222,10 @@ void log_printf_lf(enum log_levels level,
const char *format, const char *format,
...) ...)
{ {
char *string;
va_list ap; va_list ap;
count++;
if (level > debug_level)
return;
va_start(ap, format); va_start(ap, format);
log_vprintf_lf(level, file, line, function, format, ap);
string = alloc_vprintf(format, ap);
if (string != NULL) {
strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one
*char longer */
log_puts(level, file, line, function, string);
free(string);
}
va_end(ap); va_end(ap);
} }
@ -240,8 +251,14 @@ COMMAND_HANDLER(handle_log_output_command)
{ {
if (CMD_ARGC == 1) { if (CMD_ARGC == 1) {
FILE *file = fopen(CMD_ARGV[0], "w"); FILE *file = fopen(CMD_ARGV[0], "w");
if (file == NULL) {
if (file) LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]);
return ERROR_FAIL;
}
if (log_output != stderr && log_output != NULL) {
/* Close previous log file, if it was open and wasn't stderr. */
fclose(log_output);
}
log_output = file; log_output = file;
} }

View File

@ -60,6 +60,8 @@ enum log_levels {
void log_printf(enum log_levels level, const char *file, unsigned line, void log_printf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, ...) const char *function, const char *format, ...)
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
void log_vprintf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, va_list args);
void log_printf_lf(enum log_levels level, const char *file, unsigned line, void log_printf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, ...) const char *function, const char *format, ...)
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));

View File

@ -29,6 +29,15 @@
#include <getopt.h> #include <getopt.h>
#include <limits.h>
#include <stdlib.h>
#if IS_DARWIN
#include <libproc.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
static int help_flag, version_flag; static int help_flag, version_flag;
static const struct option long_options[] = { static const struct option long_options[] = {
@ -50,52 +59,129 @@ int configuration_output_handler(struct command_context *context, const char *li
return ERROR_OK; return ERROR_OK;
} }
#ifdef _WIN32 /* Return the canonical path to the directory the openocd executable is in.
static char *find_suffix(const char *text, const char *suffix) * The path should be absolute, use / as path separator and have all symlinks
* resolved. The returned string is malloc'd. */
static char *find_exe_path(void)
{ {
size_t text_len = strlen(text); char *exepath = NULL;
size_t suffix_len = strlen(suffix);
if (suffix_len == 0) do {
return (char *)text + text_len; #if IS_WIN32 && !IS_CYGWIN
exepath = malloc(MAX_PATH);
if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0) if (exepath == NULL)
return NULL; /* Not a suffix of text */ break;
GetModuleFileName(NULL, exepath, MAX_PATH);
return (char *)text + text_len - suffix_len;
}
#endif
static void add_default_dirs(void)
{
const char *run_prefix;
char *path;
#ifdef _WIN32
char strExePath[MAX_PATH];
GetModuleFileName(NULL, strExePath, MAX_PATH);
/* Strip executable file name, leaving path */
*strrchr(strExePath, '\\') = '\0';
/* Convert path separators to UNIX style, should work on Windows also. */ /* Convert path separators to UNIX style, should work on Windows also. */
for (char *p = strExePath; *p; p++) { for (char *p = exepath; *p; p++) {
if (*p == '\\') if (*p == '\\')
*p = '/'; *p = '/';
} }
char *end_of_prefix = find_suffix(strExePath, BINDIR); #elif IS_DARWIN
if (end_of_prefix != NULL) exepath = malloc(PROC_PIDPATHINFO_MAXSIZE);
*end_of_prefix = '\0'; if (exepath == NULL)
break;
if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) {
free(exepath);
exepath = NULL;
}
run_prefix = strExePath; #elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */
#else #ifndef PATH_MAX
run_prefix = ""; #define PATH_MAX 1024
#endif #endif
char *path = malloc(PATH_MAX);
if (path == NULL)
break;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t size = PATH_MAX;
if (sysctl(mib, (u_int)ARRAY_SIZE(mib), path, &size, NULL, 0) != 0)
break;
#ifdef HAVE_REALPATH
exepath = realpath(path, NULL);
free(path);
#else
exepath = path;
#endif
#elif defined(HAVE_REALPATH) /* Assume POSIX.1-2008 */
/* Try Unices in order of likelihood. */
exepath = realpath("/proc/self/exe", NULL); /* Linux/Cygwin */
if (exepath == NULL)
exepath = realpath("/proc/self/path/a.out", NULL); /* Solaris */
if (exepath == NULL)
exepath = realpath("/proc/curproc/file", NULL); /* FreeBSD (Should be covered above) */
#endif
} while (0);
if (exepath != NULL) {
/* Strip executable file name, leaving path */
*strrchr(exepath, '/') = '\0';
} else {
LOG_WARNING("Could not determine executable path, using configured BINDIR.");
LOG_DEBUG("BINDIR = %s", BINDIR);
#ifdef HAVE_REALPATH
exepath = realpath(BINDIR, NULL);
#else
exepath = strdup(BINDIR);
#endif
}
return exepath;
}
static char *find_relative_path(const char *from, const char *to)
{
size_t i;
/* Skip common /-separated parts of from and to */
i = 0;
for (size_t n = 0; from[n] == to[n]; n++) {
if (from[n] == '\0') {
i = n;
break;
}
if (from[n] == '/')
i = n + 1;
}
from += i;
to += i;
/* Count number of /-separated non-empty parts of from */
i = 0;
while (from[0] != '\0') {
if (from[0] != '/')
i++;
char *next = strchr(from, '/');
if (next == NULL)
break;
from = next + 1;
}
/* Prepend that number of ../ in front of to */
char *relpath = malloc(i * 3 + strlen(to) + 1);
relpath[0] = '\0';
for (size_t n = 0; n < i; n++)
strcat(relpath, "../");
strcat(relpath, to);
return relpath;
}
static void add_default_dirs(void)
{
char *path;
char *exepath = find_exe_path();
char *bin2data = find_relative_path(BINDIR, PKGDATADIR);
LOG_DEBUG("bindir=%s", BINDIR); LOG_DEBUG("bindir=%s", BINDIR);
LOG_DEBUG("pkgdatadir=%s", PKGDATADIR); LOG_DEBUG("pkgdatadir=%s", PKGDATADIR);
LOG_DEBUG("run_prefix=%s", run_prefix); LOG_DEBUG("exepath=%s", exepath);
LOG_DEBUG("bin2data=%s", bin2data);
/* /*
* The directory containing OpenOCD-supplied scripts should be * The directory containing OpenOCD-supplied scripts should be
@ -129,17 +215,20 @@ static void add_default_dirs(void)
} }
#endif #endif
path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site"); path = alloc_printf("%s/%s/%s", exepath, bin2data, "site");
if (path) { if (path) {
add_script_search_dir(path); add_script_search_dir(path);
free(path); free(path);
} }
path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts"); path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts");
if (path) { if (path) {
add_script_search_dir(path); add_script_search_dir(path);
free(path); free(path);
} }
free(exepath);
free(bin2data);
} }
int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
@ -178,8 +267,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
case 'd': /* --debug | -d */ case 'd': /* --debug | -d */
{ {
char *command = alloc_printf("debug_level %s", optarg ? optarg : "3"); char *command = alloc_printf("debug_level %s", optarg ? optarg : "3");
command_run_line(cmd_ctx, command); int retval = command_run_line(cmd_ctx, command);
free(command); free(command);
if (retval != ERROR_OK)
return retval;
break; break;
} }
case 'l': /* --log_output | -l */ case 'l': /* --log_output | -l */
@ -200,16 +291,26 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; " LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; "
"log_output openocd.log\"' instead."); "log_output openocd.log\"' instead.");
break; break;
default: /* '?' */
/* getopt will emit an error message, all we have to do is bail. */
return ERROR_FAIL;
} }
} }
if (optind < argc) {
/* Catch extra arguments on the command line. */
LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]);
return ERROR_FAIL;
}
if (help_flag) { if (help_flag) {
LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n"); LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n");
LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
LOG_OUTPUT("--file | -f\tuse configuration file <name>\n"); LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");
LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n");
LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); LOG_OUTPUT("--debug | -d\tset debug level to 3\n");
LOG_OUTPUT(" | -d<n>\tset debug level to <level>\n");
LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
LOG_OUTPUT("--command | -c\trun <command>\n"); LOG_OUTPUT("--command | -c\trun <command>\n");
exit(-1); exit(-1);

View File

@ -296,14 +296,21 @@ static inline int parity_u32(uint32_t x)
*/ */
#if !defined(_STDINT_H) #if !defined(_STDINT_H)
#define PRIx32 "x"
#define PRId32 "d" #define PRId32 "d"
#define SCNx32 "x"
#define PRIi32 "i" #define PRIi32 "i"
#define PRIo32 "o"
#define PRIu32 "u" #define PRIu32 "u"
#define PRIx32 "x"
#define PRIX32 "X"
#define SCNx32 "x"
#define PRId8 PRId32 #define PRId8 PRId32
#define SCNx64 "llx" #define SCNx64 "llx"
#define PRId64 "lld"
#define PRIi64 "lli"
#define PRIo64 "llo"
#define PRIu64 "llu"
#define PRIx64 "llx" #define PRIx64 "llx"
#define PRIX64 "llX"
typedef CYG_ADDRWORD intptr_t; typedef CYG_ADDRWORD intptr_t;
typedef int64_t intmax_t; typedef int64_t intmax_t;
@ -337,4 +344,23 @@ typedef uint64_t uintmax_t;
#endif #endif
#if BUILD_TARGET64
typedef uint64_t target_addr_t;
#define TARGET_ADDR_MAX UINT64_MAX
#define TARGET_PRIdADDR PRId64
#define TARGET_PRIuADDR PRIu64
#define TARGET_PRIoADDR PRIo64
#define TARGET_PRIxADDR PRIx64
#define TARGET_PRIXADDR PRIX64
#else
typedef uint32_t target_addr_t;
#define TARGET_ADDR_MAX UINT32_MAX
#define TARGET_PRIdADDR PRId32
#define TARGET_PRIuADDR PRIu32
#define TARGET_PRIoADDR PRIo32
#define TARGET_PRIxADDR PRIx32
#define TARGET_PRIXADDR PRIX32
#endif
#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR
#endif /* OPENOCD_HELPER_TYPES_H */ #endif /* OPENOCD_HELPER_TYPES_H */

View File

@ -1,86 +1,72 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libjtag.la
METASOURCES = AUTO JTAG_SRCS =
noinst_LTLIBRARIES = libjtag.la %C%_libjtag_la_LIBADD =
SUBDIRS = BUILT_SOURCES += %D%/minidriver_imp.h
DRIVERFILES = CLEANFILES += %D%/minidriver_imp.h
libjtag_la_LIBADD =
CLEANFILES =
BUILT_SOURCES =
BUILT_SOURCES += minidriver_imp.h
CLEANFILES += minidriver_imp.h
if MINIDRIVER if MINIDRIVER
if ZY1000 if ZY1000
DRIVERFILES += zy1000/zy1000.c JTAG_SRCS += %D%/zy1000/zy1000.c
JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 JTAG_MINIDRIVER_DIR = %D%/zy1000
endif endif
if MINIDRIVER_DUMMY if MINIDRIVER_DUMMY
DRIVERFILES += minidummy/minidummy.c commands.c JTAG_SRCS += %D%/minidummy/minidummy.c %D%/commands.c
JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy JTAG_MINIDRIVER_DIR = %D%/minidummy
endif endif
MINIDRIVER_IMP_DIR = $(srcdir)/minidriver MINIDRIVER_IMP_DIR = %D%/minidriver
jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h %D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h
cp $< $@ cp $< $@
BUILT_SOURCES += jtag_minidriver.h BUILT_SOURCES += %D%/jtag_minidriver.h
CLEANFILES += jtag_minidriver.h CLEANFILES += %D%/jtag_minidriver.h
else else
MINIDRIVER_IMP_DIR = $(srcdir)/drivers MINIDRIVER_IMP_DIR = %D%/drivers
DRIVERFILES += commands.c JTAG_SRCS += %D%/commands.c
if HLADAPTER if HLADAPTER
SUBDIRS += hla include %D%/hla/Makefile.am
libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la
endif endif
if AICE if AICE
SUBDIRS += aice include %D%/aice/Makefile.am
libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la
endif endif
SUBDIRS += drivers include %D%/drivers/Makefile.am
libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la
endif endif
# endif // MINIDRIVER # endif // MINIDRIVER
minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h %D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h
cp $< $@ cp $< $@
libjtag_la_SOURCES = \ %C%_libjtag_la_SOURCES = \
adapter.c \ %D%/adapter.c \
core.c \ %D%/core.c \
interface.c \ %D%/interface.c \
interfaces.c \ %D%/interfaces.c \
tcl.c \ %D%/tcl.c \
$(DRIVERFILES) %D%/commands.h \
%D%/driver.h \
%D%/interface.h \
%D%/interfaces.h \
%D%/minidriver.h \
%D%/jtag.h \
%D%/minidriver/minidriver_imp.h \
%D%/minidummy/jtag_minidriver.h \
%D%/swd.h \
%D%/tcl.h \
$(JTAG_SRCS)
noinst_HEADERS = \ STARTUP_TCL_SRCS += %D%/startup.tcl
commands.h \
driver.h \
interface.h \
interfaces.h \
minidriver.h \
jtag.h \
minidriver/minidriver_imp.h \
minidummy/jtag_minidriver.h \
swd.h \
tcl.h
EXTRA_DIST = startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -1,27 +1,14 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdaice.la
AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) %C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS)
%C%_libocdaice_la_SOURCES = \
noinst_LTLIBRARIES = libocdaice.la %D%/aice_transport.c \
%D%/aice_interface.c \
libocdaice_la_SOURCES = \ %D%/aice_port.c \
$(AICEFILES) %D%/aice_usb.c \
%D%/aice_pipe.c \
AICEFILES = %D%/aice_transport.h \
%D%/aice_interface.h \
if AICE %D%/aice_port.h \
AICEFILES += aice_transport.c %D%/aice_usb.h \
AICEFILES += aice_interface.c %D%/aice_pipe.h
AICEFILES += aice_port.c
AICEFILES += aice_usb.c
AICEFILES += aice_pipe.c
endif
noinst_HEADERS = \
aice_transport.h \
aice_interface.h \
aice_port.h \
aice_usb.h \
aice_pipe.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -786,8 +786,8 @@ static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_sel
return ERROR_FAIL; return ERROR_FAIL;
} }
static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address, static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address,
uint32_t *physical_address) target_addr_t *physical_address)
{ {
char line[AICE_PIPE_MAXLINE]; char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE];

View File

@ -180,7 +180,7 @@ struct aice_port_api_s {
int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select); int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select);
/** */ /** */
int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address); int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address);
/** */ /** */
int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address); int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address);

View File

@ -2135,10 +2135,16 @@ static int aice_usb_open(struct aice_port_param_s *param)
/* usb_set_configuration required under win32 */ /* usb_set_configuration required under win32 */
jtag_libusb_set_configuration(devh, 0); jtag_libusb_set_configuration(devh, 0);
jtag_libusb_claim_interface(devh, 0);
unsigned int aice_read_ep; unsigned int aice_read_ep;
unsigned int aice_write_ep; unsigned int aice_write_ep;
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); #ifdef HAVE_LIBUSB1
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK);
#else
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK);
#endif
LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep);
aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_read_ep = aice_read_ep;
aice_handler.usb_write_ep = aice_write_ep; aice_handler.usb_write_ep = aice_write_ep;
@ -3424,10 +3430,10 @@ static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_sele
return ERROR_OK; return ERROR_OK;
} }
static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address, static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address,
uint32_t *physical_address) target_addr_t *physical_address)
{ {
LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address); LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address);
uint32_t instructions[4]; uint32_t instructions[4];
uint32_t probe_result; uint32_t probe_result;

View File

@ -1831,11 +1831,11 @@ void jtag_set_reset_config(enum reset_types type)
int jtag_get_trst(void) int jtag_get_trst(void)
{ {
return jtag_trst; return jtag_trst == 1;
} }
int jtag_get_srst(void) int jtag_get_srst(void)
{ {
return jtag_srst; return jtag_srst == 1;
} }
void jtag_set_nsrst_delay(unsigned delay) void jtag_set_nsrst_delay(unsigned delay)

View File

@ -1,173 +1,179 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la
%C%_libocdjtagdrivers_la_LIBADD =
noinst_LTLIBRARIES = libocdjtagdrivers.la %C%_libocdjtagdrivers_la_SOURCES = \
libocdjtagdrivers_la_LIBADD = $(DRIVERFILES) \
$(DRIVERHEADERS)
libocdjtagdrivers_la_SOURCES = \ %C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS)
$(DRIVERFILES)
libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ ULINK_FIRMWARE = %D%/OpenULINK
$(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS)
ULINK_FIRMWARE = $(srcdir)/OpenULINK EXTRA_DIST += $(ULINK_FIRMWARE) \
%D%/usb_blaster/README.CheapClone \
EXTRA_DIST = $(ULINK_FIRMWARE) \ %D%/Makefile.rlink \
usb_blaster/README.CheapClone \ %D%/rlink_call.m4 \
Makefile.rlink \ %D%/rlink_init.m4
rlink_call.m4 \
rlink_init.m4
DRIVERFILES = DRIVERFILES =
SUBDIRS=
if JLINK
if INTERNAL_LIBJAYLINK
SUBDIRS += libjaylink
libjaylink_internal_la_SOURCES = jlink.c
libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la
libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \
-I$(srcdir)/libjaylink $(AM_CPPFLAGS)
noinst_LTLIBRARIES += libjaylink_internal.la
libocdjtagdrivers_la_LIBADD += libjaylink_internal.la
else
DRIVERFILES += jlink.c
endif
endif
# Standard Driver: common files # Standard Driver: common files
DRIVERFILES += driver.c DRIVERFILES += %D%/driver.c
if USE_LIBUSB1 if USE_LIBUSB1
DRIVERFILES += libusb1_common.c DRIVERFILES += %D%/libusb1_common.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
endif endif
if USE_LIBUSB0 if USE_LIBUSB0
DRIVERFILES += usb_common.c DRIVERFILES += %D%/usb_common.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS)
if !USE_LIBUSB1 if !USE_LIBUSB1
DRIVERFILES += libusb0_common.c DRIVERFILES += %D%/libusb0_common.c
endif
endif
if USE_LIBFTDI
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS)
endif
if USE_HIDAPI
%C%_libocdjtagdrivers_la_CPPFLAGS += $(HIDAPI_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(HIDAPI_LIBS)
endif
if USE_LIBJAYLINK
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBJAYLINK_LIBS)
endif
if JLINK
DRIVERFILES += %D%/jlink.c
if INTERNAL_LIBJAYLINK
SUBDIRS += %D%/libjaylink
DIST_SUBDIRS += %D%/libjaylink
%C%_libocdjtagdrivers_la_LIBADD += %D%/libjaylink/libjaylink/libjaylink.la
%C%_libocdjtagdrivers_la_CPPFLAGS += -I$(builddir)/%D%/libjaylink/libjaylink -I$(srcdir)/%D%/libjaylink
endif endif
endif endif
if BITBANG if BITBANG
DRIVERFILES += bitbang.c DRIVERFILES += %D%/bitbang.c
endif endif
if PARPORT if PARPORT
DRIVERFILES += parport.c DRIVERFILES += %D%/parport.c
endif endif
if DUMMY if DUMMY
DRIVERFILES += dummy.c DRIVERFILES += %D%/dummy.c
endif
if FT2232_DRIVER
DRIVERFILES += ft2232.c
endif endif
if FTDI if FTDI
DRIVERFILES += ftdi.c mpsse.c DRIVERFILES += %D%/ftdi.c %D%/mpsse.c
endif endif
if JTAG_VPI if JTAG_VPI
DRIVERFILES += jtag_vpi.c DRIVERFILES += %D%/jtag_vpi.c
endif endif
if USB_BLASTER_DRIVER if USB_BLASTER_DRIVER
SUBDIRS += usb_blaster %C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la
libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la include %D%/usb_blaster/Makefile.am
endif endif
if AMTJTAGACCEL if AMTJTAGACCEL
DRIVERFILES += amt_jtagaccel.c DRIVERFILES += %D%/amt_jtagaccel.c
endif endif
if EP93XX if EP93XX
DRIVERFILES += ep93xx.c DRIVERFILES += %D%/ep93xx.c
endif endif
if AT91RM9200 if AT91RM9200
DRIVERFILES += at91rm9200.c DRIVERFILES += %D%/at91rm9200.c
endif endif
if GW16012 if GW16012
DRIVERFILES += gw16012.c DRIVERFILES += %D%/gw16012.c
endif endif
if BITQ if BITQ
DRIVERFILES += bitq.c DRIVERFILES += %D%/bitq.c
endif endif
if PRESTO_DRIVER if PRESTO
DRIVERFILES += presto.c DRIVERFILES += %D%/presto.c
endif endif
if USBPROG if USBPROG
DRIVERFILES += usbprog.c DRIVERFILES += %D%/usbprog.c
endif endif
if RLINK if RLINK
DRIVERFILES += rlink.c rlink_speed_table.c DRIVERFILES += %D%/rlink.c %D%/rlink_speed_table.c
endif endif
if ULINK if ULINK
DRIVERFILES += ulink.c DRIVERFILES += %D%/ulink.c
ulinkdir = $(pkgdatadir)/OpenULINK ulinkdir = $(pkgdatadir)/OpenULINK
dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex
%C%_libocdjtagdrivers_la_LIBADD += -lm
endif endif
if VSLLINK if VSLLINK
DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c
DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c
DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoswd.c
DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtopwr.c
DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoxxx.c
DRIVERFILES += versaloon/versaloon.c DRIVERFILES += %D%/versaloon/versaloon.c
DRIVERFILES += vsllink.c DRIVERFILES += %D%/vsllink.c
endif endif
if ARMJTAGEW if ARMJTAGEW
DRIVERFILES += arm-jtag-ew.c DRIVERFILES += %D%/arm-jtag-ew.c
endif endif
if BUSPIRATE if BUSPIRATE
DRIVERFILES += buspirate.c DRIVERFILES += %D%/buspirate.c
endif endif
if REMOTE_BITBANG if REMOTE_BITBANG
DRIVERFILES += remote_bitbang.c DRIVERFILES += %D%/remote_bitbang.c
endif endif
if HLADAPTER if HLADAPTER
DRIVERFILES += stlink_usb.c DRIVERFILES += %D%/stlink_usb.c
DRIVERFILES += ti_icdi_usb.c DRIVERFILES += %D%/ti_icdi_usb.c
endif endif
if OSBDM if OSBDM
DRIVERFILES += osbdm.c DRIVERFILES += %D%/osbdm.c
endif endif
if OPENDOUS if OPENDOUS
DRIVERFILES += opendous.c DRIVERFILES += %D%/opendous.c
endif endif
if SYSFSGPIO if SYSFSGPIO
DRIVERFILES += sysfsgpio.c DRIVERFILES += %D%/sysfsgpio.c
endif endif
if BCM2835GPIO if BCM2835GPIO
DRIVERFILES += bcm2835gpio.c DRIVERFILES += %D%/bcm2835gpio.c
endif endif
if OPENJTAG if OPENJTAG
DRIVERFILES += openjtag.c DRIVERFILES += %D%/openjtag.c
endif endif
if CMSIS_DAP if CMSIS_DAP
DRIVERFILES += cmsis_dap_usb.c DRIVERFILES += %D%/cmsis_dap_usb.c
endif
if IMX_GPIO
DRIVERFILES += %D%/imx_gpio.c
endif endif
noinst_HEADERS = \ if KITPROG
bitbang.h \ DRIVERFILES += %D%/kitprog.c
bitq.h \
ftd2xx_common.h \
libusb0_common.h \
libusb1_common.h \
libusb_common.h \
minidriver_imp.h \
mpsse.h \
rlink.h \
rlink_dtc_cmd.h \
rlink_ep1_cmd.h \
rlink_st7.h \
usb_common.h \
versaloon/usbtoxxx/usbtoxxx.h \
versaloon/usbtoxxx/usbtoxxx_internal.h \
versaloon/versaloon.h \
versaloon/versaloon_include.h \
versaloon/versaloon_internal.h
DIST_SUBDIRS = usb_blaster
if INTERNAL_LIBJAYLINK
DIST_SUBDIRS += libjaylink
endif endif
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in DRIVERHEADERS = \
%D%/bitbang.h \
%D%/bitq.h \
%D%/libusb0_common.h \
%D%/libusb1_common.h \
%D%/libusb_common.h \
%D%/minidriver_imp.h \
%D%/mpsse.h \
%D%/rlink.h \
%D%/rlink_dtc_cmd.h \
%D%/rlink_ep1_cmd.h \
%D%/rlink_st7.h \
%D%/usb_common.h \
%D%/versaloon/usbtoxxx/usbtoxxx.h \
%D%/versaloon/usbtoxxx/usbtoxxx_internal.h \
%D%/versaloon/versaloon.h \
%D%/versaloon/versaloon_include.h \
%D%/versaloon/versaloon_internal.h

View File

@ -468,8 +468,8 @@ static int bcm2835gpio_init(void)
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
} }
/* set 16mA drive strength */ /* set 4mA drive strength, slew rate limited, hysteresis on */
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7; pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
tdo_gpio_mode = MODE_GPIO(tdo_gpio); tdo_gpio_mode = MODE_GPIO(tdo_gpio);
tdi_gpio_mode = MODE_GPIO(tdi_gpio); tdi_gpio_mode = MODE_GPIO(tdi_gpio);

View File

@ -118,6 +118,13 @@ static bool swd_mode;
* Bit 7: nRESET * Bit 7: nRESET
*/ */
#define SWJ_PIN_TCK (1<<0)
#define SWJ_PIN_TMS (1<<1)
#define SWJ_PIN_TDI (1<<2)
#define SWJ_PIN_TDO (1<<3)
#define SWJ_PIN_TRST (1<<5)
#define SWJ_PIN_SRST (1<<7)
/* CMSIS-DAP SWD Commands */ /* CMSIS-DAP SWD Commands */
#define CMD_DAP_SWD_CONFIGURE 0x13 #define CMD_DAP_SWD_CONFIGURE 0x13
@ -309,9 +316,11 @@ static int cmsis_dap_usb_open(void)
int packet_size = PACKET_SIZE; int packet_size = PACKET_SIZE;
/* atmel cmsis-dap uses 512 byte reports */ /* atmel cmsis-dap uses 512 byte reports */
/* except when it doesn't e.g. with mEDBG on SAMD10 Xplained
* board */
/* TODO: HID report descriptor should be parsed instead of /* TODO: HID report descriptor should be parsed instead of
* hardcoding a match by VID */ * hardcoding a match by VID */
if (target_vid == 0x03eb) if (target_vid == 0x03eb && target_pid != 0x2145)
packet_size = 512 + 1; packet_size = 512 + 1;
cmsis_dap_handle->packet_buffer = malloc(packet_size); cmsis_dap_handle->packet_buffer = malloc(packet_size);
@ -764,12 +773,12 @@ static int cmsis_dap_get_status(void)
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d", LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d",
(d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */ (d & SWJ_PIN_TCK) ? 1 : 0,
(d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */ (d & SWJ_PIN_TMS) ? 1 : 0,
(d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */ (d & SWJ_PIN_TDI) ? 1 : 0,
(d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */ (d & SWJ_PIN_TDO) ? 1 : 0,
(d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */ (d & SWJ_PIN_TRST) ? 1 : 0,
(d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */ (d & SWJ_PIN_SRST) ? 1 : 0);
} }
return retval; return retval;
@ -812,7 +821,13 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
return ERROR_FAIL; return ERROR_FAIL;
} }
return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); retval = cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s);
if (retval != ERROR_OK)
return retval;
/* Atmel EDBG needs renew clock setting after SWJ_Sequence
* otherwise default frequency is used */
return cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz());
} }
static int cmsis_dap_swd_open(void) static int cmsis_dap_swd_open(void)
@ -990,8 +1005,17 @@ static int cmsis_dap_quit(void)
static void cmsis_dap_execute_reset(struct jtag_command *cmd) static void cmsis_dap_execute_reset(struct jtag_command *cmd)
{ {
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \ /* Set both TRST and SRST even if they're not enabled as
(1 << 7), 0, NULL); * there's no way to tristate them */
uint8_t pins = 0;
if (!cmd->cmd.reset->srst)
pins |= SWJ_PIN_SRST;
if (!cmd->cmd.reset->trst)
pins |= SWJ_PIN_TRST;
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(pins,
SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
LOG_ERROR("CMSIS-DAP: Interface reset failed"); LOG_ERROR("CMSIS-DAP: Interface reset failed");
} }
@ -1475,13 +1499,11 @@ static int cmsis_dap_execute_queue(void)
static int cmsis_dap_speed(int speed) static int cmsis_dap_speed(int speed)
{ {
if (speed > DAP_MAX_CLOCK) { if (speed > DAP_MAX_CLOCK)
LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK); LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
speed = DAP_MAX_CLOCK;
}
if (speed == 0) { if (speed == 0) {
LOG_INFO("RTCK not supported"); LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
return ERROR_JTAG_NOT_IMPLEMENTED; return ERROR_JTAG_NOT_IMPLEMENTED;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
/***************************************************************************
* Copyright (C) 2011 by Spencer Oliver <spen@spen-soft.co.uk> *
* *
* Written by Arnim Laeuger, 2008 (from urjtag) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
#define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
#if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1))
#include <ftd2xx.h>
static const char *ftd2xx_status_string(FT_STATUS status)
{
switch (status) {
case FT_OK: return "OK";
case FT_INVALID_HANDLE: return "invalid handle";
case FT_DEVICE_NOT_FOUND: return "device not found";
case FT_DEVICE_NOT_OPENED: return "device not opened";
case FT_IO_ERROR: return "io error";
case FT_INSUFFICIENT_RESOURCES: return "insufficient resources";
case FT_INVALID_PARAMETER: return "invalid parameter";
case FT_INVALID_BAUD_RATE: return "invalid baud rate";
case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase";
case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write";
case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device";
case FT_EEPROM_READ_FAILED: return "eeprom read failed";
case FT_EEPROM_WRITE_FAILED: return "eeprom write failed";
case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed";
case FT_EEPROM_NOT_PRESENT: return "eeprom not present";
case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed";
case FT_INVALID_ARGS: return "invalid args";
case FT_NOT_SUPPORTED: return "not supported";
case FT_OTHER_ERROR: return "other error";
}
return "undefined FTD2xx error";
}
#endif
#endif /* OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H */

552
src/jtag/drivers/imx_gpio.c Normal file
View File

@ -0,0 +1,552 @@
/***************************************************************************
* Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com *
* *
* Based on bcm2835gpio.c *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/interface.h>
#include "bitbang.h"
#include <sys/mman.h>
#define IMX_GPIO_BASE 0x0209c000
#define IMX_GPIO_SIZE 0x00004000
#define IMX_GPIO_REGS_COUNT 8
static uint32_t imx_gpio_peri_base = IMX_GPIO_BASE;
struct imx_gpio_regs {
uint32_t dr;
uint32_t gdir;
uint32_t psr;
uint32_t icr1;
uint32_t icr2;
uint32_t imr;
uint32_t isr;
uint32_t edge_sel;
} __attribute__((aligned(IMX_GPIO_SIZE)));
static int dev_mem_fd;
static volatile struct imx_gpio_regs *pio_base;
/* GPIO setup functions */
static inline bool gpio_mode_get(int g)
{
return pio_base[g / 32].gdir >> (g & 0x1F) & 1;
}
static inline void gpio_mode_input_set(int g)
{
pio_base[g / 32].gdir &= ~(1u << (g & 0x1F));
}
static inline void gpio_mode_output_set(int g)
{
pio_base[g / 32].gdir |= (1u << (g & 0x1F));
}
static inline void gpio_mode_set(int g, int m)
{
(m) ? gpio_mode_output_set(g) : gpio_mode_input_set(g);
}
static inline void gpio_set(int g)
{
pio_base[g / 32].dr |= (1u << (g & 0x1F));
}
static inline void gpio_clear(int g)
{
pio_base[g / 32].dr &= ~(1u << (g & 0x1F));
}
static inline bool gpio_level(int g)
{
return pio_base[g / 32].dr >> (g & 0x1F) & 1;
}
static int imx_gpio_read(void);
static void imx_gpio_write(int tck, int tms, int tdi);
static void imx_gpio_reset(int trst, int srst);
static int imx_gpio_swdio_read(void);
static void imx_gpio_swdio_drive(bool is_output);
static int imx_gpio_init(void);
static int imx_gpio_quit(void);
static struct bitbang_interface imx_gpio_bitbang = {
.read = imx_gpio_read,
.write = imx_gpio_write,
.reset = imx_gpio_reset,
.swdio_read = imx_gpio_swdio_read,
.swdio_drive = imx_gpio_swdio_drive,
.blink = NULL
};
/* GPIO numbers for each signal. Negative values are invalid */
static int tck_gpio = -1;
static int tck_gpio_mode;
static int tms_gpio = -1;
static int tms_gpio_mode;
static int tdi_gpio = -1;
static int tdi_gpio_mode;
static int tdo_gpio = -1;
static int tdo_gpio_mode;
static int trst_gpio = -1;
static int trst_gpio_mode;
static int srst_gpio = -1;
static int srst_gpio_mode;
static int swclk_gpio = -1;
static int swclk_gpio_mode;
static int swdio_gpio = -1;
static int swdio_gpio_mode;
/* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted
* experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible
* to reach via memory mapped method (at least for IMX6UL@528MHz).
* Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz.
*/
static int speed_coeff = 50000;
static int speed_offset = 100;
static unsigned int jtag_delay;
static int imx_gpio_read(void)
{
return gpio_level(tdo_gpio);
}
static void imx_gpio_write(int tck, int tms, int tdi)
{
tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio);
tck ? gpio_set(tck_gpio) : gpio_clear(tck_gpio);
for (unsigned int i = 0; i < jtag_delay; i++)
asm volatile ("");
}
static void imx_gpio_swd_write(int tck, int tms, int tdi)
{
tdi ? gpio_set(swdio_gpio) : gpio_clear(swdio_gpio);
tck ? gpio_set(swclk_gpio) : gpio_clear(swclk_gpio);
for (unsigned int i = 0; i < jtag_delay; i++)
asm volatile ("");
}
/* (1) assert or (0) deassert reset lines */
static void imx_gpio_reset(int trst, int srst)
{
if (trst_gpio != -1)
trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio);
if (srst_gpio != -1)
srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio);
}
static void imx_gpio_swdio_drive(bool is_output)
{
if (is_output)
gpio_mode_output_set(swdio_gpio);
else
gpio_mode_input_set(swdio_gpio);
}
static int imx_gpio_swdio_read(void)
{
return gpio_level(swdio_gpio);
}
static int imx_gpio_khz(int khz, int *jtag_speed)
{
if (!khz) {
LOG_DEBUG("RCLK not supported");
return ERROR_FAIL;
}
*jtag_speed = speed_coeff/khz - speed_offset;
if (*jtag_speed < 0)
*jtag_speed = 0;
return ERROR_OK;
}
static int imx_gpio_speed_div(int speed, int *khz)
{
*khz = speed_coeff/(speed + speed_offset);
return ERROR_OK;
}
static int imx_gpio_speed(int speed)
{
jtag_delay = speed;
return ERROR_OK;
}
static int is_gpio_valid(int gpio)
{
return gpio >= 0 && gpio < 32 * IMX_GPIO_REGS_COUNT;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums)
{
if (CMD_ARGC == 4) {
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
} else if (CMD_ARGC != 0) {
return ERROR_COMMAND_SYNTAX_ERROR;
}
command_print(CMD_CTX,
"imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: tck = %d", tck_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: tms = %d", tms_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: tdo = %d", tdo_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: tdi = %d", tdi_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: srst = %d", srst_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
command_print(CMD_CTX, "imx_gpio GPIO config: trst = %d", trst_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_swd_gpionums)
{
if (CMD_ARGC == 2) {
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
} else if (CMD_ARGC != 0) {
return ERROR_COMMAND_SYNTAX_ERROR;
}
command_print(CMD_CTX,
"imx_gpio GPIO nums: swclk = %d, swdio = %d",
swclk_gpio, swdio_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
command_print(CMD_CTX, "imx_gpio num: swclk = %d", swclk_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
command_print(CMD_CTX, "imx_gpio num: swdio = %d", swdio_gpio);
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_speed_coeffs)
{
if (CMD_ARGC == 2) {
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
}
return ERROR_OK;
}
COMMAND_HANDLER(imx_gpio_handle_peripheral_base)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], imx_gpio_peri_base);
return ERROR_OK;
}
static const struct command_registration imx_gpio_command_handlers[] = {
{
.name = "imx_gpio_jtag_nums",
.handler = &imx_gpio_handle_jtag_gpionums,
.mode = COMMAND_CONFIG,
.help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
.usage = "(tck tms tdi tdo)* ",
},
{
.name = "imx_gpio_tck_num",
.handler = &imx_gpio_handle_jtag_gpionum_tck,
.mode = COMMAND_CONFIG,
.help = "gpio number for tck.",
},
{
.name = "imx_gpio_tms_num",
.handler = &imx_gpio_handle_jtag_gpionum_tms,
.mode = COMMAND_CONFIG,
.help = "gpio number for tms.",
},
{
.name = "imx_gpio_tdo_num",
.handler = &imx_gpio_handle_jtag_gpionum_tdo,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdo.",
},
{
.name = "imx_gpio_tdi_num",
.handler = &imx_gpio_handle_jtag_gpionum_tdi,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdi.",
},
{
.name = "imx_gpio_swd_nums",
.handler = &imx_gpio_handle_swd_gpionums,
.mode = COMMAND_CONFIG,
.help = "gpio numbers for swclk, swdio. (in that order)",
.usage = "(swclk swdio)* ",
},
{
.name = "imx_gpio_swclk_num",
.handler = &imx_gpio_handle_swd_gpionum_swclk,
.mode = COMMAND_CONFIG,
.help = "gpio number for swclk.",
},
{
.name = "imx_gpio_swdio_num",
.handler = &imx_gpio_handle_swd_gpionum_swdio,
.mode = COMMAND_CONFIG,
.help = "gpio number for swdio.",
},
{
.name = "imx_gpio_srst_num",
.handler = &imx_gpio_handle_jtag_gpionum_srst,
.mode = COMMAND_CONFIG,
.help = "gpio number for srst.",
},
{
.name = "imx_gpio_trst_num",
.handler = &imx_gpio_handle_jtag_gpionum_trst,
.mode = COMMAND_CONFIG,
.help = "gpio number for trst.",
},
{
.name = "imx_gpio_speed_coeffs",
.handler = &imx_gpio_handle_speed_coeffs,
.mode = COMMAND_CONFIG,
.help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
},
{
.name = "imx_gpio_peripheral_base",
.handler = &imx_gpio_handle_peripheral_base,
.mode = COMMAND_CONFIG,
.help = "peripheral base to access GPIOs (0x0209c000 for most IMX).",
},
COMMAND_REGISTRATION_DONE
};
static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
struct jtag_interface imx_gpio_interface = {
.name = "imx_gpio",
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
.transports = imx_gpio_transports,
.swd = &bitbang_swd,
.speed = imx_gpio_speed,
.khz = imx_gpio_khz,
.speed_div = imx_gpio_speed_div,
.commands = imx_gpio_command_handlers,
.init = imx_gpio_init,
.quit = imx_gpio_quit,
};
static bool imx_gpio_jtag_mode_possible(void)
{
if (!is_gpio_valid(tck_gpio))
return 0;
if (!is_gpio_valid(tms_gpio))
return 0;
if (!is_gpio_valid(tdi_gpio))
return 0;
if (!is_gpio_valid(tdo_gpio))
return 0;
return 1;
}
static bool imx_gpio_swd_mode_possible(void)
{
if (!is_gpio_valid(swclk_gpio))
return 0;
if (!is_gpio_valid(swdio_gpio))
return 0;
return 1;
}
static int imx_gpio_init(void)
{
bitbang_interface = &imx_gpio_bitbang;
LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver");
if (imx_gpio_jtag_mode_possible()) {
if (imx_gpio_swd_mode_possible())
LOG_INFO("JTAG and SWD modes enabled");
else
LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
} else if (imx_gpio_swd_mode_possible()) {
LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
} else {
LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
return ERROR_JTAG_INIT_FAILED;
}
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (dev_mem_fd < 0) {
perror("open");
return ERROR_JTAG_INIT_FAILED;
}
LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED, dev_mem_fd, imx_gpio_peri_base);
if (pio_base == MAP_FAILED) {
perror("mmap");
close(dev_mem_fd);
return ERROR_JTAG_INIT_FAILED;
}
/*
* Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
* as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
*/
if (imx_gpio_jtag_mode_possible()) {
tdo_gpio_mode = gpio_mode_get(tdo_gpio);
tdi_gpio_mode = gpio_mode_get(tdi_gpio);
tck_gpio_mode = gpio_mode_get(tck_gpio);
tms_gpio_mode = gpio_mode_get(tms_gpio);
gpio_clear(tdi_gpio);
gpio_clear(tck_gpio);
gpio_set(tms_gpio);
gpio_mode_input_set(tdo_gpio);
gpio_mode_output_set(tdi_gpio);
gpio_mode_output_set(tck_gpio);
gpio_mode_output_set(tms_gpio);
}
if (imx_gpio_swd_mode_possible()) {
swclk_gpio_mode = gpio_mode_get(swclk_gpio);
swdio_gpio_mode = gpio_mode_get(swdio_gpio);
gpio_clear(swdio_gpio);
gpio_clear(swclk_gpio);
gpio_mode_output_set(swclk_gpio);
gpio_mode_output_set(swdio_gpio);
}
if (trst_gpio != -1) {
trst_gpio_mode = gpio_mode_get(trst_gpio);
gpio_set(trst_gpio);
gpio_mode_output_set(trst_gpio);
}
if (srst_gpio != -1) {
srst_gpio_mode = gpio_mode_get(srst_gpio);
gpio_set(srst_gpio);
gpio_mode_output_set(srst_gpio);
}
LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
"tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
if (swd_mode) {
imx_gpio_bitbang.write = imx_gpio_swd_write;
bitbang_switch_to_swd();
}
return ERROR_OK;
}
static int imx_gpio_quit(void)
{
if (imx_gpio_jtag_mode_possible()) {
gpio_mode_set(tdo_gpio, tdo_gpio_mode);
gpio_mode_set(tdi_gpio, tdi_gpio_mode);
gpio_mode_set(tck_gpio, tck_gpio_mode);
gpio_mode_set(tms_gpio, tms_gpio_mode);
}
if (imx_gpio_swd_mode_possible()) {
gpio_mode_set(swclk_gpio, swclk_gpio_mode);
gpio_mode_set(swdio_gpio, swdio_gpio_mode);
}
if (trst_gpio != -1)
gpio_mode_set(trst_gpio, trst_gpio_mode);
if (srst_gpio != -1)
gpio_mode_set(srst_gpio, srst_gpio_mode);
return ERROR_OK;
}

View File

@ -314,12 +314,11 @@ static int jlink_execute_queue(void)
static int jlink_speed(int speed) static int jlink_speed(int speed)
{ {
int ret; int ret;
uint32_t freq; struct jaylink_speed tmp;
uint16_t divider;
int max_speed; int max_speed;
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
ret = jaylink_get_speeds(devh, &freq, &divider); ret = jaylink_get_speeds(devh, &tmp);
if (ret != JAYLINK_OK) { if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_speeds() failed: %s.", LOG_ERROR("jaylink_get_speeds() failed: %s.",
@ -327,8 +326,8 @@ static int jlink_speed(int speed)
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
freq = freq / 1000; tmp.freq /= 1000;
max_speed = freq / divider; max_speed = tmp.freq / tmp.div;
} else { } else {
max_speed = JLINK_MAX_SPEED; max_speed = JLINK_MAX_SPEED;
} }
@ -433,15 +432,16 @@ static int select_interface(void)
static int jlink_register(void) static int jlink_register(void)
{ {
int ret; int ret;
int i; size_t i;
bool handle_found; bool handle_found;
size_t count;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER))
return ERROR_OK; return ERROR_OK;
ret = jaylink_register(devh, &conn, connlist, NULL, NULL); ret = jaylink_register(devh, &conn, connlist, &count);
if (ret < 0) { if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_register() failed: %s.", LOG_ERROR("jaylink_register() failed: %s.",
jaylink_strerror_name(ret)); jaylink_strerror_name(ret));
return ERROR_FAIL; return ERROR_FAIL;
@ -449,7 +449,7 @@ static int jlink_register(void)
handle_found = false; handle_found = false;
for (i = 0; i < ret; i++) { for (i = 0; i < count; i++) {
if (connlist[i].handle == conn.handle) { if (connlist[i].handle == conn.handle) {
handle_found = true; handle_found = true;
break; break;
@ -502,6 +502,36 @@ static bool adjust_swd_buffer_size(void)
return true; return true;
} }
static int jaylink_log_handler(const struct jaylink_context *ctx,
enum jaylink_log_level level, const char *format, va_list args,
void *user_data)
{
enum log_levels tmp;
switch (level) {
case JAYLINK_LOG_LEVEL_ERROR:
tmp = LOG_LVL_ERROR;
break;
case JAYLINK_LOG_LEVEL_WARNING:
tmp = LOG_LVL_WARNING;
break;
/*
* Forward info messages to the debug output because they are more verbose
* than info messages of OpenOCD.
*/
case JAYLINK_LOG_LEVEL_INFO:
case JAYLINK_LOG_LEVEL_DEBUG:
tmp = LOG_LVL_DEBUG;
break;
default:
tmp = LOG_LVL_WARNING;
}
log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args);
return 0;
}
static int jlink_init(void) static int jlink_init(void)
{ {
int ret; int ret;
@ -515,6 +545,9 @@ static int jlink_init(void)
enum jaylink_usb_address address; enum jaylink_usb_address address;
size_t length; size_t length;
LOG_DEBUG("Using libjaylink %s (compiled with %s).",
jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING);
ret = jaylink_init(&jayctx); ret = jaylink_init(&jayctx);
if (ret != JAYLINK_OK) { if (ret != JAYLINK_OK) {
@ -523,10 +556,28 @@ static int jlink_init(void)
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
} }
ret = jaylink_get_device_list(jayctx, &devs); ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL);
if (ret < 0) { if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_device_list() failed: %s.", LOG_ERROR("jaylink_log_set_callback() failed: %s.",
jaylink_strerror_name(ret));
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
ret = jaylink_discovery_scan(jayctx, 0);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_discovery_scan() failed: %s.",
jaylink_strerror_name(ret));
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
}
ret = jaylink_get_devices(jayctx, &devs, NULL);
if (ret != JAYLINK_OK) {
LOG_ERROR("jaylink_get_devices() failed: %s.",
jaylink_strerror_name(ret)); jaylink_strerror_name(ret));
jaylink_exit(jayctx); jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
@ -576,7 +627,7 @@ static int jlink_init(void)
LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
} }
jaylink_free_device_list(devs, 1); jaylink_free_devices(devs, true);
if (!found_device) { if (!found_device) {
LOG_ERROR("No J-Link device found."); LOG_ERROR("No J-Link device found.");
@ -626,7 +677,7 @@ static int jlink_init(void)
} }
} }
jtag_command_version = JAYLINK_JTAG_V2; jtag_command_version = JAYLINK_JTAG_VERSION_2;
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) { if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) {
ret = jaylink_get_hardware_version(devh, &hwver); ret = jaylink_get_hardware_version(devh, &hwver);
@ -642,7 +693,7 @@ static int jlink_init(void)
LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor); LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor);
if (hwver.major >= 5) if (hwver.major >= 5)
jtag_command_version = JAYLINK_JTAG_V3; jtag_command_version = JAYLINK_JTAG_VERSION_3;
} }
if (iface == JAYLINK_TIF_SWD) { if (iface == JAYLINK_TIF_SWD) {
@ -685,7 +736,7 @@ static int jlink_init(void)
conn.handle = 0; conn.handle = 0;
conn.pid = 0; conn.pid = 0;
conn.hid = 0; strcpy(conn.hid, "0.0.0.0");
conn.iid = 0; conn.iid = 0;
conn.cid = 0; conn.cid = 0;
@ -729,6 +780,7 @@ static int jlink_init(void)
static int jlink_quit(void) static int jlink_quit(void)
{ {
int ret; int ret;
size_t count;
if (trace_enabled) { if (trace_enabled) {
ret = jaylink_swo_stop(devh); ret = jaylink_swo_stop(devh);
@ -739,9 +791,9 @@ static int jlink_quit(void)
} }
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) { if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) {
ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL); ret = jaylink_unregister(devh, &conn, connlist, &count);
if (ret < 0) if (ret != JAYLINK_OK)
LOG_ERROR("jaylink_unregister() failed: %s.", LOG_ERROR("jaylink_unregister() failed: %s.",
jaylink_strerror_name(ret)); jaylink_strerror_name(ret));
} }
@ -878,14 +930,22 @@ COMMAND_HANDLER(jlink_usb_command)
COMMAND_HANDLER(jlink_serial_command) COMMAND_HANDLER(jlink_serial_command)
{ {
int ret;
if (CMD_ARGC != 1) { if (CMD_ARGC != 1) {
command_print(CMD_CTX, "Need exactly one argument for jlink serial."); command_print(CMD_CTX, "Need exactly one argument for jlink serial.");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) { ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number);
if (ret == JAYLINK_ERR) {
command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]); command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]);
return ERROR_FAIL; return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.",
jaylink_strerror_name(ret));
return ERROR_FAIL;
} }
use_serial_number = true; use_serial_number = true;
@ -951,10 +1011,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
if (!CMD_ARGC) { if (!CMD_ARGC) {
switch (jtag_command_version) { switch (jtag_command_version) {
case JAYLINK_JTAG_V2: case JAYLINK_JTAG_VERSION_2:
version = 2; version = 2;
break; break;
case JAYLINK_JTAG_V3: case JAYLINK_JTAG_VERSION_3:
version = 3; version = 3;
break; break;
default: default:
@ -970,10 +1030,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
switch (tmp) { switch (tmp) {
case 2: case 2:
jtag_command_version = JAYLINK_JTAG_V2; jtag_command_version = JAYLINK_JTAG_VERSION_2;
break; break;
case 3: case 3:
jtag_command_version = JAYLINK_JTAG_V3; jtag_command_version = JAYLINK_JTAG_VERSION_3;
break; break;
default: default:
command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
@ -1545,6 +1605,125 @@ COMMAND_HANDLER(jlink_handle_config_command)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(jlink_handle_emucom_write_command)
{
int ret;
size_t tmp;
uint32_t channel;
uint32_t length;
uint8_t *buf;
size_t dummy;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) {
LOG_ERROR("Device does not support EMUCOM.");
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel);
tmp = strlen(CMD_ARGV[1]);
if (tmp % 2 != 0) {
LOG_ERROR("Data must be encoded as hexadecimal pairs.");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
buf = malloc(tmp / 2);
if (!buf) {
LOG_ERROR("Failed to allocate buffer.");
return ERROR_FAIL;
}
dummy = unhexify(buf, CMD_ARGV[1], tmp / 2);
if (dummy != (tmp / 2)) {
LOG_ERROR("Data must be encoded as hexadecimal pairs.");
free(buf);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
length = tmp / 2;
ret = jaylink_emucom_write(devh, channel, buf, &length);
free(buf);
if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) {
LOG_ERROR("Channel not supported by the device.");
return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
LOG_ERROR("Failed to write to channel: %s.",
jaylink_strerror_name(ret));
return ERROR_FAIL;
}
if (length != (tmp / 2))
LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length);
return ERROR_OK;
}
COMMAND_HANDLER(jlink_handle_emucom_read_command)
{
int ret;
uint32_t channel;
uint32_t length;
uint8_t *buf;
size_t tmp;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) {
LOG_ERROR("Device does not support EMUCOM.");
return ERROR_FAIL;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
buf = malloc(length * 3 + 1);
if (!buf) {
LOG_ERROR("Failed to allocate buffer.");
return ERROR_FAIL;
}
ret = jaylink_emucom_read(devh, channel, buf, &length);
if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) {
LOG_ERROR("Channel is not supported by the device.");
free(buf);
return ERROR_FAIL;
} else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) {
LOG_ERROR("Channel is not available for the requested amount of data. "
"%" PRIu32 " bytes are avilable.", length);
free(buf);
return ERROR_FAIL;
} else if (ret != JAYLINK_OK) {
LOG_ERROR("Failed to read from channel: %s.",
jaylink_strerror_name(ret));
free(buf);
return ERROR_FAIL;
}
tmp = hexify((char *)buf + length, buf, length, 2 * length + 1);
if (tmp != 2 * length) {
LOG_ERROR("Failed to convert data into hexadecimal string.");
free(buf);
return ERROR_FAIL;
}
command_print(CMD_CTX, "%s", buf + length);
free(buf);
return ERROR_OK;
}
static const struct command_registration jlink_config_subcommand_handlers[] = { static const struct command_registration jlink_config_subcommand_handlers[] = {
{ {
.name = "usb", .name = "usb",
@ -1590,6 +1769,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = {
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
static const struct command_registration jlink_emucom_subcommand_handlers[] = {
{
.name = "write",
.handler = &jlink_handle_emucom_write_command,
.mode = COMMAND_EXEC,
.help = "write to a channel",
.usage = "<channel> <data>",
},
{
.name = "read",
.handler = &jlink_handle_emucom_read_command,
.mode = COMMAND_EXEC,
.help = "read from a channel",
.usage = "<channel> <length>"
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration jlink_subcommand_handlers[] = { static const struct command_registration jlink_subcommand_handlers[] = {
{ {
.name = "jtag", .name = "jtag",
@ -1639,6 +1836,12 @@ static const struct command_registration jlink_subcommand_handlers[] = {
"this will show the device configuration", "this will show the device configuration",
.chain = jlink_config_subcommand_handlers, .chain = jlink_config_subcommand_handlers,
}, },
{
.name = "emucom",
.mode = COMMAND_EXEC,
.help = "access EMUCOM channel",
.chain = jlink_emucom_subcommand_handlers
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

967
src/jtag/drivers/kitprog.c Normal file
View File

@ -0,0 +1,967 @@
/***************************************************************************
* Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
* based on Dominic Rath's and Benedikt Sauter's usbprog.c *
* *
* Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk *
* *
* Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD *
* plagnioj@jcrosoft.com *
* *
* Copyright (C) 2015 by Marc Schink *
* openocd-dev@marcschink.de *
* *
* Copyright (C) 2015 by Paul Fertser *
* fercerpav@gmail.com *
* *
* Copyright (C) 2015-2017 by Forest Crossman *
* cyrozap@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h>
#include <hidapi.h>
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <jtag/commands.h>
#include "libusb_common.h"
#define VID 0x04b4
#define PID 0xf139
#define BULK_EP_IN 1
#define BULK_EP_OUT 2
#define CONTROL_TYPE_READ 0x01
#define CONTROL_TYPE_WRITE 0x02
#define CONTROL_COMMAND_PROGRAM 0x07
#define CONTROL_MODE_POLL_PROGRAMMER_STATUS 0x01
#define CONTROL_MODE_RESET_TARGET 0x04
#define CONTROL_MODE_SET_PROGRAMMER_PROTOCOL 0x40
#define CONTROL_MODE_SYNCHRONIZE_TRANSFER 0x41
#define CONTROL_MODE_ACQUIRE_SWD_TARGET 0x42
#define CONTROL_MODE_SEND_SWD_SEQUENCE 0x43
#define PROTOCOL_JTAG 0x00
#define PROTOCOL_SWD 0x01
#define DEVICE_PSOC4 0x00
#define DEVICE_PSOC3 0x01
#define DEVICE_UNKNOWN 0x02
#define DEVICE_PSOC5 0x03
#define ACQUIRE_MODE_RESET 0x00
#define ACQUIRE_MODE_POWER_CYCLE 0x01
#define SEQUENCE_LINE_RESET 0x00
#define SEQUENCE_JTAG_TO_SWD 0x01
#define PROGRAMMER_NOK_NACK 0x00
#define PROGRAMMER_OK_ACK 0x01
#define HID_TYPE_WRITE 0x00
#define HID_TYPE_READ 0x01
#define HID_TYPE_START 0x02
#define HID_COMMAND_POWER 0x80
#define HID_COMMAND_VERSION 0x81
#define HID_COMMAND_RESET 0x82
#define HID_COMMAND_CONFIGURE 0x8f
#define HID_COMMAND_BOOTLOADER 0xa0
/* 512 bytes seems to work reliably */
#define SWD_MAX_BUFFER_LENGTH 512
struct kitprog {
hid_device *hid_handle;
struct jtag_libusb_device_handle *usb_handle;
uint16_t packet_size;
uint16_t packet_index;
uint8_t *packet_buffer;
char *serial;
uint8_t hardware_version;
uint8_t minor_version;
uint8_t major_version;
uint16_t millivolts;
bool supports_jtag_to_swd;
};
struct pending_transfer_result {
uint8_t cmd;
uint32_t data;
void *buffer;
};
static char *kitprog_serial;
static bool kitprog_init_acquire_psoc;
static int pending_transfer_count, pending_queue_len;
static struct pending_transfer_result *pending_transfers;
static int queued_retval;
static struct kitprog *kitprog_handle;
static int kitprog_usb_open(void);
static void kitprog_usb_close(void);
static int kitprog_hid_command(uint8_t *command, size_t command_length,
uint8_t *data, size_t data_length);
static int kitprog_get_version(void);
static int kitprog_get_millivolts(void);
static int kitprog_get_info(void);
static int kitprog_set_protocol(uint8_t protocol);
static int kitprog_get_status(void);
static int kitprog_set_unknown(void);
static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
uint8_t max_attempts);
static int kitprog_reset_target(void);
static int kitprog_swd_sync(void);
static int kitprog_swd_seq(uint8_t seq_type);
static int kitprog_generic_acquire(void);
static int kitprog_swd_run_queue(void);
static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data);
static int kitprog_swd_switch_seq(enum swd_special_seq seq);
static inline int mm_to_version(uint8_t major, uint8_t minor)
{
return (major << 8) | minor;
}
static int kitprog_init(void)
{
int retval;
kitprog_handle = malloc(sizeof(struct kitprog));
if (kitprog_handle == NULL) {
LOG_ERROR("Failed to allocate memory");
return ERROR_FAIL;
}
if (kitprog_usb_open() != ERROR_OK) {
LOG_ERROR("Can't find a KitProg device! Please check device connections and permissions.");
return ERROR_JTAG_INIT_FAILED;
}
/* Get the current KitProg version and target voltage */
if (kitprog_get_info() != ERROR_OK)
return ERROR_FAIL;
/* Compatibility check */
kitprog_handle->supports_jtag_to_swd = true;
int kitprog_version = mm_to_version(kitprog_handle->major_version, kitprog_handle->minor_version);
if (kitprog_version < mm_to_version(2, 14)) {
LOG_WARNING("KitProg firmware versions below v2.14 do not support sending JTAG to SWD sequences. These sequences will be substituted with SWD line resets.");
kitprog_handle->supports_jtag_to_swd = false;
}
/* I have no idea what this does */
if (kitprog_set_unknown() != ERROR_OK)
return ERROR_FAIL;
/* SWD won't work unless we do this */
if (kitprog_swd_sync() != ERROR_OK)
return ERROR_FAIL;
/* Set the protocol to SWD */
if (kitprog_set_protocol(PROTOCOL_SWD) != ERROR_OK)
return ERROR_FAIL;
/* Reset the SWD bus */
if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
return ERROR_FAIL;
if (kitprog_init_acquire_psoc) {
/* Try to acquire any device that will respond */
retval = kitprog_generic_acquire();
if (retval != ERROR_OK) {
LOG_ERROR("No PSoC devices found");
return retval;
}
}
/* Allocate packet buffers and queues */
kitprog_handle->packet_size = SWD_MAX_BUFFER_LENGTH;
kitprog_handle->packet_buffer = malloc(SWD_MAX_BUFFER_LENGTH);
if (kitprog_handle->packet_buffer == NULL) {
LOG_ERROR("Failed to allocate memory for the packet buffer");
return ERROR_FAIL;
}
pending_queue_len = SWD_MAX_BUFFER_LENGTH / 5;
pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers));
if (pending_transfers == NULL) {
LOG_ERROR("Failed to allocate memory for the SWD transfer queue");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_quit(void)
{
kitprog_usb_close();
if (kitprog_handle->packet_buffer != NULL)
free(kitprog_handle->packet_buffer);
if (kitprog_handle->serial != NULL)
free(kitprog_handle->serial);
if (kitprog_handle != NULL)
free(kitprog_handle);
if (kitprog_serial != NULL)
free(kitprog_serial);
if (pending_transfers != NULL)
free(pending_transfers);
return ERROR_OK;
}
/*************** kitprog usb functions *********************/
static int kitprog_get_usb_serial(void)
{
int retval;
const uint8_t str_index = 128; /* This seems to be a constant */
char desc_string[256+1]; /* Max size of string descriptor */
retval = libusb_get_string_descriptor_ascii(kitprog_handle->usb_handle,
str_index, (unsigned char *)desc_string, sizeof(desc_string)-1);
if (retval < 0) {
LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval);
return ERROR_FAIL;
}
/* Null terminate descriptor string */
desc_string[retval] = '\0';
/* Allocate memory for the serial number */
kitprog_handle->serial = calloc(retval + 1, sizeof(char));
if (kitprog_handle->serial == NULL) {
LOG_ERROR("Failed to allocate memory for the serial number");
return ERROR_FAIL;
}
/* Store the serial number */
strncpy(kitprog_handle->serial, desc_string, retval + 1);
return ERROR_OK;
}
static int kitprog_usb_open(void)
{
const uint16_t vids[] = { VID, 0 };
const uint16_t pids[] = { PID, 0 };
if (jtag_libusb_open(vids, pids, kitprog_serial,
&kitprog_handle->usb_handle) != ERROR_OK) {
LOG_ERROR("Failed to open or find the device");
return ERROR_FAIL;
}
/* Get the serial number for the device */
if (kitprog_get_usb_serial() != ERROR_OK)
LOG_WARNING("Failed to get KitProg serial number");
/* Convert the ASCII serial number into a (wchar_t *) */
size_t len = strlen(kitprog_handle->serial);
wchar_t *hid_serial = calloc(len + 1, sizeof(wchar_t));
if (hid_serial == NULL) {
LOG_ERROR("Failed to allocate memory for the serial number");
return ERROR_FAIL;
}
if (mbstowcs(hid_serial, kitprog_handle->serial, len + 1) == (size_t)-1) {
free(hid_serial);
LOG_ERROR("Failed to convert serial number");
return ERROR_FAIL;
}
/* Use HID for the KitBridge interface */
kitprog_handle->hid_handle = hid_open(VID, PID, hid_serial);
free(hid_serial);
if (kitprog_handle->hid_handle == NULL) {
LOG_ERROR("Failed to open KitBridge (HID) interface");
return ERROR_FAIL;
}
/* Claim the KitProg Programmer (bulk transfer) interface */
if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface");
return ERROR_FAIL;
}
return ERROR_OK;
}
static void kitprog_usb_close(void)
{
if (kitprog_handle->hid_handle != NULL) {
hid_close(kitprog_handle->hid_handle);
hid_exit();
}
jtag_libusb_close(kitprog_handle->usb_handle);
}
/*************** kitprog lowlevel functions *********************/
static int kitprog_hid_command(uint8_t *command, size_t command_length,
uint8_t *data, size_t data_length)
{
int ret;
ret = hid_write(kitprog_handle->hid_handle, command, command_length);
if (ret < 0) {
LOG_DEBUG("HID write returned %i", ret);
return ERROR_FAIL;
}
ret = hid_read(kitprog_handle->hid_handle, data, data_length);
if (ret < 0) {
LOG_DEBUG("HID read returned %i", ret);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_get_version(void)
{
int ret;
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION};
unsigned char data[64];
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
if (ret != ERROR_OK)
return ret;
kitprog_handle->hardware_version = data[1];
kitprog_handle->minor_version = data[2];
kitprog_handle->major_version = data[3];
return ERROR_OK;
}
static int kitprog_get_millivolts(void)
{
int ret;
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER};
unsigned char data[64];
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
if (ret != ERROR_OK)
return ret;
kitprog_handle->millivolts = (data[4] << 8) | data[3];
return ERROR_OK;
}
static int kitprog_get_info(void)
{
/* Get the device version information */
if (kitprog_get_version() == ERROR_OK) {
LOG_INFO("KitProg v%u.%02u",
kitprog_handle->major_version, kitprog_handle->minor_version);
LOG_INFO("Hardware version: %u",
kitprog_handle->hardware_version);
} else {
LOG_ERROR("Failed to get KitProg version");
return ERROR_FAIL;
}
/* Get the current reported target voltage */
if (kitprog_get_millivolts() == ERROR_OK) {
LOG_INFO("VTARG = %u.%03u V",
kitprog_handle->millivolts / 1000, kitprog_handle->millivolts % 1000);
} else {
LOG_ERROR("Failed to get target voltage");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_set_protocol(uint8_t protocol)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM,
protocol, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_get_status(void)
{
int transferred = 0;
char status = PROGRAMMER_NOK_NACK;
/* Try a maximum of three times */
for (int i = 0; (i < 3) && (transferred == 0); i++) {
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_READ,
(CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
jtag_sleep(1000);
}
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_set_unknown(void)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(0x03 << 8) | 0x04,
0, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
uint8_t max_attempts)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_reset_target(void)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_swd_sync(void)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_swd_seq(uint8_t seq_type)
{
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM,
seq_type, &status, 1, 0);
if (transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
if (status != PROGRAMMER_OK_ACK) {
LOG_DEBUG("Programmer did not respond OK");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_generic_acquire(void)
{
const uint8_t devices[] = {DEVICE_PSOC4, DEVICE_PSOC3, DEVICE_PSOC5};
int retval;
int acquire_count = 0;
/* Due to the way the SWD port is shared between the Test Controller (TC)
* and the Cortex-M3 DAP on the PSoC 5LP, the TC is the default SWD target
* after power is applied. To access the DAP, the PSoC 5LP requires at least
* one acquisition sequence to be run (which switches the SWD mux from the
* TC to the DAP). However, after the mux is switched, the Cortex-M3 will be
* held in reset until a series of registers are written to (see section 5.2
* of the PSoC 5LP Device Programming Specifications for details).
*
* Instead of writing the registers in this function, we just do what the
* Cypress tools do and run the acquisition sequence a second time. This
* will take the Cortex-M3 out of reset and enable debugging.
*/
for (int i = 0; i < 2; i++) {
for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) {
retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3);
if (retval != ERROR_OK) {
LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]);
return retval;
}
if (kitprog_get_status() == ERROR_OK)
acquire_count++;
}
jtag_sleep(10);
}
if (acquire_count < 2)
return ERROR_FAIL;
return ERROR_OK;
}
/*************** swd wrapper functions *********************/
static int kitprog_swd_init(void)
{
return ERROR_OK;
}
static void kitprog_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
{
assert(!(cmd & SWD_CMD_RnW));
kitprog_swd_queue_cmd(cmd, NULL, value);
}
static void kitprog_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
{
assert(cmd & SWD_CMD_RnW);
kitprog_swd_queue_cmd(cmd, value, 0);
}
/*************** swd lowlevel functions ********************/
static int kitprog_swd_switch_seq(enum swd_special_seq seq)
{
switch (seq) {
case JTAG_TO_SWD:
if (kitprog_handle->supports_jtag_to_swd) {
LOG_DEBUG("JTAG to SWD");
if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK)
return ERROR_FAIL;
break;
} else {
LOG_DEBUG("JTAG to SWD not supported");
/* Fall through to fix target reset issue */
}
case LINE_RESET:
LOG_DEBUG("SWD line reset");
if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
return ERROR_FAIL;
break;
default:
LOG_ERROR("Sequence %d not supported.", seq);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int kitprog_swd_run_queue(void)
{
int ret;
size_t read_count = 0;
size_t read_index = 0;
size_t write_count = 0;
uint8_t *buffer = kitprog_handle->packet_buffer;
do {
LOG_DEBUG("Executing %d queued transactions", pending_transfer_count);
if (queued_retval != ERROR_OK) {
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
break;
}
if (!pending_transfer_count)
break;
for (int i = 0; i < pending_transfer_count; i++) {
uint8_t cmd = pending_transfers[i].cmd;
uint32_t data = pending_transfers[i].data;
/* When proper WAIT handling is implemented in the
* common SWD framework, this kludge can be
* removed. However, this might lead to minor
* performance degradation as the adapter wouldn't be
* able to automatically retry anything (because ARM
* has forgotten to implement sticky error flags
* clearing). See also comments regarding
* cmsis_dap_cmd_DAP_TFER_Configure() and
* cmsis_dap_cmd_DAP_SWD_Configure() in
* cmsis_dap_init().
*/
if (!(cmd & SWD_CMD_RnW) &&
!(cmd & SWD_CMD_APnDP) &&
(cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT &&
(data & CORUNDETECT)) {
LOG_DEBUG("refusing to enable sticky overrun detection");
data &= ~CORUNDETECT;
}
#if 0
LOG_DEBUG("%s %s reg %x %"PRIx32,
cmd & SWD_CMD_APnDP ? "AP" : "DP",
cmd & SWD_CMD_RnW ? "read" : "write",
(cmd & SWD_CMD_A32) >> 1, data);
#endif
buffer[write_count++] = (cmd | SWD_CMD_START | SWD_CMD_PARK) & ~SWD_CMD_STOP;
read_count++;
if (!(cmd & SWD_CMD_RnW)) {
buffer[write_count++] = (data) & 0xff;
buffer[write_count++] = (data >> 8) & 0xff;
buffer[write_count++] = (data >> 16) & 0xff;
buffer[write_count++] = (data >> 24) & 0xff;
} else {
read_count += 4;
}
}
ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
BULK_EP_OUT, (char *)buffer, write_count, 0);
if (ret > 0) {
queued_retval = ERROR_OK;
} else {
LOG_ERROR("Bulk write failed");
queued_retval = ERROR_FAIL;
break;
}
/* We use the maximum buffer size here because the KitProg sometimes
* doesn't like bulk reads of fewer than 62 bytes. (?!?!)
*/
ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
SWD_MAX_BUFFER_LENGTH, 0);
if (ret > 0) {
/* Handle garbage data by offsetting the initial read index */
if ((unsigned int)ret > read_count)
read_index = ret - read_count;
queued_retval = ERROR_OK;
} else {
LOG_ERROR("Bulk read failed");
queued_retval = ERROR_FAIL;
break;
}
for (int i = 0; i < pending_transfer_count; i++) {
if (pending_transfers[i].cmd & SWD_CMD_RnW) {
uint32_t data = le_to_h_u32(&buffer[read_index]);
#if 0
LOG_DEBUG("Read result: %"PRIx32, data);
#endif
if (pending_transfers[i].buffer)
*(uint32_t *)pending_transfers[i].buffer = data;
read_index += 4;
}
uint8_t ack = buffer[read_index] & 0x07;
if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) {
LOG_DEBUG("SWD ack not OK: %d %s", i,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
break;
}
read_index++;
}
} while (0);
pending_transfer_count = 0;
int retval = queued_retval;
queued_retval = ERROR_OK;
return retval;
}
static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
{
if (pending_transfer_count == pending_queue_len) {
/* Not enough room in the queue. Run the queue. */
queued_retval = kitprog_swd_run_queue();
}
if (queued_retval != ERROR_OK)
return;
pending_transfers[pending_transfer_count].data = data;
pending_transfers[pending_transfer_count].cmd = cmd;
if (cmd & SWD_CMD_RnW) {
/* Queue a read transaction */
pending_transfers[pending_transfer_count].buffer = dst;
}
pending_transfer_count++;
}
/*************** jtag lowlevel functions ********************/
static void kitprog_execute_reset(struct jtag_command *cmd)
{
int retval = ERROR_OK;
if (cmd->cmd.reset->srst == 1) {
retval = kitprog_reset_target();
/* Since the previous command also disables SWCLK output, we need to send an
* SWD bus reset command to re-enable it. For some reason, running
* kitprog_swd_seq() immediately after kitprog_reset_target() won't
* actually fix this. Instead, kitprog_swd_seq() will be run once OpenOCD
* tries to send a JTAG-to-SWD sequence, which should happen during
* swd_check_reconnect (see the JTAG_TO_SWD case in kitprog_swd_switch_seq).
*/
}
if (retval != ERROR_OK)
LOG_ERROR("KitProg: Interface reset failed");
}
static void kitprog_execute_sleep(struct jtag_command *cmd)
{
jtag_sleep(cmd->cmd.sleep->us);
}
static void kitprog_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
case JTAG_RESET:
kitprog_execute_reset(cmd);
break;
case JTAG_SLEEP:
kitprog_execute_sleep(cmd);
break;
default:
LOG_ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
}
}
static int kitprog_execute_queue(void)
{
struct jtag_command *cmd = jtag_command_queue;
while (cmd != NULL) {
kitprog_execute_command(cmd);
cmd = cmd->next;
}
return ERROR_OK;
}
COMMAND_HANDLER(kitprog_handle_info_command)
{
int retval = kitprog_get_info();
return retval;
}
COMMAND_HANDLER(kitprog_handle_acquire_psoc_command)
{
int retval = kitprog_generic_acquire();
return retval;
}
COMMAND_HANDLER(kitprog_handle_serial_command)
{
if (CMD_ARGC == 1) {
size_t len = strlen(CMD_ARGV[0]);
kitprog_serial = calloc(len + 1, sizeof(char));
if (kitprog_serial == NULL) {
LOG_ERROR("Failed to allocate memory for the serial number");
return ERROR_FAIL;
}
strncpy(kitprog_serial, CMD_ARGV[0], len + 1);
} else {
LOG_ERROR("expected exactly one argument to kitprog_serial <serial-number>");
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(kitprog_handle_init_acquire_psoc_command)
{
kitprog_init_acquire_psoc = true;
return ERROR_OK;
}
static const struct command_registration kitprog_subcommand_handlers[] = {
{
.name = "info",
.handler = &kitprog_handle_info_command,
.mode = COMMAND_EXEC,
.usage = "",
.help = "show KitProg info",
},
{
.name = "acquire_psoc",
.handler = &kitprog_handle_acquire_psoc_command,
.mode = COMMAND_EXEC,
.usage = "",
.help = "try to acquire a PSoC",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration kitprog_command_handlers[] = {
{
.name = "kitprog",
.mode = COMMAND_ANY,
.help = "perform KitProg management",
.usage = "<cmd>",
.chain = kitprog_subcommand_handlers,
},
{
.name = "kitprog_serial",
.handler = &kitprog_handle_serial_command,
.mode = COMMAND_CONFIG,
.help = "set the serial number of the adapter",
.usage = "serial_string",
},
{
.name = "kitprog_init_acquire_psoc",
.handler = &kitprog_handle_init_acquire_psoc_command,
.mode = COMMAND_CONFIG,
.help = "try to acquire a PSoC during init",
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
static const struct swd_driver kitprog_swd = {
.init = kitprog_swd_init,
.switch_seq = kitprog_swd_switch_seq,
.read_reg = kitprog_swd_read_reg,
.write_reg = kitprog_swd_write_reg,
.run = kitprog_swd_run_queue,
};
static const char * const kitprog_transports[] = { "swd", NULL };
struct jtag_interface kitprog_interface = {
.name = "kitprog",
.commands = kitprog_command_handlers,
.transports = kitprog_transports,
.swd = &kitprog_swd,
.execute_queue = kitprog_execute_queue,
.init = kitprog_init,
.quit = kitprog_quit
};

@ -1 +1 @@
Subproject commit d57dee67bc756291b7d8b51d350d1c6213e514f0 Subproject commit 699b7001d34a79c8e7064503dde1bede786fd7f0

View File

@ -146,7 +146,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep, unsigned int *usb_read_ep,
unsigned int *usb_write_ep, unsigned int *usb_write_ep,
int bclass, int subclass, int protocol) int bclass, int subclass, int protocol, int trans_type)
{ {
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
struct usb_interface *iface = udev->config->interface; struct usb_interface *iface = udev->config->interface;
@ -157,7 +157,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
for (int i = 0; i < desc->bNumEndpoints; i++) { for (int i = 0; i < desc->bNumEndpoints; i++) {
if ((bclass > 0 && desc->bInterfaceClass != bclass) || if ((bclass > 0 && desc->bInterfaceClass != bclass) ||
(subclass > 0 && desc->bInterfaceSubClass != subclass) || (subclass > 0 && desc->bInterfaceSubClass != subclass) ||
(protocol > 0 && desc->bInterfaceProtocol != protocol)) (protocol > 0 && desc->bInterfaceProtocol != protocol) ||
(trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type))
continue; continue;
uint8_t epnum = desc->endpoint[i].bEndpointAddress; uint8_t epnum = desc->endpoint[i].bEndpointAddress;

View File

@ -67,7 +67,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep, unsigned int *usb_read_ep,
unsigned int *usb_write_ep, unsigned int *usb_write_ep,
int bclass, int subclass, int protocol); int bclass, int subclass, int protocol, int trans_type);
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */ #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */

View File

@ -187,7 +187,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep, unsigned int *usb_read_ep,
unsigned int *usb_write_ep, unsigned int *usb_write_ep,
int bclass, int subclass, int protocol) int bclass, int subclass, int protocol, int trans_type)
{ {
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
const struct libusb_interface *inter; const struct libusb_interface *inter;
@ -210,6 +210,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
continue; continue;
epdesc = &interdesc->endpoint[k]; epdesc = &interdesc->endpoint[k];
if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type)
continue;
uint8_t epnum = epdesc->bEndpointAddress; uint8_t epnum = epdesc->bEndpointAddress;
bool is_input = epnum & 0x80; bool is_input = epnum & 0x80;

View File

@ -69,12 +69,13 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
* @param bclass `bInterfaceClass` to match, or -1 to ignore this field. * @param bclass `bInterfaceClass` to match, or -1 to ignore this field.
* @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field.
* @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field.
* @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field.
* @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
*/ */
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep, unsigned int *usb_read_ep,
unsigned int *usb_write_ep, unsigned int *usb_write_ep,
int bclass, int subclass, int protocol); int bclass, int subclass, int protocol, int trans_type);
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */ #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */

View File

@ -19,9 +19,9 @@
#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H #define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
#ifdef HAVE_LIBUSB1 #ifdef HAVE_LIBUSB1
#include <libusb1_common.h> #include "libusb1_common.h"
#else #else
#include <libusb0_common.h> #include "libusb0_common.h"
#endif #endif
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */ #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */

View File

@ -247,8 +247,8 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con
err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface); err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface);
if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND
&& err != LIBUSB_ERROR_NOT_SUPPORTED) { && err != LIBUSB_ERROR_NOT_SUPPORTED) {
LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err)); LOG_WARNING("libusb_detach_kernel_driver() failed with %s, trying to continue anyway",
goto error; libusb_error_name(err));
} }
err = libusb_claim_interface(ctx->usb_dev, ctx->interface); err = libusb_claim_interface(ctx->usb_dev, ctx->interface);
@ -872,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx)
libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer, libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer,
ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout); ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout);
retval = libusb_submit_transfer(write_transfer); retval = libusb_submit_transfer(write_transfer);
if (retval != LIBUSB_SUCCESS)
goto error_check;
if (ctx->read_count) { if (ctx->read_count) {
read_transfer = libusb_alloc_transfer(0); read_transfer = libusb_alloc_transfer(0);
@ -879,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx)
ctx->read_chunk_size, read_cb, &read_result, ctx->read_chunk_size, read_cb, &read_result,
ctx->usb_read_timeout); ctx->usb_read_timeout);
retval = libusb_submit_transfer(read_transfer); retval = libusb_submit_transfer(read_transfer);
if (retval != LIBUSB_SUCCESS)
goto error_check;
} }
/* Polling loop, more or less taken from libftdi */ /* Polling loop, more or less taken from libftdi */
while (!write_result.done || !read_result.done) { while (!write_result.done || !read_result.done) {
retval = libusb_handle_events(ctx->usb_ctx); struct timeval timeout_usb;
timeout_usb.tv_sec = 1;
timeout_usb.tv_usec = 0;
retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL);
keep_alive(); keep_alive();
if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) { if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED)
break;
if (retval != LIBUSB_SUCCESS) {
libusb_cancel_transfer(write_transfer); libusb_cancel_transfer(write_transfer);
if (read_transfer) if (read_transfer)
libusb_cancel_transfer(read_transfer); libusb_cancel_transfer(read_transfer);
while (!write_result.done || !read_result.done) while (!write_result.done || !read_result.done) {
if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS) retval = libusb_handle_events_timeout_completed(ctx->usb_ctx,
&timeout_usb, NULL);
if (retval != LIBUSB_SUCCESS)
break; break;
} }
} }
}
error_check:
if (retval != LIBUSB_SUCCESS) { if (retval != LIBUSB_SUCCESS) {
LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval)); LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval));
retval = ERROR_FAIL; retval = ERROR_FAIL;

View File

@ -2,6 +2,10 @@
* Driver for OpenJTAG Project (www.openjtag.org) * * Driver for OpenJTAG Project (www.openjtag.org) *
* Compatible with libftdi and ftd2xx drivers. * * Compatible with libftdi and ftd2xx drivers. *
* * * *
* Cypress CY7C65215 support *
* Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV *
* <vianney.leclement@essensium.com> *
* *
* Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> * * Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> *
* * * *
* Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> * * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> *
@ -41,7 +45,18 @@
#include <jtag/interface.h> #include <jtag/interface.h>
#include <jtag/commands.h> #include <jtag/commands.h>
#include "usb_common.h" #include "libusb_common.h"
static enum {
OPENJTAG_VARIANT_STANDARD,
OPENJTAG_VARIANT_CY7C65215,
} openjtag_variant = OPENJTAG_VARIANT_STANDARD;
static const char * const openjtag_variant_names[] = {
"standard",
"cy7c65215",
NULL
};
/* /*
* OpenJTAG-OpenOCD state conversion * OpenJTAG-OpenOCD state conversion
@ -66,19 +81,8 @@ typedef enum openjtag_tap_state {
OPENJTAG_TAP_UPDATE_IR = 15, OPENJTAG_TAP_UPDATE_IR = 15,
} openjtag_tap_state_t; } openjtag_tap_state_t;
#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1)
#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI "
"are mutually exclusive"
#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1)
#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen"
#endif
/* OPENJTAG access library includes */ /* OPENJTAG access library includes */
#if BUILD_OPENJTAG_FTD2XX == 1
#include <ftd2xx.h>
#elif BUILD_OPENJTAG_LIBFTDI == 1
#include <ftdi.h> #include <ftdi.h>
#endif
/* OpenJTAG vid/pid */ /* OpenJTAG vid/pid */
static uint16_t openjtag_vid = 0x0403; static uint16_t openjtag_vid = 0x0403;
@ -86,12 +90,7 @@ static uint16_t openjtag_pid = 0x6001;
static char *openjtag_device_desc; static char *openjtag_device_desc;
#if BUILD_OPENJTAG_FTD2XX == 1
static FT_HANDLE ftdih;
#elif BUILD_OPENJTAG_LIBFTDI == 1
static struct ftdi_context ftdic; static struct ftdi_context ftdic;
#endif
#define OPENJTAG_BUFFER_SIZE 504 #define OPENJTAG_BUFFER_SIZE 504
#define OPENJTAG_MAX_PENDING_RESULTS 256 #define OPENJTAG_MAX_PENDING_RESULTS 256
@ -112,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS]; static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
static int openjtag_scan_result_count; static int openjtag_scan_result_count;
/* Openocd usb handler */ static jtag_libusb_device_handle *usbh;
struct openocd {
struct usb_dev_handle *usb_handle; /* CY7C65215 model only */
}; #define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */
#define CY7C65215_JTAG_ENABLE 0xD0 /* bRequest: enable JTAG */
#define CY7C65215_JTAG_DISABLE 0xD1 /* bRequest: disable JTAG */
#define CY7C65215_JTAG_READ 0xD2 /* bRequest: read buffer */
#define CY7C65215_JTAG_WRITE 0xD3 /* bRequest: write buffer */
#define CY7C65215_USB_TIMEOUT 100
static const uint16_t cy7c65215_vids[] = {0x04b4, 0};
static const uint16_t cy7c65215_pids[] = {0x0007, 0};
#define CY7C65215_JTAG_CLASS 0xff
#define CY7C65215_JTAG_SUBCLASS 0x04
static unsigned int ep_in, ep_out;
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_
@ -201,26 +214,9 @@ static int8_t openjtag_get_tap_state(int8_t state)
} }
} }
static int openjtag_buf_write( static int openjtag_buf_write_standard(
uint8_t *buf, int size, uint32_t *bytes_written) uint8_t *buf, int size, uint32_t *bytes_written)
{ {
#if BUILD_OPENJTAG_FTD2XX == 1
FT_STATUS status;
DWORD dw_bytes_written;
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
#endif
status = FT_Write(ftdih, buf, size, &dw_bytes_written);
if (status != FT_OK) {
*bytes_written = dw_bytes_written;
LOG_ERROR("FT_Write returned: %u", status);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = dw_bytes_written;
return ERROR_OK;
#elif BUILD_OPENJTAG_LIBFTDI == 1
int retval; int retval;
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
@ -236,36 +232,56 @@ static int openjtag_buf_write(
*bytes_written += retval; *bytes_written += retval;
return ERROR_OK; return ERROR_OK;
#endif
} }
static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) static int openjtag_buf_write_cy7c65215(
uint8_t *buf, int size, uint32_t *bytes_written)
{ {
int ret;
#if BUILD_OPENJTAG_FTD2XX == 1
DWORD dw_bytes_read;
FT_STATUS status;
int timeout = 50;
*bytes_read = 0;
while (qty && (*bytes_read < qty) && timeout--) {
status = FT_Read(ftdih, buf + *bytes_read,
qty - *bytes_read, &dw_bytes_read);
if (status != FT_OK) {
*bytes_read = dw_bytes_read;
LOG_ERROR("FT_Read returned: %u", status);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read += dw_bytes_read;
}
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
#endif #endif
if (size == 0) {
*bytes_written = 0;
return ERROR_OK; return ERROR_OK;
#elif BUILD_OPENJTAG_LIBFTDI == 1 }
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_WRITE, size, 0,
NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("vendor command failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
}
ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("bulk write failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = ret;
return ERROR_OK;
}
static int openjtag_buf_write(
uint8_t *buf, int size, uint32_t *bytes_written)
{
switch (openjtag_variant) {
case OPENJTAG_VARIANT_CY7C65215:
return openjtag_buf_write_cy7c65215(buf, size, bytes_written);
default:
return openjtag_buf_write_standard(buf, size, bytes_written);
}
}
static int openjtag_buf_read_standard(
uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
{
int retval; int retval;
int timeout = 5; int timeout = 5;
@ -287,10 +303,53 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
#endif #endif
#endif
return ERROR_OK; return ERROR_OK;
} }
static int openjtag_buf_read_cy7c65215(
uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
{
int ret;
if (qty == 0) {
*bytes_read = 0;
goto out;
}
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_READ, qty, 0,
NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("vendor command failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
}
ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("bulk read failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read = ret;
out:
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
#endif
return ERROR_OK;
}
static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
{
switch (openjtag_variant) {
case OPENJTAG_VARIANT_CY7C65215:
return openjtag_buf_read_cy7c65215(buf, qty, bytes_read);
default:
return openjtag_buf_read_standard(buf, qty, bytes_read);
}
}
static int openjtag_sendcommand(uint8_t cmd) static int openjtag_sendcommand(uint8_t cmd)
{ {
uint32_t written; uint32_t written;
@ -335,24 +394,10 @@ static int openjtag_speed(int speed)
return ERROR_OK; return ERROR_OK;
} }
static int openjtag_init(void) static int openjtag_init_standard(void)
{ {
uint8_t latency_timer; uint8_t latency_timer;
#if BUILD_OPENJTAG_FTD2XX == 1
FT_STATUS status;
#endif
usb_tx_buf_offs = 0;
usb_rx_buf_len = 0;
openjtag_scan_result_count = 0;
#if BUILD_OPENJTAG_FTD2XX == 1
LOG_DEBUG("'openjtag' interface using FTD2XX");
#elif BUILD_OPENJTAG_LIBFTDI == 1
LOG_DEBUG("'openjtag' interface using libftdi");
#endif
/* Open by device description */ /* Open by device description */
if (openjtag_device_desc == NULL) { if (openjtag_device_desc == NULL) {
LOG_WARNING("no openjtag device description specified, " LOG_WARNING("no openjtag device description specified, "
@ -360,84 +405,6 @@ if (openjtag_device_desc == NULL) {
openjtag_device_desc = "Open JTAG Project"; openjtag_device_desc = "Open JTAG Project";
} }
#if BUILD_OPENJTAG_FTD2XX == 1
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
status = FT_SetVIDPID(openjtag_vid, openjtag_pid);
if (status != FT_OK) {
LOG_WARNING("couldn't add %4.4x:%4.4x",
openjtag_vid, openjtag_pid);
}
#endif
status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION,
&ftdih);
if (status != FT_OK) {
DWORD num_devices;
LOG_ERROR("unable to open ftdi device: %u", status);
status = FT_ListDevices(&num_devices, NULL,
FT_LIST_NUMBER_ONLY);
if (status == FT_OK) {
char **desc_array = malloc(sizeof(char *)
* (num_devices + 1));
unsigned int i;
for (i = 0; i < num_devices; i++)
desc_array[i] = malloc(64);
desc_array[num_devices] = NULL;
status = FT_ListDevices(desc_array, &num_devices,
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
if (status == FT_OK) {
LOG_ERROR("ListDevices: %u\n", num_devices);
for (i = 0; i < num_devices; i++)
LOG_ERROR("%i: %s", i, desc_array[i]);
}
for (i = 0; i < num_devices; i++)
free(desc_array[i]);
free(desc_array);
} else {
LOG_ERROR("ListDevices: NONE\n");
}
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetLatencyTimer(ftdih, 2);
if (status != FT_OK) {
LOG_ERROR("unable to set latency timer: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_GetLatencyTimer(ftdih, &latency_timer);
if (status != FT_OK) {
LOG_ERROR("unable to get latency timer: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
LOG_DEBUG("current latency timer: %i", latency_timer);
status = FT_SetBitMode(ftdih, 0x00, 0x40);
if (status != FT_OK) {
LOG_ERROR("unable to disable bit i/o mode: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetTimeouts(ftdih, 50, 0);
if (status != FT_OK) {
LOG_ERROR("unable to set timeouts: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
if (status != FT_OK) {
LOG_ERROR("unable to FT_Purge() %u", status);
return ERROR_JTAG_INIT_FAILED;
}
#elif BUILD_OPENJTAG_LIBFTDI == 1
if (ftdi_init(&ftdic) < 0) if (ftdi_init(&ftdic) < 0)
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
@ -470,38 +437,107 @@ if (openjtag_device_desc == NULL) {
ftdi_get_error_string(&ftdic)); ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
#endif
#if BUILD_OPENJTAG_FTD2XX == 1
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
if (status != FT_OK)
return ERROR_JTAG_INIT_FAILED;
#elif BUILD_OPENJTAG_LIBFTDI == 1
if (ftdi_usb_purge_buffers(&ftdic) < 0) { if (ftdi_usb_purge_buffers(&ftdic) < 0) {
LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
return ERROR_JTAG_INIT_FAILED; return ERROR_JTAG_INIT_FAILED;
} }
#endif
/* OpenJTAG speed */ return ERROR_OK;
openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ }
/* MSB */ static int openjtag_init_cy7c65215(void)
openjtag_sendcommand(0x75); {
int ret;
usbh = NULL;
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh);
if (ret != ERROR_OK) {
LOG_ERROR("unable to open cy7c65215 device");
goto err;
}
ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out,
CY7C65215_JTAG_CLASS,
CY7C65215_JTAG_SUBCLASS, -1, LIBUSB_TRANSFER_TYPE_BULK);
if (ret != ERROR_OK) {
LOG_ERROR("unable to claim JTAG interface");
goto err;
}
ret = jtag_libusb_control_transfer(usbh,
CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_ENABLE,
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("could not enable JTAG module");
goto err;
}
return ERROR_OK;
err:
if (usbh != NULL)
jtag_libusb_close(usbh);
return ERROR_JTAG_INIT_FAILED;
}
static int openjtag_init(void)
{
int ret;
usb_tx_buf_offs = 0;
usb_rx_buf_len = 0;
openjtag_scan_result_count = 0;
switch (openjtag_variant) {
case OPENJTAG_VARIANT_CY7C65215:
ret = openjtag_init_cy7c65215();
break;
default:
ret = openjtag_init_standard();
}
if (ret != ERROR_OK)
return ret;
openjtag_speed(375); /* Start at slowest adapter speed */
openjtag_sendcommand(0x75); /* MSB */
return ERROR_OK;
}
static int openjtag_quit_standard(void)
{
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
return ERROR_OK;
}
static int openjtag_quit_cy7c65215(void)
{
int ret;
ret = jtag_libusb_control_transfer(usbh,
CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_DISABLE,
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0)
LOG_WARNING("could not disable JTAG module");
jtag_libusb_close(usbh);
return ERROR_OK; return ERROR_OK;
} }
static int openjtag_quit(void) static int openjtag_quit(void)
{ {
#if BUILD_OPENJTAG_FTD2XX == 1 switch (openjtag_variant) {
FT_Close(ftdih); case OPENJTAG_VARIANT_CY7C65215:
#elif BUILD_OPENJTAG_LIBFTDI == 1 return openjtag_quit_cy7c65215();
ftdi_usb_close(&ftdic); default:
ftdi_deinit(&ftdic); return openjtag_quit_standard();
#endif }
return ERROR_OK;
} }
static void openjtag_write_tap_buffer(void) static void openjtag_write_tap_buffer(void)
@ -536,8 +572,8 @@ static int openjtag_execute_tap_queue(void)
uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer; uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
while (len) { while (len > 0) {
if (len <= 8) { if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) {
DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X", DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len)); usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
buffer[count] = usb_rx_buf[rx_offs] >> (8 - len); buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
@ -724,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd)
if (cmd->cmd.runtest->num_cycles > 16) if (cmd->cmd.runtest->num_cycles > 16)
LOG_WARNING("num_cycles > 16 on run test"); LOG_WARNING("num_cycles > 16 on run test");
if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
cmd->cmd.runtest->num_cycles) {
uint8_t command; uint8_t command;
command = 7; command = 7;
command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
openjtag_add_byte(command); openjtag_add_byte(command);
}
tap_set_end_state(end_state); tap_set_end_state(end_state);
if (tap_get_end_state() != tap_get_state()) { if (tap_get_end_state() != tap_get_state()) {
@ -816,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(openjtag_handle_variant_command)
{
if (CMD_ARGC == 1) {
const char * const *name = openjtag_variant_names;
int variant = 0;
for (; *name; name++, variant++) {
if (strcasecmp(CMD_ARGV[0], *name) == 0) {
openjtag_variant = variant;
return ERROR_OK;
}
}
LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]);
} else {
LOG_ERROR("require exactly one argument to "
"openjtag_variant <variant>");
}
return ERROR_OK;
}
static const struct command_registration openjtag_command_handlers[] = { static const struct command_registration openjtag_command_handlers[] = {
{ {
@ -825,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = {
.help = "set the USB device description of the OpenJTAG", .help = "set the USB device description of the OpenJTAG",
.usage = "description-string", .usage = "description-string",
}, },
{
.name = "openjtag_variant",
.handler = openjtag_handle_variant_command,
.mode = COMMAND_CONFIG,
.help = "set the OpenJTAG variant",
.usage = "variant-string",
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -34,14 +34,7 @@
#include "bitq.h" #include "bitq.h"
/* PRESTO access library includes */ /* PRESTO access library includes */
#if BUILD_PRESTO_FTD2XX == 1
#include <ftd2xx.h>
#include "ftd2xx_common.h"
#elif BUILD_PRESTO_LIBFTDI == 1
#include <ftdi.h> #include <ftdi.h>
#else
#error "BUG: either FTD2XX and LIBFTDI has to be used"
#endif
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@ -55,13 +48,8 @@
#define BUFFER_SIZE (64*62) #define BUFFER_SIZE (64*62)
struct presto { struct presto {
#if BUILD_PRESTO_FTD2XX == 1
FT_HANDLE handle;
FT_STATUS status;
#elif BUILD_PRESTO_LIBFTDI == 1
struct ftdi_context ftdic; struct ftdi_context ftdic;
int retval; int retval;
#endif
char serial[FT_DEVICE_SERNUM_LEN]; char serial[FT_DEVICE_SERNUM_LEN];
@ -95,15 +83,6 @@ static uint8_t presto_init_seq[] = {
static int presto_write(uint8_t *buf, uint32_t size) static int presto_write(uint8_t *buf, uint32_t size)
{ {
#if BUILD_PRESTO_FTD2XX == 1
DWORD ftbytes;
presto->status = FT_Write(presto->handle, buf, size, &ftbytes);
if (presto->status != FT_OK) {
LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status));
return ERROR_JTAG_DEVICE_ERROR;
}
#elif BUILD_PRESTO_LIBFTDI == 1
uint32_t ftbytes; uint32_t ftbytes;
presto->retval = ftdi_write_data(&presto->ftdic, buf, size); presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
if (presto->retval < 0) { if (presto->retval < 0) {
@ -111,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
ftbytes = presto->retval; ftbytes = presto->retval;
#endif
if (ftbytes != size) { if (ftbytes != size) {
LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
@ -124,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
static int presto_read(uint8_t *buf, uint32_t size) static int presto_read(uint8_t *buf, uint32_t size)
{ {
#if BUILD_PRESTO_FTD2XX == 1
DWORD ftbytes;
presto->status = FT_Read(presto->handle, buf, size, &ftbytes);
if (presto->status != FT_OK) {
LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status));
return ERROR_JTAG_DEVICE_ERROR;
}
#elif BUILD_PRESTO_LIBFTDI == 1
uint32_t ftbytes = 0; uint32_t ftbytes = 0;
struct timeval timeout, now; struct timeval timeout, now;
@ -152,7 +121,6 @@ static int presto_read(uint8_t *buf, uint32_t size)
((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
break; break;
} }
#endif
if (ftbytes != size) { if (ftbytes != size) {
/* this is just a warning, there might have been timeout when detecting PRESTO, /* this is just a warning, there might have been timeout when detecting PRESTO,
@ -165,150 +133,6 @@ static int presto_read(uint8_t *buf, uint32_t size)
return ERROR_OK; return ERROR_OK;
} }
#if BUILD_PRESTO_FTD2XX == 1
static int presto_open_ftd2xx(char *req_serial)
{
uint32_t i;
DWORD numdevs;
DWORD vidpid;
char devname[FT_DEVICE_NAME_LEN];
FT_DEVICE device;
BYTE presto_data;
DWORD ftbytes;
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID);
if (presto->status != FT_OK) {
LOG_ERROR("couldn't add PRESTO VID/PID");
exit(-1);
}
#endif
presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY);
if (presto->status != FT_OK) {
LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status));
return ERROR_JTAG_DEVICE_ERROR;
}
LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs);
for (i = 0; i < numdevs; i++) {
presto->status = FT_Open(i, &(presto->handle));
if (presto->status != FT_OK) {
/* this is not fatal, the device may be legitimately open by other process,
*hence debug message only */
LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status));
continue;
}
LOG_DEBUG("FTDI device %i open", (int)i);
presto->status = FT_GetDeviceInfo(presto->handle, &device,
&vidpid, presto->serial, devname, NULL);
if (presto->status == FT_OK) {
if (vidpid == PRESTO_VID_PID && (req_serial == NULL ||
!strcmp(presto->serial, req_serial)))
break;
} else
LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string(
presto->status));
LOG_DEBUG("FTDI device %i does not match, closing", (int)i);
FT_Close(presto->handle);
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
}
if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */
presto->status = FT_SetLatencyTimer(presto->handle, 1);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_SetTimeouts(presto->handle, 100, 0);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto_data = 0xD0;
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
/* delay between first write/read turnaround (after purge?) necessary
* under Linux for unknown reason,
* probably a bug in library threading */
usleep(100000);
presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
if (ftbytes != 1) {
LOG_DEBUG("PRESTO reset");
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_SetBitMode(presto->handle, 0x80, 1);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_SetBaudRate(presto->handle, 9600);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto_data = 0;
for (i = 0; i < 4 * 62; i++) {
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
}
usleep(100000);
presto->status = FT_SetBitMode(presto->handle, 0x00, 0);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto_data = 0xD0;
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
/* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
probably a bug in library threading */
usleep(100000);
presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
if (ftbytes != 1) {
LOG_DEBUG("PRESTO not responding");
return ERROR_JTAG_DEVICE_ERROR;
}
}
presto->status = FT_SetTimeouts(presto->handle, 0, 0);
if (presto->status != FT_OK)
return ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_Write(presto->handle, &presto_init_seq,
sizeof(presto_init_seq), &ftbytes);
if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
return ERROR_JTAG_DEVICE_ERROR;
return ERROR_OK;
}
#elif BUILD_PRESTO_LIBFTDI == 1
static int presto_open_libftdi(char *req_serial) static int presto_open_libftdi(char *req_serial)
{ {
uint8_t presto_data; uint8_t presto_data;
@ -371,7 +195,6 @@ static int presto_open_libftdi(char *req_serial)
return ERROR_OK; return ERROR_OK;
} }
#endif /* BUILD_PRESTO_LIBFTDI == 1 */
static int presto_open(char *req_serial) static int presto_open(char *req_serial)
{ {
@ -391,11 +214,7 @@ static int presto_open(char *req_serial)
presto->jtag_speed = 0; presto->jtag_speed = 0;
#if BUILD_PRESTO_FTD2XX == 1
return presto_open_ftd2xx(req_serial);
#elif BUILD_PRESTO_LIBFTDI == 1
return presto_open_libftdi(req_serial); return presto_open_libftdi(req_serial);
#endif
} }
static int presto_close(void) static int presto_close(void)
@ -403,35 +222,6 @@ static int presto_close(void)
int result = ERROR_OK; int result = ERROR_OK;
#if BUILD_PRESTO_FTD2XX == 1
DWORD ftbytes;
if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
return result;
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
if (presto->status != FT_OK)
result = ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_Write(presto->handle,
&presto_init_seq,
sizeof(presto_init_seq),
&ftbytes);
if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
result = ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_SetLatencyTimer(presto->handle, 16);
if (presto->status != FT_OK)
result = ERROR_JTAG_DEVICE_ERROR;
presto->status = FT_Close(presto->handle);
if (presto->status != FT_OK)
result = ERROR_JTAG_DEVICE_ERROR;
else
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
#elif BUILD_PRESTO_LIBFTDI == 1
presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq)); presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
if (presto->retval != sizeof(presto_init_seq)) if (presto->retval != sizeof(presto_init_seq))
result = ERROR_JTAG_DEVICE_ERROR; result = ERROR_JTAG_DEVICE_ERROR;
@ -445,7 +235,6 @@ static int presto_close(void)
result = ERROR_JTAG_DEVICE_ERROR; result = ERROR_JTAG_DEVICE_ERROR;
else else
ftdi_deinit(&presto->ftdic); ftdi_deinit(&presto->ftdic);
#endif
return result; return result;
} }
@ -455,11 +244,7 @@ static int presto_flush(void)
if (presto->buff_out_pos == 0) if (presto->buff_out_pos == 0)
return ERROR_OK; return ERROR_OK;
#if BUILD_PRESTO_FTD2XX == 1
if (presto->status != FT_OK) {
#elif BUILD_PRESTO_LIBFTDI == 1
if (presto->retval < 0) { if (presto->retval < 0) {
#endif
LOG_DEBUG("error in previous communication, canceling I/O operation"); LOG_DEBUG("error in previous communication, canceling I/O operation");
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
@ -502,13 +287,9 @@ static int presto_sendbyte(int data)
} else } else
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
#if BUILD_PRESTO_FTD2XX == 1
if (presto->buff_out_pos >= BUFFER_SIZE)
#elif BUILD_PRESTO_LIBFTDI == 1
/* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
*bytes only!) */ *bytes only!) */
if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128) if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
#endif
return presto_flush(); return presto_flush();
return ERROR_OK; return ERROR_OK;

View File

@ -216,7 +216,7 @@ struct stlink_usb_handle_s {
#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01
#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
#define STLINK_TRACE_SIZE 1024 #define STLINK_TRACE_SIZE 4096
#define STLINK_TRACE_MAX_HZ 2000000 #define STLINK_TRACE_MAX_HZ 2000000
#define STLINK_TRACE_MIN_VERSION 13 #define STLINK_TRACE_MIN_VERSION 13

View File

@ -242,7 +242,8 @@ static int icdi_send_remote_cmd(void *handle, const char *data)
struct icdi_usb_handle_s *h = handle; struct icdi_usb_handle_s *h = handle;
size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,");
cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len); cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data,
strlen(data), h->max_packet - cmd_len);
return icdi_send_packet(handle, cmd_len); return icdi_send_packet(handle, cmd_len);
} }
@ -266,7 +267,7 @@ static int icdi_get_cmd_result(void *handle)
if (h->read_buffer[offset] == 'E') { if (h->read_buffer[offset] == 'E') {
/* get error code */ /* get error code */
char result; uint8_t result;
if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1) if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1)
return ERROR_FAIL; return ERROR_FAIL;
return result; return result;
@ -328,7 +329,7 @@ static int icdi_usb_version(void *handle)
} }
/* convert reply */ /* convert reply */
if (unhexify(version, h->read_buffer + 2, 4) != 4) { if (unhexify((uint8_t *)version, h->read_buffer + 2, 4) != 4) {
LOG_WARNING("unable to get ICDI version"); LOG_WARNING("unable to get ICDI version");
return ERROR_OK; return ERROR_OK;
} }
@ -495,7 +496,7 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val)
/* convert result */ /* convert result */
uint8_t buf[4]; uint8_t buf[4];
if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) { if (unhexify(buf, h->read_buffer + 2, 4) != 4) {
LOG_ERROR("failed to convert result"); LOG_ERROR("failed to convert result");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -512,7 +513,7 @@ static int icdi_usb_write_reg(void *handle, int num, uint32_t val)
h_u32_to_le(buf, val); h_u32_to_le(buf, val);
int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num);
hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd)); hexify(cmd + cmd_len, buf, 4, sizeof(cmd));
result = icdi_send_cmd(handle, cmd); result = icdi_send_cmd(handle, cmd);
if (result != ERROR_OK) if (result != ERROR_OK)

View File

@ -2066,7 +2066,7 @@ static int ulink_khz(int khz, int *jtag_speed)
} }
#ifdef _DEBUG_JTAG_IO_ #ifdef _DEBUG_JTAG_IO_
long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io; long f_tck = 0, f_tms = 0, f_scan_in = 0, f_scan_out = 0, f_scan_io = 0;
ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck, ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck,
&f_tck); &f_tck);

View File

@ -1,24 +1,13 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdusbblaster.la
%C%_libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC)
%C%_libocdusbblaster_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS)
AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) USB_BLASTER_SRC = %D%/usb_blaster.c %D%/ublast_access.h
noinst_LTLIBRARIES = libocdusbblaster.la if USB_BLASTER
libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) USB_BLASTER_SRC += %D%/ublast_access_ftdi.c
USB_BLASTER_SRC = usb_blaster.c
if USB_BLASTER_LIBFTDI
USB_BLASTER_SRC += ublast_access_ftdi.c
endif
if USB_BLASTER_FTD2XX
USB_BLASTER_SRC += ublast_access_ftd2xx.c
endif endif
if USB_BLASTER_2 if USB_BLASTER_2
USB_BLASTER_SRC += ublast2_access_libusb.c USB_BLASTER_SRC += %D%/ublast2_access_libusb.c
endif endif
noinst_HEADERS = ublast_access.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@ -56,19 +56,16 @@ struct ublast_lowlevel {
/** /**
* ublast_register_ftdi - get a lowlevel USB Blaster driver * ublast_register_ftdi - get a lowlevel USB Blaster driver
* ublast_register_ftd2xx - get a lowlevel USB Blaster driver
* ublast2_register_libusb - get a lowlevel USB Blaster II driver * ublast2_register_libusb - get a lowlevel USB Blaster II driver
* *
* Get a lowlevel USB-Blaster driver. In the current implementation, there are 3 * Get a lowlevel USB-Blaster driver. In the current implementation, there are 2
* possible lowlevel drivers : * possible lowlevel drivers :
* - one based on libftdi from ftdichip.com * - one based on libftdi,
* - one based on libftdxx, the free alternative
* - one based on libusb, specific to the USB-Blaster II * - one based on libusb, specific to the USB-Blaster II
* *
* Returns the lowlevel driver structure. * Returns the lowlevel driver structure.
*/ */
extern struct ublast_lowlevel *ublast_register_ftdi(void); extern struct ublast_lowlevel *ublast_register_ftdi(void);
extern struct ublast_lowlevel *ublast_register_ftd2xx(void);
extern struct ublast_lowlevel *ublast2_register_libusb(void); extern struct ublast_lowlevel *ublast2_register_libusb(void);
#endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */ #endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */

View File

@ -1,180 +0,0 @@
/*
* Driver for USB-JTAG, Altera USB-Blaster and compatibles
*
* Inspired from original code from Kolja Waschk's USB-JTAG project
* (http://www.ixo.de/info/usb_jtag/), and from openocd project.
*
* Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
* Copyright (C) 2011 Ali Lown ali@lown.me.uk
* Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
* Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <jtag/interface.h>
#include <jtag/commands.h>
#include "ublast_access.h"
#include <ftd2xx.h>
#include "jtag/drivers/ftd2xx_common.h"
static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low)
{
return low->priv;
}
static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
uint32_t *bytes_written)
{
FT_STATUS status;
DWORD dw_bytes_written;
FT_HANDLE *ftdih = ublast_getftdih(low);
status = FT_Write(*ftdih, buf, size, &dw_bytes_written);
if (status != FT_OK) {
*bytes_written = dw_bytes_written;
LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = dw_bytes_written;
return ERROR_OK;
}
static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf,
unsigned size, uint32_t *bytes_read)
{
DWORD dw_bytes_read;
FT_STATUS status;
FT_HANDLE *ftdih = ublast_getftdih(low);
status = FT_Read(*ftdih, buf, size, &dw_bytes_read);
if (status != FT_OK) {
*bytes_read = dw_bytes_read;
LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read = dw_bytes_read;
return ERROR_OK;
}
static int ublast_ftd2xx_init(struct ublast_lowlevel *low)
{
FT_STATUS status;
FT_HANDLE *ftdih = ublast_getftdih(low);
uint8_t latency_timer;
LOG_INFO("usb blaster interface using FTD2XX");
/* Open by device description */
if (low->ublast_device_desc == NULL) {
LOG_WARNING("no usb blaster device description specified, "
"using default 'USB-Blaster'");
low->ublast_device_desc = "USB-Blaster";
}
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid);
if (status != FT_OK) {
LOG_WARNING("couldn't add %4.4x:%4.4x",
low->ublast_vid, low->ublast_pid);
}
#endif
status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION,
ftdih);
if (status != FT_OK) {
DWORD num_devices;
LOG_ERROR("unable to open ftdi device: %s",
ftd2xx_status_string(status));
status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
if (status == FT_OK) {
char **desc_array =
malloc(sizeof(char *) * (num_devices + 1));
unsigned int i;
for (i = 0; i < num_devices; i++)
desc_array[i] = malloc(64);
desc_array[num_devices] = NULL;
status = FT_ListDevices(desc_array, &num_devices,
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
if (status == FT_OK) {
LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
for (i = 0; i < num_devices; i++)
LOG_ERROR("%i: %s", i, desc_array[i]);
}
for (i = 0; i < num_devices; i++)
free(desc_array[i]);
free(desc_array);
} else {
printf("ListDevices: NONE\n");
}
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetLatencyTimer(*ftdih, 2);
if (status != FT_OK) {
LOG_ERROR("unable to set latency timer: %s",
ftd2xx_status_string(status));
return ERROR_JTAG_INIT_FAILED;
}
status = FT_GetLatencyTimer(*ftdih, &latency_timer);
if (status != FT_OK)
LOG_ERROR("unable to get latency timer: %s",
ftd2xx_status_string(status));
else
LOG_DEBUG("current latency timer: %i", latency_timer);
status = FT_SetBitMode(*ftdih, 0x00, 0);
if (status != FT_OK) {
LOG_ERROR("unable to disable bit i/o mode: %s",
ftd2xx_status_string(status));
return ERROR_JTAG_INIT_FAILED;
}
return ERROR_OK;
}
static int ublast_ftd2xx_quit(struct ublast_lowlevel *low)
{
FT_HANDLE *ftdih = ublast_getftdih(low);
FT_Close(*ftdih);
return ERROR_OK;
}
static struct ublast_lowlevel_priv {
FT_HANDLE ftdih;
} info;
static struct ublast_lowlevel low = {
.open = ublast_ftd2xx_init,
.close = ublast_ftd2xx_quit,
.read = ublast_ftd2xx_read,
.write = ublast_ftd2xx_write,
.priv = &info,
};
struct ublast_lowlevel *ublast_register_ftd2xx(void)
{
return &low;
}

View File

@ -147,12 +147,9 @@ struct drvs_map {
}; };
static struct drvs_map lowlevel_drivers_map[] = { static struct drvs_map lowlevel_drivers_map[] = {
#if BUILD_USB_BLASTER_LIBFTDI #if BUILD_USB_BLASTER
{ .name = "ftdi", .drv_register = ublast_register_ftdi }, { .name = "ftdi", .drv_register = ublast_register_ftdi },
#endif #endif
#if BUILD_USB_BLASTER_FTD2XX
{ .name = "ftd2xx", .drv_register = ublast_register_ftd2xx },
#endif
#if BUILD_USB_BLASTER_2 #if BUILD_USB_BLASTER_2
{ .name = "ublast2", .drv_register = ublast2_register_libusb }, { .name = "ublast2", .drv_register = ublast2_register_libusb },
#endif #endif
@ -1048,8 +1045,8 @@ static const struct command_registration ublast_command_handlers[] = {
.name = "usb_blaster_lowlevel_driver", .name = "usb_blaster_lowlevel_driver",
.handler = ublast_handle_lowlevel_drv_command, .handler = ublast_handle_lowlevel_drv_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)", .help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)",
.usage = "(ftdi|ftd2xx|ublast2)", .usage = "(ftdi|ublast2)",
}, },
{ {
.name = "usb_blaster_pin", .name = "usb_blaster_pin",

View File

@ -1,23 +1,11 @@
include $(top_srcdir)/common.mk noinst_LTLIBRARIES += %D%/libocdhla.la
noinst_LTLIBRARIES = libocdhla.la %C%_libocdhla_la_SOURCES = \
%D%/hla_transport.c \
libocdhla_la_SOURCES = \ %D%/hla_tcl.c \
$(HLFILES) %D%/hla_interface.c \
%D%/hla_layout.c \
HLFILES = %D%/hla_transport.h \
%D%/hla_interface.h \
if HLADAPTER %D%/hla_layout.h \
HLFILES += hla_transport.c %D%/hla_tcl.h
HLFILES += hla_tcl.c
HLFILES += hla_interface.c
HLFILES += hla_layout.c
endif
noinst_HEADERS = \
hla_interface.h \
hla_layout.h \
hla_tcl.h \
hla_transport.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

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