Skip to content

Commit 83e0293

Browse files
Richard Pasektom-van
authored andcommitted
Add Linux SPI device SWD adapter support
To alleviate the need to bitbang SWD, I've written a SWD SPI implementation. This code is inspired by the work of [email protected] as shown at github.com/lupyuen/openocd-spi but with the desire to be more generic. This implementation makes use of the more common 4 wire SPI port using full duplex transfers to be able to capture the SWD ACK bits when a SWD TX operation is in progress. TEST: Connects successfully with the following combinations: Hosts: Raspberry Pi 4B Unnamed Qualcomm SoC with QUPv3 based SPI port Targets: Raspberry Pi 2040 Nordic nRF52840 NXP RT500 Change-Id: Ic2f38a1806085d527e6f999a3d15aea6f32d1019 Signed-off-by: Richard Pasek <[email protected]> Reviewed-on: https://review.openocd.org/c/openocd/+/8645 Reviewed-by: Tomas Vanek <[email protected]> Reviewed-by: Antonio Borneo <[email protected]> Reviewed-by: zapb <[email protected]> Tested-by: jenkins
1 parent 26f2df8 commit 83e0293

File tree

7 files changed

+711
-0
lines changed

7 files changed

+711
-0
lines changed

configure.ac

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ m4_define([PCIE_ADAPTERS],
163163
m4_define([SERIAL_PORT_ADAPTERS],
164164
[[[buspirate], [Bus Pirate], [BUS_PIRATE]]])
165165

166+
m4_define([LINUXSPIDEV_ADAPTER],
167+
[[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]])
168+
166169
# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter
167170
# because there is an M4 macro called 'adapter'.
168171
m4_define([DUMMY_ADAPTER],
@@ -289,6 +292,7 @@ AC_ARG_ADAPTERS([
289292
LIBFTDI_ADAPTERS,
290293
LIBFTDI_USB1_ADAPTERS,
291294
LIBGPIOD_ADAPTERS,
295+
LINUXSPIDEV_ADAPTER,
292296
SERIAL_PORT_ADAPTERS,
293297
DUMMY_ADAPTER,
294298
PCIE_ADAPTERS,
@@ -726,6 +730,7 @@ PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o
726730
PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build])
727731
PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"],
728732
[internal error: validation should happen beforehand])
733+
PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev])
729734
PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused])
730735

731736
AS_IF([test "x$enable_linuxgpiod" != "xno"], [
@@ -875,6 +880,7 @@ m4_foreach([adapter], [USB1_ADAPTERS,
875880
LIBFTDI_USB1_ADAPTERS,
876881
LIBGPIOD_ADAPTERS,
877882
LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
883+
LINUXSPIDEV_ADAPTER,
878884
DUMMY_ADAPTER,
879885
OPTIONAL_LIBRARIES,
880886
COVERAGE],

doc/openocd.texi

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,9 @@ emulation model of target hardware.
614614
@item @b{xlnx_pcie_xvc}
615615
@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface.
616616

617+
@item @b{linuxspidev}
618+
@* A SPI based SWD driver using Linux SPI devices.
619+
617620
@item @b{linuxgpiod}
618621
@* A bitbang JTAG driver using Linux GPIO through library libgpiod.
619622

@@ -3401,6 +3404,70 @@ See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file.
34013404

34023405
@end deffn
34033406

3407+
@deffn {Interface Driver} {linuxspidev}
3408+
Linux provides userspace access to SPI through spidev. Full duplex SPI
3409+
transactions are used to simultaneously read and write to/from the target to
3410+
emulate the SWD transport.
3411+
3412+
@deffn {Config Command} {spidev path} path
3413+
Specifies the path to the spidev device.
3414+
@end deffn
3415+
3416+
@deffn {Config Command} {spidev mode} value
3417+
Set the mode of the spi port with optional bit flags (default=3).
3418+
See /usr/include/linux/spi/spidev.h for all of the SPI mode options.
3419+
@end deffn
3420+
3421+
@deffn {Config Command} {spidev queue_entries} value
3422+
Set the maximum number of queued transactions per spi exchange (default=64).
3423+
More queued transactions may offer greater performance when the target doesn't
3424+
need to wait. On the contrary higher numbers will reduce performance when the
3425+
target requests a wait as all queued transactions will need to be exchanged
3426+
before spidev can see the wait request.
3427+
@end deffn
3428+
3429+
See @file{tcl/interface/spidev_example.cfg} for a sample configuration file.
3430+
3431+
Electrical connections:
3432+
@example
3433+
+--------------+ +--------------+
3434+
| | 1K | |
3435+
| MOSI|---/\/\/\---+ | |
3436+
| Host | | | Target |
3437+
| MISO|------------+---|SWDIO |
3438+
| | | |
3439+
| SCK|----------------|SWDCLK |
3440+
| | | |
3441+
+--------------+ +--------------+
3442+
@end example
3443+
3444+
The 1K resistor works well with most MCUs up to 3 MHz. A lower resistance
3445+
could be used to achieve higher speeds granted that the target SWDIO pin has
3446+
enough drive strength to pull the signal high while being pulled low by this
3447+
resistor.
3448+
3449+
If you are having trouble here are some tips:
3450+
3451+
@itemize @bullet
3452+
3453+
@item @b{Make sure MISO and MOSI are tied together with a 1K resistor.}
3454+
MISO should be attached to the target.
3455+
3456+
@item @b{Make sure that your host and target are using the same I/O voltage}
3457+
(for example both are using 3.3 volts).
3458+
3459+
@item @b{Your host's SPI port may not idle low.}
3460+
This will lead to an additional clock edge being sent to the target, causing
3461+
the host and target being 1 clock off from each other. Try setting
3462+
SPI_MOSI_IDLE_LOW in spi_mode. Try using a different spi_mode (0 - 3).
3463+
3464+
@item @b{Your target may pull SWDIO and/or SWDCLK high.}
3465+
This will create an extra edge when the host releases control of the SPI port
3466+
at the end of a transaction. You'll need to confirm this with a scope or meter.
3467+
Try installing 10K resistors on SWDIO and SWDCLK to ground to stop this.
3468+
3469+
@end itemize
3470+
@end deffn
34043471

34053472
@deffn {Interface Driver} {linuxgpiod}
34063473
Linux provides userspace access to GPIO through libgpiod since Linux kernel

src/jtag/drivers/Makefile.am

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ endif
176176
if SYSFSGPIO
177177
DRIVERFILES += %D%/sysfsgpio.c
178178
endif
179+
if LINUXSPIDEV
180+
DRIVERFILES += %D%/linuxspidev.c
181+
endif
179182
if XLNX_PCIE_XVC
180183
DRIVERFILES += %D%/xlnx-pcie-xvc.c
181184
endif

0 commit comments

Comments
 (0)