update README

This commit is contained in:
Triss 2021-07-30 01:39:09 +02:00
parent 637833ae35
commit 0e7dc0010c
5 changed files with 51 additions and 348 deletions

View File

@ -2,7 +2,10 @@ The below copyright and permission notice applies to portions of the following
files, which have been modified from their original versions in files, which have been modified from their original versions in
<https://github.com/perexg/picoprobe-sump> (the "picoprobe-sump repository") <https://github.com/perexg/picoprobe-sump> (the "picoprobe-sump repository")
- TODO - bsp/rp2040/m_sump/sump_hw.c
- bsp/rp2040/m_sump/sump_hw.h
- src/m_sump/cdc_sump.c
- src/m_sump/sump.h
The below notice does not apply to any modifications made to the above files The below notice does not apply to any modifications made to the above files
since the versions present in the picoprobe-usb repository, nor to any files since the versions present in the picoprobe-usb repository, nor to any files

118
README.md
View File

@ -136,30 +136,31 @@ Different serial speeds can be used, too. Serprog support is *techincally*
untested, as in it does output the correct SPI commands as seen by my logic untested, as in it does output the correct SPI commands as seen by my logic
analyzer, but I don't have a SPI flash chip to test it on. analyzer, but I don't have a SPI flash chip to test it on.
### I2C-Tiny-USB ### SPI, I2C and temperature sensor
The I2C-Tiny-USB functionality can be used as follows: first, load the This functionality depends on custom kernel modules being loaded: In the
`i2c-dev` and `i2c-tiny-usb` modules (for now you need a patched version of the `host/modules/` directory, one can find the sources and a Makefile.
latter, can be found in the `i2c-tiny-usb-misc/` folder in this repo). Then you
can use the I2C USB bridge as any other I2C device on your computer. For After loading the modules (and modprobing `i2c-dev` and `spidev`), devices for
example, the `i2cdetect`, `i2cget` and `i2cset` tools from `i2c-tools` should these interfaces should appear in `/dev`.
all work. You can find which I2C device corresponds to the I2C-Tiny-USB, by
running `i2cdetect -l`: SPI and I2C can be controlled using the standard tools for these (eg. the
utilities from `i2c-tools` package), and the temperature sensor should show
up in `lm_sensors`.
Using `i2cdetect -l`, you should be able to see which I2C device belongs to
the tool:
``` ```
$ sudo i2cdetect -l $ sudo i2cdetect -l
[...] [...]
i2c-1 i2c i915 gmbus dpb I2C adapter i2c-1 i2c i915 gmbus dpb I2C adapter
i2c-8 i2c Radeon i2c bit bus 0x95 I2C adapter i2c-8 i2c Radeon i2c bit bus 0x95 I2C adapter
i2c-15 i2c i2c-tiny-usb at bus 001 device 011 I2C adapter # <---- ! i2c-15 i2c dmj-i2c-1-1:1.0 I2C adapter
i2c-6 i2c Radeon i2c bit bus 0x93 I2C adapter i2c-6 i2c Radeon i2c bit bus 0x93 I2C adapter
i2c-13 i2c AUX C/DDI C/PHY C I2C adapter i2c-13 i2c AUX C/DDI C/PHY C I2C adapter
[...]
``` ```
**NOTE**: I2C functionality sometimes breaks with certain USB hubs. If this is
the case, try unplugging and replugging the entire hub.
#### I2C temperature sensor emulation #### I2C temperature sensor emulation
If the board/MCU has a builtin temperature sensor, a fake I2C device on the bus If the board/MCU has a builtin temperature sensor, a fake I2C device on the bus
@ -168,7 +169,7 @@ sensor (the exact sensor emulated is the Microchip MCP9808). To have it show
up in `sensors`, do the following (with `BUSNUM` the number from the above up in `sensors`, do the following (with `BUSNUM` the number from the above
`i2cdetect -l` output): `i2cdetect -l` output):
``` ```
$ ./dmctl.py /dev/ttyACM1 --i2ctemp 0x18 # need to give it an address first $ ./dmctl.sh tempsensor --set 0x18 # need to give it an address first
$ sudo modprobe jc42 $ sudo modprobe jc42
$ # now tell the jc42 module that the device can be found at this address $ # now tell the jc42 module that the device can be found at this address
$ echo "jc42 0x18" | sudo tee /sys/bus/i2c/devices/i2c-BUSNUM/new_device $ echo "jc42 0x18" | sudo tee /sys/bus/i2c/devices/i2c-BUSNUM/new_device
@ -185,38 +186,40 @@ Temperature readout may be a bit higher than the ambient temperature.
### Runtime configuration ### Runtime configuration
Several settings can be applied at runtime, using the `dmctl` Python script. Several settings can be applied at runtime, using the `dmctl` Python script.
Settings are communicated over the Serprog USB serial port. Settings are communicated over a vendor USB interface.
The currently implemented options are:
- `support`: tells you which features this implementation/board supports
- `ctsrts`: Enable/disable CTS/RTS-based hardware flow control for the UART port
- `i2ctemp`: Get or set the I2C address of the fake I2C device of the temperature
sensor. Use 0 for getting the value, 0xff for disabling, and any
other for setting the address. The I2C device emulated is an MCP9808.
When setting a value, the old value is printed.
``` ```
usage: dmctl [-h] [-v] [--ctsrts [CTSRTS]] tty $ ./dmctl.sh --help
usage: dmctl [-h] [--conn CONN] subcommand ...
Runtime configuration control for DapperMime-JTAG
positional arguments:
tty Path to DapperMime-JTAG Serprog UART device
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
-v, --verbose Verbose logging (for this utility) --conn CONN Connection string. Either a dmj-char device in /dev, a USB
--ctsrts [CTSRTS] Enable or disable CTS/RTS flow control (--ctsrts [true|false]) bus.device number, or a USB VID:PID pair. Defaults to trying
--i2ctemp [I2CTEMP] Control the builtin I2C temperature controller: get (0), /dev/dmj-* (if there is only one), and cafe:1312 otherwise.
disable (-1/0xff) or set/enable (other) the current
status and I2C bus address subcommands:
--support Get list of supported/implemented functionality 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
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
``` ```
example: Example:
``` ```
$ ./dmctl.py /dev/ttyACM1 --ctsrts true $ ./dmctl.py --conn cafe:1312 get-device-info
``` ```
## License ## License
@ -227,18 +230,15 @@ ARM's CMSIS 5 code is licensed under the [Apache 2.0 license](https://opensource
libco is licensed under the [ISC license](https://opensource.org/licenses/ISC) libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
Some code has been incorporated from the [DapperMime](https://github.com/majbthrd/DapperMime)
and [picoprobe-sump](https://github.com/perexg/picoprobe-sump)
projects. These respective licenses can be found in
[this](./LICENSE.dappermime) and [this](./LICENSE.picoprobe-sump) file.
## TODO ## TODO
- [ ] A name - [ ] A name
- [ ] A (VID and) PID, and maybe better subclass & protocol IDs for the vnd cfg itf - [ ] A (VID and) PID, and maybe better subclass & protocol IDs for the vnd cfg itf
- [x] More Pico SDK meta/buildinfo
- [x] CMSIS-DAP JTAG implementation
- [x] Flashrom/SPI support using Serprog
- Parallel ROM flashing support, too, by having the device switch into a
separate mode that temporarily disables all other IO protocols
- Not enough IO, rip.
- [x] UART with CTS/RTS flow control
- [x] Needs configurable stuff as well, as some UART interfaces won't use this.
- [x] Debug interface to send printf stuff directly to USB, instead of having - [x] Debug interface to send printf stuff directly to USB, instead of having
to use the UART interface as a loopback thing. to use the UART interface as a loopback thing.
- [ ] Second UART port for when stdio UART is disabled? - [ ] Second UART port for when stdio UART is disabled?
@ -248,35 +248,11 @@ libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
parts do, but, laziness. parts do, but, laziness.
- [x] 10-bit I2C address support (Needs poking at the Pico SDK, as it only - [x] 10-bit I2C address support (Needs poking at the Pico SDK, as it only
supports 7-bit ones). supports 7-bit ones).
- [x] Better USB interface stuff, because I2C-Tiny-USB sucks and serprog can only - [ ] 1-wire
do flash chips instead of being a real spidev. General idea can probably be
taken from the DLN2 Linux drivers, except better (dynamic interface
signalled in the protocol (eg. does the device actually have I2C/SPI/..?),
dynamic I2C and SPI capabilities, add 1wire stuff, maybe yeet the GPIO bc
it'll be used for other stuff anyway, etc.). Means a custom Linux driver but
oh well, I2C-Tiny-USB needs patching either way.
- [ ] 1-wire using ↑
- [x] A proper interface for sending commands etc. instead of shoehorning it
into Serprog.
- Can probably be included in the "Better USB interface stuff".
- [ ] make modes persistent? - [ ] make modes persistent?
- [ ] JTAG pinout detector - [ ] JTAG pinout detector
- https://github.com/cyphunk/JTAGenum - https://github.com/cyphunk/JTAGenum
- https://github.com/travisgoodspeed/goodfet/blob/master/firmware/apps/jscan/jscan.c - https://github.com/travisgoodspeed/goodfet/blob/master/firmware/apps/jscan/jscan.c
- [x] Host-side script that is an XVC (or hw_server) cable and communicates
with the device to perform the JTAG commands, because Vivado no likey
OpenOCD.
- CMSIS-DAP interface can be used directly, see CMSIS_5/CMSIS/DoxyGen/DAP/src/dap_USB_cmds.txt
- https://github.com/BerkeleyLab/XVC-FTDI-JTAG
- https://www.eevblog.com/forum/fpga/xilinx-jtag-and-tcf/
- https://git.eclipse.org/c/tcf/org.eclipse.tcf.git/plain/docs/TCF%20Linux%20Agent%20Prototype.html
- http://www.eclipse.org/tcf/
- https://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/
- https://github.com/Xilinx/XilinxVirtualCable/
- https://github.com/derekmulcahy/xvcpi
- [x] SUMP logic analyzer mode?
- see also [this](https://github.com/perexg/picoprobe-sump)
- [ ] runtime config options for overclocking, logging
- [ ] FT2232 emulation mode? - [ ] FT2232 emulation mode?
- watch out, still need a vnd cfg interface! libftdi expects the following stuff: (TODO: acquire detailed protocol description) - watch out, still need a vnd cfg interface! libftdi expects the following stuff: (TODO: acquire detailed protocol description)
- interface 0 ("A"): index 1, epin 0x02, epout 0x81 - interface 0 ("A"): index 1, epin 0x02, epout 0x81

148
dmctl.py
View File

@ -1,148 +0,0 @@
#!/usr/bin/env python3
import argparse, serial, struct
from typing import *
def auto_int(x):
return int(x, 0)
class RTOpt(NamedTuple):
type: Callable[[Any], Any]
optid: int
desc: str
supportmap = {
1: "CMSIS-DAP",
2: "UART",
4: "I2C-Tiny-USB",
8: "Temperature sensor",
0x80: "stdio USB-CDC debug interface"
}
option_table = {
'ctsrts': RTOpt(bool, 1, "Enable or disable CTS/RTS flow control (--ctsrts [true|false])"),
'i2ctemp': RTOpt(auto_int, 2, "Control the builtin I2C temperature controller: get (0), disable (-1/0xff) or set/enable (other) the current status and I2C bus address"),
'support': RTOpt(str, 0xff, "Get list of supported/implemented functionality"),
}
S_ACK = b'\x06'
S_NAK = b'\x15'
S_CMD_NOP = b'\x00'
S_CMD_Q_IFACE = b'\x01'
S_CMD_Q_CMDMAP = b'\x02'
S_CMD_Q_PGMNAME = b'\x03'
S_CMD_SYNCNOP = b'\x10'
S_CMD_MAGIC_SETTINGS = b'\x53'
def val2byte(t, v) -> int:
if t == bool:
return 1 if v else 0
if t == int or t == auto_int:
return 0xff if v < 0 else (v & 0xff)
if t == str:
return 0
assert False, "unimplemented type %s" % str(t)
def do_xfer(args, cmd:int, arg:int, port: str, baudrate:int=115200) -> Optional[int]:
with serial.Serial(port, baudrate, timeout=1) as ser:
cmdmap = [0]*32
syncok = False
for i in range(8):
ser.write(S_CMD_SYNCNOP)
a = ser.read()
b = ser.read()
if a == S_NAK and b == S_ACK:
syncok = True
break
if not syncok:
print("sync failed")
return None
ser.write(S_CMD_NOP)
if ser.read() != S_ACK:
print("nop failed")
return None
ser.write(S_CMD_Q_IFACE)
if ser.read() != S_ACK:
print("q_iface failed")
return None
serprogver = struct.unpack('<H', ser.read(2))[0]
if serprogver != 1:
print("unknown serprog protocol version %d" % serprogver)
return None
ser.write(S_CMD_Q_CMDMAP)
if ser.read() != S_ACK:
print("q_cmdmap failed")
return None
else:
cmdmap = ser.read(32)
if (cmdmap[S_CMD_MAGIC_SETTINGS[0] >> 3] & (1<<(S_CMD_MAGIC_SETTINGS[0]&7))) == 0:
print("serprog programmer has no S_CMD_MAGIC_SETTINGS")
return None
if (cmdmap[S_CMD_Q_PGMNAME[0] >> 3] & (1<<(S_CMD_Q_PGMNAME[0]&7))) != 0:
ser.write(S_CMD_Q_PGMNAME)
if ser.read() != S_ACK:
print("q_pgmname failed")
else:
name = ser.read(16).decode('utf-8')
if args.verbose: print("programmer is '%s'" % name)
ser.write(S_CMD_MAGIC_SETTINGS)
ser.write(bytes([cmd,arg]))
acknak = ser.read()
if acknak == S_ACK:
return ser.read()[0]
else:
print("settings command failed")
return None
def main():
parser = argparse.ArgumentParser(prog="dmctl",
description="Runtime configuration control for DapperMime-JTAG")
parser.add_argument('tty', type=str, nargs=1, #'?', #default="/dev/ttyACM1",
help="Path to DapperMime-JTAG Serprog UART device"#+\
#" [/dev/ttyACM1]"
)
parser.add_argument('-v', '--verbose', default=False, action='store_true',
help="Verbose logging (for this utility)")
for k, v in option_table.items():
if k == "support":
parser.add_argument('--%s'%k, default=None, action='store_true',
help=v.desc)
else:
parser.add_argument('--%s'%k, type=v.type, nargs='?', default=None,
help=v.desc)
args = parser.parse_args()
for k, v in option_table.items():
if args.__dict__[k] is not None:
resp = do_xfer(args, v.optid, val2byte(v.type, args.__dict__[k]), args.tty[0])
if resp is None:
return 1
if k == "support":
print(", ".join(kvp[1] for kvp in supportmap.items() if (kvp[0] & resp) != 0))
else:
#if args.verbose:
print("-> %d" % resp)
return 0
#do_xfer(1, 1, "/dev/ttyACM1")
#do_xfer(1, 0, "/dev/ttyACM1")
if __name__ == '__main__':
main()

110
dmctl2.py
View File

@ -1,110 +0,0 @@
#!/usr/bin/env python3
# TODO: RIIR, probably
import usb.core
from typing import *
import array
print("find")
dev = usb.core.find(idVendor=0xcafe, idProduct=0x1312)
#print("set config")
#dev.set_configuration()
print("get config")
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
print("get eps")
epout = usb.util.find_descriptor(intf, custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
epin = usb.util.find_descriptor(intf, custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN )
assert epout is not None
assert epin is not None
def wrusb(ep, data: bytes):
return ep.write(data)
# TODO: buffering read?
def rdresp(ep) -> Tuple[int, bytes]:
acc = bytearray()
# first stuff: header etc
arr = array.array('B')
arr.fromlist([0]*64)
nrd = ep.read(arr)
stat = arr[0]
plen = arr[1]
print("plen=0x%x"%plen)
if (plen & 0x80) != 0:
plen &= 0x7f
plen |= arr[2] << 7
for x in arr.tobytes()[3:nrd]:
acc.append(x)
else:
for x in arr.tobytes()[2:nrd]:
acc.append(x)
while len(acc) < plen:
for i in range(len(arr)): arr[i] = 0
nrd = ep.read(arr)
for x in arr.tobytes()[:nrd]:
acc.append(x)
return (stat, acc)
print("cmds!")
epout.write(b'\x00') # get version
print('[%s]'%(', '.join(hex(x) for x in epin.read(4)))) # result: status, payload len, version
# 0 2 0x10 0x00 -> ok
epout.write(b'\x01') # get modes
print('[%s]'%(', '.join(hex(x) for x in epin.read(4)))) # result: status, payload len, modes
# 0 2 0x3 0 -> ok
epout.write(b'\x02') # get cur mode
print('[%s]'%(', '.join(hex(x) for x in epin.read(3)))) # result: status, payload len, mode
# 0 1 1 -> ok
epout.write(b'\x04') # get infostr
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x10') # get mode1 name
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x11') # get mode1 version
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x12') # get mode1 features
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x40') # get mode4 name
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x41') # get mode4 version
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x42') # get mode4 features
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
### ATTEMPT A MODESET ###
#epout.write(b'\x03\x04') # set cur mode
#print('[%s]'%(', '.join(hex(x) for x in epin.read(3)))) # result: status, payload len, mode

View File

@ -1,18 +0,0 @@
#!/usr/bin/env python3
import os, struct, sys
f = os.open(sys.argv[1], os.O_RDWR | os.O_CLOEXEC) # TODO: windows: os.O_BINARY |
try:
os.write(f, b'\x00') # get version
resp = os.read(f, 4) # response: status, paylaod len (should be 2), payload
print("resp=%s"%repr(resp))
print("stat=%d plen=%d ver=%04x" % (resp[0], resp[1], struct.unpack('<H', resp[2:])[0]))
finally:
os.close(f)
#with open(sys.argv[1], 'rb') as f:
# f.write(b'\x00') # get version
# resp = f.read(4) # response
# print("stat=%d plen=%d ver=%04x" % (resp[0], resp[1], struct.unpack('<H', resp[2:])[0]))