3 dpctl
sys64738 edited this page 2021-08-26 18:45:32 +00:00

dpctl is the host-side utility for configuring the device at runtime. It can be used to query device info, switch to another mode, or perform a few mode-specific commands.

Communicating these commands happens over the USB vendor interface.

General usage

The dpctl.sh script can be found in the host/ directory in the source tree.

$ ./dpctl.sh --help
usage: dpctl [-h] [--conn CONN] subcommand ...

optional arguments:
  -h, --help       show this help message and exit
  --conn CONN      Connection string. Either a dragonprobe-char device in /dev,
                   a USB bus.device number, or a USB VID:PID pair. Defaults to
                   trying /dev/dragonprobe-* (if there is only one), and
                   cafe:1312 otherwise.

subcommands:
  For more info on each subcommand, run the program with 'subcommand --help' as
  arguments.

  subcommand       Command to send to the device
    get-device-info
                   Shows device info
    get-mode-info  Shows mode info. A mode can optionally be specified, default
                   is the current mode.
    set-mode       Set the device mode
    bootloader     Set the device in bootloader mode
    storage-info   Get persistent storage info
    storage-flush  Flush persistent storage data to storage medium
    storage-get    Get data of a particular mode
    uart-cts-rts   Get, enable/disable UART hardware flow control
    tempsensor     Get or set the IRC emulation enable/address of the
                   temperature sensor.
    jtag-scan      JTAG pinout scanner
    sump-overclock
                   SUMP logic analyzer overclock settings

Connecting to a device

While it is possible to have dpctl connect directly to a USB device (using --conn vid:pid or --conn bus.dev), having the kernel module loaded will keep the USB vendor interface reserved for itself. To work around this problem, a character device driver has been made, which exposes a /dev/dragonprobe-<id> device which can also be used by dpctl using --conn /dev/dragonprobe-<id>.

General subcommands

get-device-info

Shows general device information. No other arguments required. Example:

$ ./dpctl.sh get-device-info
CMSIS-DAP (RP2040 Pico): protocol version: 00.10, currently in mode 1 (Default mode with misc features)
available modes: 1, 3, 4

get-mode-info

Gets info of a specific mode. An extra mode number can be specified, but it defaults to the current mode. Using all as mode number displays the information of all available modes. Example:

$ ./dpctl.sh get-mode-info 
mode 1: Default mode with misc features: version 00.10 with features UART, CMSIS-DAP, SPI, I2C, temperature sensor
$ ./dpctl.sh get-mode-info 3
mode 3: JTAG (etc) pinout scanner: version 00.10 with features JTAG, SWD
$ ./dpctl.sh get-mode-info 42
No mode 42 available
$ ./dpctl.sh get-mode-info all
mode  1: Default mode with misc features: version 00.10 with features UART, CMSIS-DAP, SPI, I2C, temperature sensor
mode  3: JTAG (etc) pinout scanner: version 00.10 with features JTAG, SWD
mode  4: SUMP logic analyzer mode: version 00.10 with features SUMP

set-mode

This subcommand changes the device mode. Do note that this causes the device to temporarily disconnect for about one half to one second, in order to reconfigure its interface descriptor tables. Example:

$ ./dpctl.sh set-mode 4

Mode 0 is a special meaning to switch the device into (chip/board-specific) bootloader mode.

bootloader

This is a shorthand for dpctl set-mode 0.

Persistent storage subcommands

storage-info

Shows the header information of the persistent storage. Example:

$ ./dpctl.sh storage-info
magic: OK, version=0010, current mode=1, #modes=2, DJB2(table)=780903137
	mode 1 version 0010: 0x1ff000..+0x2, DJB2=6220460
	mode 4 version 0010: 0x1ff020..+0x1, DJB2=182954

storage-get

Gets the data blob of a specified mode. Example:

$ ./dpctl.sh storage-get 1
b'\x00\x18'

storage-flush

Saves data to the persistent storage when changed. Example:

$ ./dpctl.sh storage-flush
storage saved

# immediately afterwards:
$ ./dpctl.sh storage-flush
no write needed

Mode 1-specific subcommands

uart-cts-rts

Enable or disable UART hardware flow control. Example:

$ ./dpctl.sh uart-cts-rts --get
Flow control disabled
$ ./dpctl.sh uart-cts-rts --enable
$ ./dpctl.sh uart-cts-rts --disable
$ ./dpctl.sh uart-cts-rts --set [true|false|0|1]

tempsensor

Configures the device address of the emulated I2C temperature sensor device. Example:

$ ./dpctl.sh tempsensor --get
Temperature sensor I2C emulation disabled
$ ./dpctl.sh tempsensor --set 0x18
Temperature sensor I2C device changed from disabled to 0x18
$ ./dpctl.sh tempsensor --get
Temperature sensor I2C device at address 0x18
$ ./dpctl.sh tempsensor --disable
Temperature sensor I2C device changed from 0x18 to disabled

Mode 3-specific subcommands

jtag-scan

Does a JTAG (or other supported debug interface) scan:

usage: dpctl jtag-scan [-h] {jtag,swd} start end

positional arguments:
  {jtag,swd}  Pinout type to check for.
  start       Number of the start of the pin range to scan (inclusive)
  end         Number of the end of the pin range to scan (inclusive)
$ ./dpctl.sh jtag-scan jtag 10 15
Starting JTAG scan...
JTAG scan finished (12 matches):
Certain matches:
 1	TCK=11 TMS=10 TDI=13 TDO=12 nTRST=14 IRLEN=4
 2	TCK=11 TMS=10 TDI=13 TDO=12 nTRST=15 IRLEN=4

Possible matches:
 3	TCK=11 TMS=10 TDI=14 TDO=12 nTRST=13 #toggle=2
    <snip>
 
$ ./dpctl.sh jtag-scan swd 10 15
Starting SWD scan...
SWD scan finished (1 matches):
 1	SWCLK=11 SWDIO=10 idcode=2ba01477

$ ./dpctl.sh jtag-scan swd 15 10
WARN: start pin 15 greater than end pin 10, swapping the order...
Starting SWD scan...
...
SWD scan finished (1 matches):
 1	SWCLK=11 SWDIO=10 idcode=2ba01477

$ ./dpctl.sh jtag-scan swd 0 999
Start pin must be at least 2, but is 0

$ ./dpctl.sh jtag-scan idk 10 15
usage: dpctl jtag-scan [-h] {jtag,swd} start end
dpctl jtag-scan: error: argument type: invalid choice: 'idk' (choose from 'jtag', 'swd')

Mode 4-specific subcommands

sump-overclock

This subcommand can be used to get or set the SUMP logic analyzer sampling overclock settings. The actual meaning of the values passed depends on the hardware used. Example:

$ ./dpctl.sh sump-overclock --get
0
$ ./dpctl.sh sump-overclock --enable
$ ./dpctl.sh sump-overclock --get
1
$ ./dpctl.sh sump-overclock --set 0

The setting is a single byte. However, a number of hardware platforms have a binary "enable/disable" option, for which --enable/--disable flag are made available. These simply set the byte value to 0 or 1.

On the Raspberry Pico, only 0 and nonzero are available as options, which resp. mean overclocking disabled (133 MHz) and enabled (200 MHz). Sampling happens at 1/4th of the system clock, thus, with overclocking enabled, the sample rate becomes 50 MHz.