Skip to content

Commit

Permalink
Add Linux SPI device SWD adapter support
Browse files Browse the repository at this point in the history
To alleviate the need to bitbang SWD, I've written a SWD SPI
implementation. This code is inspired by the work of luppy@appkaki.com
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 <rpasek@google.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8645
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: zapb <dev@zapb.de>
Tested-by: jenkins
  • Loading branch information
Richard Pasek authored and tom-van committed Jan 22, 2025
1 parent 26f2df8 commit 83e0293
Show file tree
Hide file tree
Showing 7 changed files with 711 additions and 0 deletions.
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ m4_define([PCIE_ADAPTERS],
m4_define([SERIAL_PORT_ADAPTERS],
[[[buspirate], [Bus Pirate], [BUS_PIRATE]]])

m4_define([LINUXSPIDEV_ADAPTER],
[[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]])

# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter
# because there is an M4 macro called 'adapter'.
m4_define([DUMMY_ADAPTER],
Expand Down Expand Up @@ -289,6 +292,7 @@ AC_ARG_ADAPTERS([
LIBFTDI_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
LINUXSPIDEV_ADAPTER,
SERIAL_PORT_ADAPTERS,
DUMMY_ADAPTER,
PCIE_ADAPTERS,
Expand Down Expand Up @@ -726,6 +730,7 @@ PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o
PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build])
PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"],
[internal error: validation should happen beforehand])
PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev])
PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused])

AS_IF([test "x$enable_linuxgpiod" != "xno"], [
Expand Down Expand Up @@ -875,6 +880,7 @@ m4_foreach([adapter], [USB1_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
LINUXSPIDEV_ADAPTER,
DUMMY_ADAPTER,
OPTIONAL_LIBRARIES,
COVERAGE],
Expand Down
67 changes: 67 additions & 0 deletions doc/openocd.texi
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,9 @@ emulation model of target hardware.
@item @b{xlnx_pcie_xvc}
@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface.

@item @b{linuxspidev}
@* A SPI based SWD driver using Linux SPI devices.

@item @b{linuxgpiod}
@* A bitbang JTAG driver using Linux GPIO through library libgpiod.

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

@end deffn

@deffn {Interface Driver} {linuxspidev}
Linux provides userspace access to SPI through spidev. Full duplex SPI
transactions are used to simultaneously read and write to/from the target to
emulate the SWD transport.

@deffn {Config Command} {spidev path} path
Specifies the path to the spidev device.
@end deffn

@deffn {Config Command} {spidev mode} value
Set the mode of the spi port with optional bit flags (default=3).
See /usr/include/linux/spi/spidev.h for all of the SPI mode options.
@end deffn

@deffn {Config Command} {spidev queue_entries} value
Set the maximum number of queued transactions per spi exchange (default=64).
More queued transactions may offer greater performance when the target doesn't
need to wait. On the contrary higher numbers will reduce performance when the
target requests a wait as all queued transactions will need to be exchanged
before spidev can see the wait request.
@end deffn

See @file{tcl/interface/spidev_example.cfg} for a sample configuration file.

Electrical connections:
@example
+--------------+ +--------------+
| | 1K | |
| MOSI|---/\/\/\---+ | |
| Host | | | Target |
| MISO|------------+---|SWDIO |
| | | |
| SCK|----------------|SWDCLK |
| | | |
+--------------+ +--------------+
@end example

The 1K resistor works well with most MCUs up to 3 MHz. A lower resistance
could be used to achieve higher speeds granted that the target SWDIO pin has
enough drive strength to pull the signal high while being pulled low by this
resistor.

If you are having trouble here are some tips:

@itemize @bullet

@item @b{Make sure MISO and MOSI are tied together with a 1K resistor.}
MISO should be attached to the target.

@item @b{Make sure that your host and target are using the same I/O voltage}
(for example both are using 3.3 volts).

@item @b{Your host's SPI port may not idle low.}
This will lead to an additional clock edge being sent to the target, causing
the host and target being 1 clock off from each other. Try setting
SPI_MOSI_IDLE_LOW in spi_mode. Try using a different spi_mode (0 - 3).

@item @b{Your target may pull SWDIO and/or SWDCLK high.}
This will create an extra edge when the host releases control of the SPI port
at the end of a transaction. You'll need to confirm this with a scope or meter.
Try installing 10K resistors on SWDIO and SWDCLK to ground to stop this.

@end itemize
@end deffn

@deffn {Interface Driver} {linuxgpiod}
Linux provides userspace access to GPIO through libgpiod since Linux kernel
Expand Down
3 changes: 3 additions & 0 deletions src/jtag/drivers/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ endif
if SYSFSGPIO
DRIVERFILES += %D%/sysfsgpio.c
endif
if LINUXSPIDEV
DRIVERFILES += %D%/linuxspidev.c
endif
if XLNX_PCIE_XVC
DRIVERFILES += %D%/xlnx-pcie-xvc.c
endif
Expand Down
Loading

0 comments on commit 83e0293

Please # to comment.