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
commit
845c2f6b69
|
@ -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
|
||||||
|
|
||||||
|
|
70
Makefile.am
70
Makefile.am
|
@ -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
|
||||||
|
|
|
@ -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
55
README
|
@ -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
3
TODO
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 ...."
|
||||||
|
|
12
common.mk
12
common.mk
|
@ -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
|
|
1136
configure.ac
1136
configure.ac
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
|
@ -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"
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
204
doc/INSTALL.txt
204
doc/INSTALL.txt
|
@ -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.
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
423
doc/openocd.texi
423
doc/openocd.texi
|
@ -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?
|
||||||
|
|
129
src/Makefile.am
129
src/Makefile.am
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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__);
|
/* Access through AHB is stalled while flash is being programmed */
|
||||||
goto free_pb;
|
usleep(200);
|
||||||
}
|
|
||||||
|
res = samd_check_error(bank->target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Access through AHB is stalled while flash is being programmed */
|
if (res != ERROR_OK) {
|
||||||
usleep(200);
|
|
||||||
|
|
||||||
if (samd_check_error(bank->target)) {
|
|
||||||
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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */
|
init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* address */
|
||||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */
|
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* word count */
|
||||||
init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
|
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
|
||||||
|
init_reg_param(®_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);
|
||||||
LOG_ERROR("Error executing kinetis Flash programming algorithm");
|
if (retval == ERROR_OK) {
|
||||||
retval = ERROR_FLASH_OPERATION_FAILED;
|
retval = kinetis_ftfx_decode_error(fstat);
|
||||||
break;
|
|
||||||
|
/* reset error flags */
|
||||||
|
target_write_u8(target, FTFx_FSTAT, 0x70);
|
||||||
}
|
}
|
||||||
|
} else if (retval != ERROR_OK)
|
||||||
buffer += thisrun_count * 4;
|
LOG_ERROR("Error executing kinetis Flash programming algorithm");
|
||||||
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(®_params[0]);
|
destroy_reg_param(®_params[0]);
|
||||||
destroy_reg_param(®_params[1]);
|
destroy_reg_param(®_params[1]);
|
||||||
destroy_reg_param(®_params[2]);
|
destroy_reg_param(®_params[2]);
|
||||||
|
destroy_reg_param(®_params[3]);
|
||||||
|
destroy_reg_param(®_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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,43 +670,46 @@ 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) {
|
||||||
LOG_ERROR("Couldn't read code page size");
|
LOG_ERROR("Couldn't read code page size");
|
||||||
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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,32 +897,21 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct stm32lx_part_info *info = stm32lx_info->part_info;
|
for (unsigned int i = 0; i < info->num_revs; i++)
|
||||||
|
if (rev_id == info->revs[i].rev)
|
||||||
|
rev_str = info->revs[i].str;
|
||||||
|
|
||||||
if (info) {
|
if (rev_str != NULL) {
|
||||||
const char *rev_str = NULL;
|
snprintf(buf, buf_size,
|
||||||
uint16_t rev_id = stm32lx_info->idcode >> 16;
|
"%s - Rev: %s",
|
||||||
|
info->device_str, rev_str);
|
||||||
for (unsigned int i = 0; i < info->num_revs; i++)
|
|
||||||
if (rev_id == info->revs[i].rev)
|
|
||||||
rev_str = info->revs[i].str;
|
|
||||||
|
|
||||||
if (rev_str != NULL) {
|
|
||||||
snprintf(buf, buf_size,
|
|
||||||
"%s - Rev: %s",
|
|
||||||
stm32lx_info->part_info->device_str, rev_str);
|
|
||||||
} else {
|
|
||||||
snprintf(buf, buf_size,
|
|
||||||
"%s - Rev: unknown (0x%04x)",
|
|
||||||
stm32lx_info->part_info->device_str, rev_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, buf_size, "Cannot identify target as a STM32Lx");
|
snprintf(buf, buf_size,
|
||||||
|
"%s - Rev: unknown (0x%04x)",
|
||||||
return ERROR_FAIL;
|
info->device_str, rev_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,7 +718,16 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
offset = 0;
|
||||||
|
|
||||||
|
if (CMD_ARGC > 2)
|
||||||
|
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) {
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(®_params[0], "r0", 32, PARAM_OUT);
|
|
||||||
buf_set_u32(reg_params[0].value, 0, 32, address);
|
|
||||||
|
|
||||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
|
||||||
buf_set_u32(reg_params[1].value, 0, 32, count);
|
|
||||||
|
|
||||||
init_reg_param(®_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(®_params[0]);
|
|
||||||
destroy_reg_param(®_params[1]);
|
|
||||||
destroy_reg_param(®_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,
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,9 +251,15 @@ 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]);
|
||||||
log_output = file;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -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)));
|
||||||
|
|
|
@ -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 (exepath == NULL)
|
||||||
|
break;
|
||||||
|
GetModuleFileName(NULL, exepath, MAX_PATH);
|
||||||
|
|
||||||
if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0)
|
/* Convert path separators to UNIX style, should work on Windows also. */
|
||||||
return NULL; /* Not a suffix of text */
|
for (char *p = exepath; *p; p++) {
|
||||||
|
if (*p == '\\')
|
||||||
|
*p = '/';
|
||||||
|
}
|
||||||
|
|
||||||
return (char *)text + text_len - suffix_len;
|
#elif IS_DARWIN
|
||||||
}
|
exepath = malloc(PROC_PIDPATHINFO_MAXSIZE);
|
||||||
|
if (exepath == NULL)
|
||||||
|
break;
|
||||||
|
if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) {
|
||||||
|
free(exepath);
|
||||||
|
exepath = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#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)
|
static void add_default_dirs(void)
|
||||||
{
|
{
|
||||||
const char *run_prefix;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
char *exepath = find_exe_path();
|
||||||
#ifdef _WIN32
|
char *bin2data = find_relative_path(BINDIR, PKGDATADIR);
|
||||||
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. */
|
|
||||||
for (char *p = strExePath; *p; p++) {
|
|
||||||
if (*p == '\\')
|
|
||||||
*p = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
char *end_of_prefix = find_suffix(strExePath, BINDIR);
|
|
||||||
if (end_of_prefix != NULL)
|
|
||||||
*end_of_prefix = '\0';
|
|
||||||
|
|
||||||
run_prefix = strExePath;
|
|
||||||
#else
|
|
||||||
run_prefix = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
@ -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 */
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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, ÷r);
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return ERROR_OK;
|
||||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
}
|
||||||
|
|
||||||
|
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,109 +394,17 @@ 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
|
/* Open by device description */
|
||||||
FT_STATUS status;
|
if (openjtag_device_desc == NULL) {
|
||||||
#endif
|
LOG_WARNING("no openjtag device description specified, "
|
||||||
|
|
||||||
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 */
|
|
||||||
if (openjtag_device_desc == NULL) {
|
|
||||||
LOG_WARNING("no openjtag device description specified, "
|
|
||||||
"using default 'Open JTAG Project'");
|
"using default 'Open JTAG Project'");
|
||||||
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");
|
||||||
|
|
||||||
uint8_t command;
|
if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
|
||||||
command = 7;
|
cmd->cmd.runtest->num_cycles) {
|
||||||
command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
|
uint8_t command;
|
||||||
|
command = 7;
|
||||||
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue