tribble-control 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/DESIGN.md +871 -0
- data/LICENSE +21 -0
- data/README.md +541 -0
- data/examples/tribble.conf +208 -0
- data/examples/vbus-check +140 -0
- data/exe/tribble-control +14 -0
- data/lib/tribble-control/cli/connect.rb +282 -0
- data/lib/tribble-control/cli/flash.rb +102 -0
- data/lib/tribble-control/cli/reset.rb +39 -0
- data/lib/tribble-control/cli/serial.rb +60 -0
- data/lib/tribble-control/cli/usb.rb +104 -0
- data/lib/tribble-control/cli.rb +1230 -0
- data/lib/tribble-control/hub/exsys.rb +248 -0
- data/lib/tribble-control/hub/usb.rb +418 -0
- data/lib/tribble-control/hub.rb +115 -0
- data/lib/tribble-control/platform.rb +271 -0
- data/lib/tribble-control/tally.rb +91 -0
- data/lib/tribble-control/version.rb +8 -0
- data/lib/tribble-control.rb +32 -0
- data/man/man1/tribble-control.1 +1483 -0
- data/tribble-control.gemspec +99 -0
- metadata +192 -0
|
@@ -0,0 +1,1483 @@
|
|
|
1
|
+
.Dd October 7, 2026
|
|
2
|
+
.Dt TRIBBLE-CONTROL 1
|
|
3
|
+
.Os
|
|
4
|
+
.Sh NAME
|
|
5
|
+
.Nm tribble-control
|
|
6
|
+
.Nd power, flash and monitor the devices on a switchable USB hub
|
|
7
|
+
.Sh SYNOPSIS
|
|
8
|
+
.Nm
|
|
9
|
+
.Op Fl d Ar DEV
|
|
10
|
+
.Op Fl -hub Ar KIND
|
|
11
|
+
.Op Fl C Ar FILE
|
|
12
|
+
.Op Fl m Ar TYPE
|
|
13
|
+
.Op Fl W Ar SECONDS
|
|
14
|
+
.Op Fl p Ar STRING
|
|
15
|
+
.Op Fl -openocd Ar PATH
|
|
16
|
+
.Op Fl F
|
|
17
|
+
.Op Fl v
|
|
18
|
+
.Op Fl -debug Ns Oo = Ns Ar FILE Oc
|
|
19
|
+
.Ar command
|
|
20
|
+
.Op command options
|
|
21
|
+
.Op Ar PORT | DEVNAME ...
|
|
22
|
+
.Nm
|
|
23
|
+
.Fl -man | -help | -version
|
|
24
|
+
.Sh DESCRIPTION
|
|
25
|
+
The hub switches its ports independently, and there are two kinds of
|
|
26
|
+
it.
|
|
27
|
+
The ExSYS managed hub, the default, switches VBUS on each of its
|
|
28
|
+
sixteen sockets over an FT232 serial line wired inside it, and
|
|
29
|
+
tribble\-control drives that line.
|
|
30
|
+
Any standard USB hub with per\-port power switching is the other
|
|
31
|
+
\(em 'hub = usb' in the configuration, or \-\-hub usb \(em and it is switched on
|
|
32
|
+
the bus itself, with hub\-class requests through
|
|
33
|
+
.Xr usbconfig 8 ,
|
|
34
|
+
which makes it
|
|
35
|
+
.Fx
|
|
36
|
+
only for now.
|
|
37
|
+
See THE HUB.
|
|
38
|
+
For a board on either that
|
|
39
|
+
carries a debug probe, tribble\-control additionally speaks SWD through
|
|
40
|
+
openocd and reads the board's console over USB CDC.
|
|
41
|
+
Which probe and
|
|
42
|
+
which chip a board needs is the configuration's business (interface= and
|
|
43
|
+
target=), so the family it belongs to is not built in; the bench is
|
|
44
|
+
nRF52 today, and that is the default, not a requirement.
|
|
45
|
+
Everything
|
|
46
|
+
else on the hub is only an electrical load \(em see PROTECTED PORTS.
|
|
47
|
+
.Bd -literal
|
|
48
|
+
tribble\-control \-C tribble.conf flash zephyr.hex alpha beta
|
|
49
|
+
stdbuf \-oL tribble\-control \-C tribble.conf connect \-\-off gamma epsilon \e
|
|
50
|
+
| tee twr.log
|
|
51
|
+
.Ed
|
|
52
|
+
.Pp
|
|
53
|
+
It lives on the host owning the hub, alongside tribble.conf.
|
|
54
|
+
It is a gem, so
|
|
55
|
+
.Ic gem install tribble-control
|
|
56
|
+
\(em from a built .gem, or
|
|
57
|
+
.Ic rake install
|
|
58
|
+
in a checkout \(em puts
|
|
59
|
+
.Nm
|
|
60
|
+
on PATH with its dependencies and needs nothing further.
|
|
61
|
+
.Pp
|
|
62
|
+
A checkout with a vendored bundle works too, and is what a host that
|
|
63
|
+
should not have gems installed system\-wide wants:
|
|
64
|
+
.Ic bundle install --path vendor
|
|
65
|
+
followed by
|
|
66
|
+
.Ic bundle binstubs tribble-control
|
|
67
|
+
writes bin/tribble\-control, which sets that bundle up before loading
|
|
68
|
+
anything.
|
|
69
|
+
Run that one from the directory holding the bundle.
|
|
70
|
+
.Sh THE HUB
|
|
71
|
+
.Bd -literal
|
|
72
|
+
the host running tribble\-control
|
|
73
|
+
│
|
|
74
|
+
│ FT232R ──▸ /dev/ttyUSB0 the hub's control line. It is
|
|
75
|
+
│ 9600 8N1 internal to the hub: it is NOT
|
|
76
|
+
▾ one of the 16 switched sockets.
|
|
77
|
+
┌───────────────────────────────────────────────────────────────────┐
|
|
78
|
+
│ ExSYS 16\-port managed USB hub │
|
|
79
|
+
│ │
|
|
80
|
+
│ bank 1 bank 2 bank 3 bank 4 │
|
|
81
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
82
|
+
│ │ 1 │ │ 5 │ │ 9 │ │ 13 │ │
|
|
83
|
+
│ │ 2 │ │ 6 │ │ 10 │ │ 14 │ │
|
|
84
|
+
│ │ 3 │ │ 7 │ │ 11 │ │ 15 │ │
|
|
85
|
+
│ │ 4 │ │ 8 │ │ 12 │ │ 16 │ │
|
|
86
|
+
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|
87
|
+
└───────────────────────────────────────────────────────────────────┘
|
|
88
|
+
Sixteen independently switched sockets. What is on each is the
|
|
89
|
+
configuration's business, not this diagram's: a socket may carry a board
|
|
90
|
+
the tool drives over SWD, or something it only powers and never
|
|
91
|
+
talks to, or nothing at all. Sockets in the second class are what
|
|
92
|
+
PROTECTED PORTS exists for.
|
|
93
|
+
.Ed
|
|
94
|
+
.Pp
|
|
95
|
+
Ports are numbered 1 to 16 across four internal banks of four.
|
|
96
|
+
These are
|
|
97
|
+
the hub's own numbers, the ones the configuration and every command use; whether
|
|
98
|
+
the sockets are silkscreened that way is another matter, so count banks
|
|
99
|
+
left to right and sockets top to bottom if you are looking for one by hand.
|
|
100
|
+
.Pp
|
|
101
|
+
The FT232 control adapter enumerates at the last position of the hub's
|
|
102
|
+
internal tree (USB path 1\-1.2.4.4), which makes it look as though it
|
|
103
|
+
occupies port 16.
|
|
104
|
+
It does not: it is wired inside the hub and is not
|
|
105
|
+
switched.
|
|
106
|
+
Port 16 is an ordinary socket like the other fifteen.
|
|
107
|
+
The one
|
|
108
|
+
consequence is that a board must never be put on port 16: \-\-method usb
|
|
109
|
+
would compute the path 1\-1.2.4.4 for it and address the FT232 instead.
|
|
110
|
+
.Pp
|
|
111
|
+
A port that only supplies power tells the tool nothing about what is on
|
|
112
|
+
it, so if you need to reboot one device in particular, establish which
|
|
113
|
+
socket it is physically first.
|
|
114
|
+
Nothing on such a port communicates with
|
|
115
|
+
the host, and the configuration records a name and a port, not what is plugged
|
|
116
|
+
in.
|
|
117
|
+
.Pp
|
|
118
|
+
The host running tribble\-control is not powered from the hub, so no hub
|
|
119
|
+
port can cut power to the machine you are typing on, and \-\-force is safe
|
|
120
|
+
in that one narrow respect.
|
|
121
|
+
.Pp
|
|
122
|
+
Requirements: Ruby 3.1, and openocd \(em everything that reaches a
|
|
123
|
+
board over SWD shells out to it.
|
|
124
|
+
The Ruby dependencies come with the gem; openocd does not, being no
|
|
125
|
+
gem of anybody's.
|
|
126
|
+
It is expected at /usr/bin/openocd and found elsewhere with
|
|
127
|
+
\-\-openocd; flash and reset check for it before switching anything, and
|
|
128
|
+
connect \-\-reset when it reaches for it.
|
|
129
|
+
.Ss A standard hub with per-port power switching
|
|
130
|
+
Everything above is the ExSYS hub.
|
|
131
|
+
\&'hub = usb' at the top of a configuration, or \-\-hub usb on the command line,
|
|
132
|
+
drives any hub that switches its own ports instead.
|
|
133
|
+
Nothing about it is an agreement with one manufacturer: what is spoken
|
|
134
|
+
is the USB hub class, which every hub answers \(em the hub descriptor
|
|
135
|
+
says how many ports there are, GET_STATUS says whether one is powered,
|
|
136
|
+
and SET_FEATURE/CLEAR_FEATURE of PORT_POWER switches it.
|
|
137
|
+
The ports are that hub's own, 1 to the bNbrPorts its descriptor
|
|
138
|
+
reports, read once when the hub is opened.
|
|
139
|
+
The fixed sixteen, and the 4\-by\-4 geometry \-\-method usb rests on, are
|
|
140
|
+
the ExSYS hub's alone.
|
|
141
|
+
.Pp
|
|
142
|
+
The kind has to be said because it cannot be read off the
|
|
143
|
+
.Cm device
|
|
144
|
+
value: a USB path such as 1\-1.1 names the FT232's socket for an ExSYS
|
|
145
|
+
hub and the hub itself for a usb hub, so the same line would mean two
|
|
146
|
+
different hubs.
|
|
147
|
+
It names what the hub IS and not which tool drives it, so a configuration
|
|
148
|
+
written today keeps working when another host learns to drive such a
|
|
149
|
+
hub.
|
|
150
|
+
.Pp
|
|
151
|
+
Today that host is
|
|
152
|
+
.Fx
|
|
153
|
+
only:
|
|
154
|
+
.Xr usbconfig 8
|
|
155
|
+
is what issues the requests, and no other host here has a command that
|
|
156
|
+
sends an arbitrary control request to a hub.
|
|
157
|
+
Root is not among the requirements.
|
|
158
|
+
The ugen nodes are root:operator 0660, and the kernel asks for the
|
|
159
|
+
driver privilege only for SET_ADDRESS, SET_CONFIG and SET_INTERFACE,
|
|
160
|
+
so a hub\-class port feature request passes: membership of group
|
|
161
|
+
operator is the whole of it
|
|
162
|
+
.Pq Ic pw groupmod operator -m yourname ,
|
|
163
|
+
then log in again.
|
|
164
|
+
Without it every request answers "Permission denied" and
|
|
165
|
+
.Nm
|
|
166
|
+
says so, naming the group.
|
|
167
|
+
.Pp
|
|
168
|
+
Which hub, when the host has more than one, works as it does for the
|
|
169
|
+
other kind: one candidate is taken, two or more are refused and listed
|
|
170
|
+
\(em each with its serial, its ugen name, its USB path and its port
|
|
171
|
+
count, semicolons between them, the count being the only thing that
|
|
172
|
+
tells two of the same part apart when neither carries a serial.
|
|
173
|
+
Root hubs are never candidates.
|
|
174
|
+
They are the controller a host's own sockets hang off, and a port of
|
|
175
|
+
one has no PORT_POWER to clear, so offering one would offer a hub every
|
|
176
|
+
command against it then failed on.
|
|
177
|
+
See
|
|
178
|
+
.Fl d
|
|
179
|
+
under
|
|
180
|
+
.Sx OPTIONS
|
|
181
|
+
for the three shapes a name may take.
|
|
182
|
+
.Pp
|
|
183
|
+
What 'off' then does to the socket is the one thing software cannot
|
|
184
|
+
find out, and
|
|
185
|
+
.Cm switch
|
|
186
|
+
in the configuration is how it is told.
|
|
187
|
+
A hub with no power switch wired still reports the port unpowered and
|
|
188
|
+
still drops the link, so the device vanishes from the host and comes
|
|
189
|
+
back either way.
|
|
190
|
+
.Bl -tag -width "switch = link" -compact
|
|
191
|
+
.It Li "switch = link"
|
|
192
|
+
The default.
|
|
193
|
+
\&'off' takes the port off the bus and the board stays powered.
|
|
194
|
+
.It Li "switch = vbus"
|
|
195
|
+
\&'off' cuts the socket's power.
|
|
196
|
+
.El
|
|
197
|
+
.Pp
|
|
198
|
+
Watch a board's LED to find out which this hub is: put a board that
|
|
199
|
+
lights up on a port, run 'usb off' for that port, and look.
|
|
200
|
+
An LED that goes out is vbus; an LED that stays lit while the board
|
|
201
|
+
disappears from the host is link.
|
|
202
|
+
Test the socket the bench will use \(em the USB 2 and USB 3 sides of one
|
|
203
|
+
physical socket are different ports on different hubs, and a hub may
|
|
204
|
+
switch neither.
|
|
205
|
+
The ExSYS hub refuses the key rather than ignoring it: it always cuts
|
|
206
|
+
power, and a line that changes nothing is a line somebody will trust.
|
|
207
|
+
.Pp
|
|
208
|
+
Under 'switch = link' everything that powers down still works.
|
|
209
|
+
\&'usb off', 'toggle' and 'set' behave, the board vanishes from the host
|
|
210
|
+
exactly as a power cut would, and \-\-method power still identifies a
|
|
211
|
+
board by being the only one openocd can see.
|
|
212
|
+
What does not happen is the board restarting, so every power\-down
|
|
213
|
+
warns once, naming the ports that stay powered, and the after\-flash
|
|
214
|
+
power cycle is skipped with a warning rather than pretended \(em see
|
|
215
|
+
.Sx TRAPS .
|
|
216
|
+
.Pp
|
|
217
|
+
After every switch the port's status is read back, and the command
|
|
218
|
+
fails if the power bit did not follow.
|
|
219
|
+
That read\-back is the tool's only measurement of whether a hub
|
|
220
|
+
switches at all: one that accepts CLEAR_FEATURE(PORT_POWER), answers OK
|
|
221
|
+
and leaves the port up would otherwise have 'usb off' report success on
|
|
222
|
+
a bench it never touched.
|
|
223
|
+
Nothing is refused on what a hub DECLARES about its switching, for the
|
|
224
|
+
same reason \(em the dock's Genesys hub declares ganged and switches per
|
|
225
|
+
port anyway.
|
|
226
|
+
.Sh OPTIONS
|
|
227
|
+
Ordering matters, and it is the thing most likely to waste your afternoon.
|
|
228
|
+
Global options come before the command; a command's own options come after
|
|
229
|
+
the command but before its sub\-action.
|
|
230
|
+
So:
|
|
231
|
+
.Bd -literal
|
|
232
|
+
tribble\-control \-C tribble.conf \-\-force usb off 14 global, then cmd
|
|
233
|
+
tribble\-control \-C tribble.conf usb \-\-default=false set gamma:on
|
|
234
|
+
.Ed
|
|
235
|
+
.Pp
|
|
236
|
+
and NOT 'usb set \-\-default=false ...', which parses the flag as an argument
|
|
237
|
+
to 'set' and fails with "invalid argument".
|
|
238
|
+
.Pp
|
|
239
|
+
Global options, which go before the command:
|
|
240
|
+
.Bl -tag -width "-W, --warm-up=SECONDS"
|
|
241
|
+
.It Fl d , Fl -device Ns = Ns Ar DEV
|
|
242
|
+
Which hub to drive, in one of three shapes, told apart by what they
|
|
243
|
+
look like:
|
|
244
|
+
.Bl -tag -width "1-1.2.4.4" -compact
|
|
245
|
+
.It Pa /dev/ttyUSB1
|
|
246
|
+
a
|
|
247
|
+
.Sq /
|
|
248
|
+
in it, so the serial line itself, used as given \(em the same rule
|
|
249
|
+
.Fl -openocd
|
|
250
|
+
uses to tell a path from a name
|
|
251
|
+
.It Cm 1-1.2.4.4
|
|
252
|
+
the USB path shape, so the adapter sitting in that socket on this host
|
|
253
|
+
.It Cm AL03GD7X
|
|
254
|
+
anything else, so the FT232's serial number
|
|
255
|
+
.El
|
|
256
|
+
.Pp
|
|
257
|
+
With
|
|
258
|
+
.Fl -hub Cm usb
|
|
259
|
+
the three shapes name a hub of that kind instead:
|
|
260
|
+
.Bl -tag -width "1-1.2.4.4" -compact
|
|
261
|
+
.It Cm ugen1.4
|
|
262
|
+
the ugen shape, so that device, used as given
|
|
263
|
+
.It Cm 1-1.1
|
|
264
|
+
the USB path shape, so the hub in that socket on this host
|
|
265
|
+
.It Cm AC0528515619
|
|
266
|
+
anything else, so the hub's own serial number
|
|
267
|
+
.El
|
|
268
|
+
.Pp
|
|
269
|
+
ugen1.4 is that kind's /dev/ttyUSB1 and carries the same warning below:
|
|
270
|
+
the number is enumeration order \(em ugen1.4 is the fourth device the
|
|
271
|
+
second controller attached \(em so a replug renumbers it, and a configuration
|
|
272
|
+
naming a hub that way points at whatever attached in its place.
|
|
273
|
+
Write the serial, which follows the hub, or the USB path, which follows
|
|
274
|
+
the socket.
|
|
275
|
+
.Pp
|
|
276
|
+
Three answers, in the order they are trusted: this option, then the
|
|
277
|
+
configuration's own
|
|
278
|
+
.Cm device
|
|
279
|
+
line, then the host, which is searched for an FTDI 0403:6001 and
|
|
280
|
+
normally turns up /dev/ttyUSB0.
|
|
281
|
+
.Pp
|
|
282
|
+
That last one is a guess, and it is made only when there is nothing to
|
|
283
|
+
guess between.
|
|
284
|
+
An FTDI 0403:6001 is the hub's control adapter and also every other
|
|
285
|
+
FT232 on the host, so with two of them attached
|
|
286
|
+
.Nm
|
|
287
|
+
refuses and lists what it found, with serials, rather than switching the
|
|
288
|
+
ports of whichever enumerated first.
|
|
289
|
+
A host owning more than one bench says which in each configuration, so that
|
|
290
|
+
.Fl C
|
|
291
|
+
alone selects one; this option is for the one\-off.
|
|
292
|
+
.Pp
|
|
293
|
+
The serial line itself is the worst of the three to write down.
|
|
294
|
+
The number in /dev/ttyUSB1 is not the hub's, and not the USB device
|
|
295
|
+
number either: it is the usbserial layer's own index (ttyU on FreeBSD,
|
|
296
|
+
allocated the same way), and it is the lowest one free when that
|
|
297
|
+
adapter is probed.
|
|
298
|
+
So it depends on what else attached first, and it is reused \(em unplug
|
|
299
|
+
whatever holds ttyUSB0 and the next thing to attach takes ttyUSB0.
|
|
300
|
+
Two hubs can swap names across a reboot, or while the machine is up,
|
|
301
|
+
and every configuration naming them that way then points at the other bench,
|
|
302
|
+
silently and in a way no command can detect.
|
|
303
|
+
.Pp
|
|
304
|
+
The other two are both stable, and they answer different questions.
|
|
305
|
+
A serial stays with the ADAPTER \(em move the hub to another socket, or
|
|
306
|
+
another machine, and its serial goes with it \(em and is the usual
|
|
307
|
+
want, naming one particular hub.
|
|
308
|
+
A USB path stays with the SOCKET: whatever is plugged in there answers
|
|
309
|
+
to it, a replacement hub included.
|
|
310
|
+
Use the path for a hub whose EEPROM carries no serial, that being the
|
|
311
|
+
only stable name such a one has, and for a bench where the socket is
|
|
312
|
+
the fixed thing.
|
|
313
|
+
.Pp
|
|
314
|
+
Both platforms report a path, by different means: Linux states it in
|
|
315
|
+
/sys, and on FreeBSD it is walked out of the sysctl tree, each device's
|
|
316
|
+
%location giving the port it occupies on its parent and %parent naming
|
|
317
|
+
that parent.
|
|
318
|
+
The numbering is each host's own, though \(em FreeBSD counts buses from
|
|
319
|
+
0 and Linux from 1 \(em so a path names a socket on the machine that
|
|
320
|
+
reported it and does not travel to another.
|
|
321
|
+
Read the ones on this host with
|
|
322
|
+
.Ic exsys-usb discover ,
|
|
323
|
+
which the exsys gem installs and which lists one adapter per line, its
|
|
324
|
+
line then its serial \(em or by asking
|
|
325
|
+
.Nm
|
|
326
|
+
for a serial that does not exist, since the refusal lists them.
|
|
327
|
+
.It Fl -hub Ns = Ns Ar KIND
|
|
328
|
+
Which kind of hub to drive:
|
|
329
|
+
.Cm exsys
|
|
330
|
+
(the default) or
|
|
331
|
+
.Cm usb .
|
|
332
|
+
Overrides the configuration's own
|
|
333
|
+
.Cm hub
|
|
334
|
+
line.
|
|
335
|
+
The option takes those two words only; a configuration naming another kind is
|
|
336
|
+
refused at load with both listed.
|
|
337
|
+
See
|
|
338
|
+
.Sx THE HUB .
|
|
339
|
+
.It Fl C , Fl -config Ns = Ns Ar FILE
|
|
340
|
+
The configuration.
|
|
341
|
+
Required for any power\-down at all, and by any command taking device
|
|
342
|
+
names.
|
|
343
|
+
Without
|
|
344
|
+
.Fl C ,
|
|
345
|
+
a file named
|
|
346
|
+
.Pa tribble-control.conf
|
|
347
|
+
in the current directory is used if there is one; neither the home
|
|
348
|
+
directory nor /etc is ever consulted, and given
|
|
349
|
+
.Fl C
|
|
350
|
+
the current directory is not either.
|
|
351
|
+
.Ic usb on
|
|
352
|
+
and
|
|
353
|
+
.Ic usb status
|
|
354
|
+
work without it.
|
|
355
|
+
.It Fl m , Fl -method Ns = Ns Ar TYPE
|
|
356
|
+
Device selection:
|
|
357
|
+
.Cm power , usb
|
|
358
|
+
or
|
|
359
|
+
.Cm serial .
|
|
360
|
+
See
|
|
361
|
+
.Sx DEVICE SELECTION .
|
|
362
|
+
Rejected if the command does not support it.
|
|
363
|
+
.It Fl W , Fl -warm-up Ns = Ns Ar SECONDS
|
|
364
|
+
Delay after powering a port on, before touching the board.
|
|
365
|
+
Default 5.
|
|
366
|
+
.It Fl F , Fl -force
|
|
367
|
+
Switch ports the configuration does not allow.
|
|
368
|
+
See
|
|
369
|
+
.Sx PROTECTED PORTS .
|
|
370
|
+
.It Fl p , Fl -password Ns = Ns Ar STRING
|
|
371
|
+
Supplies the ExSYS hub's password; it does not change it.
|
|
372
|
+
Default
|
|
373
|
+
.Sq pass .
|
|
374
|
+
A wrong one makes the hub answer E01 and the command abort loudly, not
|
|
375
|
+
silently.
|
|
376
|
+
A usb hub has no password, so the option is refused there rather than
|
|
377
|
+
ignored.
|
|
378
|
+
.It Fl r , Fl -require Ns = Ns Ar FILE Ns Op , Ns Ar FILE ...
|
|
379
|
+
Ruby files to load before anything else runs, for the tallies they
|
|
380
|
+
register.
|
|
381
|
+
Repeatable: every
|
|
382
|
+
.Fl r
|
|
383
|
+
given is loaded, in order.
|
|
384
|
+
An empty name, from \-\-require= or a doubled comma, is refused.
|
|
385
|
+
See
|
|
386
|
+
.Sx TALLIES .
|
|
387
|
+
.It Fl -openocd Ns = Ns Ar PATH
|
|
388
|
+
openocd binary.
|
|
389
|
+
Default /usr/bin/openocd; a name with no
|
|
390
|
+
.Sq /
|
|
391
|
+
in it is looked up in PATH, which is how to reach it on a host that
|
|
392
|
+
keeps it elsewhere (FreeBSD: /usr/local/bin).
|
|
393
|
+
Checked before any port is switched, by the commands that always need
|
|
394
|
+
it.
|
|
395
|
+
.It Fl -debug Ns Oo = Ns Ar FILE Oc
|
|
396
|
+
Show debug output \(em chiefly the openocd command line issued for each
|
|
397
|
+
board, which is the thing worth having when a flash behaves oddly.
|
|
398
|
+
With
|
|
399
|
+
.Ar FILE ,
|
|
400
|
+
the whole log is copied there as well as shown, appending, so a long
|
|
401
|
+
run can be kept without being watched.
|
|
402
|
+
An unwritable path is refused before any port is switched.
|
|
403
|
+
.It Fl v , Fl -verbose , Fl -no-verbose
|
|
404
|
+
Run verbosely.
|
|
405
|
+
.It Fl V , Fl -version
|
|
406
|
+
Print the tribble\-control and ExSYS library versions and exit.
|
|
407
|
+
.It Fl h , Fl -help
|
|
408
|
+
Usage, including the command list.
|
|
409
|
+
.El
|
|
410
|
+
.Pp
|
|
411
|
+
Per\-command: 'usb' takes \-\-default=BOOL, 'connect' takes \-\-off.
|
|
412
|
+
Both are
|
|
413
|
+
described under COMMANDS.
|
|
414
|
+
.Sh "HUB PROTOCOL, AND WHAT IT CANNOT TELL YOU"
|
|
415
|
+
The ExSYS hub speaks a small ASCII protocol over the FT232 line.
|
|
416
|
+
Recovered from
|
|
417
|
+
the vendor's own cusba64 binary (which ships unstripped), the complete
|
|
418
|
+
vocabulary is eight commands, each terminated by CR, answering 'G...' on
|
|
419
|
+
success and 'E01' on error:
|
|
420
|
+
.Bd -literal
|
|
421
|
+
?Q query: an id, the port count and the firmware no password
|
|
422
|
+
GP get port states no password
|
|
423
|
+
SP set port states password
|
|
424
|
+
FP set port states, and save as the power\-on state password
|
|
425
|
+
WP save the current states as the power\-on state password
|
|
426
|
+
CP change password password
|
|
427
|
+
RD restore factory defaults password
|
|
428
|
+
RH reset the whole hub password
|
|
429
|
+
.Ed
|
|
430
|
+
.Pp
|
|
431
|
+
?Q answers a single string: an id, then the port count, then the
|
|
432
|
+
firmware version \(em CENTOS000516v02 on a 16\-port hub running v02.
|
|
433
|
+
It carries no port states; cusba64 fills its On= and Off= display from
|
|
434
|
+
a separate GP.
|
|
435
|
+
.Pp
|
|
436
|
+
The exsys gem implements all eight as of 1.0, ?Q as #query, and the
|
|
437
|
+
port count it answers decides what "every port" covers rather than
|
|
438
|
+
being assumed.
|
|
439
|
+
It holds an exclusive lock on the line for the whole of a
|
|
440
|
+
read\-modify\-write, so two processes cannot lose each other's changes
|
|
441
|
+
between the GP and the SP, and it refuses an empty port list rather
|
|
442
|
+
than reading it as every port.
|
|
443
|
+
The default password is
|
|
444
|
+
\&'pass', right\-padded to 8 characters.
|
|
445
|
+
.Pp
|
|
446
|
+
tribble\-control only ever issues SP, never FP or WP: port states are set for
|
|
447
|
+
the here and now and never written to the hub's flash, so nothing it does
|
|
448
|
+
survives a hub power cycle.
|
|
449
|
+
Note also that RD, the only recovery from a
|
|
450
|
+
forgotten password, drops every port \(em so changing the password with CP
|
|
451
|
+
is close to a one\-way door on a hub carrying anything that minds losing
|
|
452
|
+
power without notice.
|
|
453
|
+
.Pp
|
|
454
|
+
There is no per\-port current or voltage telemetry, and no way to bolt it
|
|
455
|
+
on: the protocol has no such command, cusba64 contains no such code, and
|
|
456
|
+
USB 2.x/3.x hubs do not report per\-port draw to the host under any
|
|
457
|
+
circumstances.
|
|
458
|
+
A device's bMaxPower descriptor is what it asks for at
|
|
459
|
+
enumeration, not what it consumes, and a pure power load never enumerates
|
|
460
|
+
at all.
|
|
461
|
+
Measuring consumption needs an inline USB power meter or an
|
|
462
|
+
instrumented bench supply.
|
|
463
|
+
.Pp
|
|
464
|
+
Two of these commands are worth fearing.
|
|
465
|
+
RH resets the hub and RD
|
|
466
|
+
restores factory defaults; either drops every port, which power\-cycles
|
|
467
|
+
everything on the hub, protected ports included.
|
|
468
|
+
tribble\-control never
|
|
469
|
+
issues them, and the exsys gem only does so via #reset and
|
|
470
|
+
#factory_reset, both of which require an explicit confirm: true.
|
|
471
|
+
.Ss What a usb hub is asked
|
|
472
|
+
A hub of the other kind needs no gem and no serial line: the switching
|
|
473
|
+
is on the bus itself, and the whole vocabulary is four control requests
|
|
474
|
+
issued through
|
|
475
|
+
.Xr usbconfig 8 ,
|
|
476
|
+
by absolute path so that nothing depends on whoever's PATH the command
|
|
477
|
+
was started with.
|
|
478
|
+
.Bd -literal
|
|
479
|
+
/usr/sbin/usbconfig \-d ugenB.D do_request ...
|
|
480
|
+
|
|
481
|
+
0xa0 0x06 0x2900 0 9 hub descriptor, USB 2
|
|
482
|
+
0xa0 0x06 0x2a00 0 12 hub descriptor, SuperSpeed
|
|
483
|
+
0xa3 0x00 0x0000 P 4 GET_PORT_STATUS of port P
|
|
484
|
+
0x23 0x03 0x0008 P 0 SET_FEATURE PORT_POWER, port P
|
|
485
|
+
0x23 0x01 0x0008 P 0 CLEAR_FEATURE PORT_POWER, port P
|
|
486
|
+
.Ed
|
|
487
|
+
.Pp
|
|
488
|
+
Both descriptors are asked for and whichever the hub answers decides
|
|
489
|
+
how its port status word is read from then on; the other is refused,
|
|
490
|
+
which is the only way to learn which kind of hub this is.
|
|
491
|
+
The hubs themselves are found with '/sbin/sysctl \-e dev.uhub'.
|
|
492
|
+
.Pp
|
|
493
|
+
Nothing here outlives the hub either: PORT_POWER is set for the here
|
|
494
|
+
and now, exactly as SP is above, and no descriptor is written.
|
|
495
|
+
And there is no per\-port telemetry on this side either, for the reason
|
|
496
|
+
already given \(em no USB hub reports per\-port draw to the host.
|
|
497
|
+
.Sh CONFIGURATION
|
|
498
|
+
A UCL file mapping a device name to a hub port, and optionally to the
|
|
499
|
+
board's debug\-probe serial number.
|
|
500
|
+
It is what \-C/\-\-config points at (or, failing that, a
|
|
501
|
+
.Pa tribble-control.conf
|
|
502
|
+
in the current directory), and it
|
|
503
|
+
is the only thing that tells tribble\-control which ports it may touch.
|
|
504
|
+
.Bd -literal
|
|
505
|
+
device = AL03GD7X # which hub these ports are on
|
|
506
|
+
hub = exsys # which KIND; 'usb' is the other
|
|
507
|
+
protect { # what must not lose power;
|
|
508
|
+
undeclared = yes # see PROTECTED PORTS
|
|
509
|
+
ports = [ 13, 14, 15, 16 ]
|
|
510
|
+
nodes = [ rpi ]
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
alpha { serial = '1026360216055e5b0000...97969902', port = 1 }
|
|
514
|
+
beta { port = 2 }
|
|
515
|
+
gamma { serial = '1026360213072dde0000...97969902', port = 4 }
|
|
516
|
+
retired { serial = '1026360202c4dc0f0000...97969902', port = none }
|
|
517
|
+
rpi { port = 12 }
|
|
518
|
+
.Ed
|
|
519
|
+
.Pp
|
|
520
|
+
Indentation is not significant, but separators are: two keys on one line
|
|
521
|
+
need a comma between them, which is why the entries above carry one and
|
|
522
|
+
one\-key\-per\-line entries do not.
|
|
523
|
+
A CMSIS\-DAP serial is 48 hex
|
|
524
|
+
characters and a J\-Link one 12, and both are pasted whole \(em the ones
|
|
525
|
+
above are elided in the middle for width.
|
|
526
|
+
.Pp
|
|
527
|
+
Every device entry must carry a port, and 'port = none' is how one says it
|
|
528
|
+
is a record rather than a board on the bench.
|
|
529
|
+
\&'retired' above is the
|
|
530
|
+
case: it stopped enumerating, its port was given to another board, and the
|
|
531
|
+
entry stays so that its serial is not lost.
|
|
532
|
+
Such an entry is left out of
|
|
533
|
+
everything \(em never selected, never switched, never flashed \(em and naming
|
|
534
|
+
it says so ("device 'retired' is not on the bench").
|
|
535
|
+
A MISSING port is an
|
|
536
|
+
error, not a synonym for none: deleting the port line is exactly what
|
|
537
|
+
happens when a port is reassigned, and inferring "gone" from a line
|
|
538
|
+
somebody forgot would drop a live board silently.
|
|
539
|
+
Two entries claiming
|
|
540
|
+
one port is refused at load, none excepted.
|
|
541
|
+
.Pp
|
|
542
|
+
Every key other than 'device', 'hub', 'switch', 'protect',
|
|
543
|
+
\&'tally' and 'types' is a device.
|
|
544
|
+
A command
|
|
545
|
+
given no device names operates on all of them.
|
|
546
|
+
Names may be used anywhere
|
|
547
|
+
a port number can be, in every command.
|
|
548
|
+
.Pp
|
|
549
|
+
A board with no serial= cannot be reached by 'reset' or by \-\-method
|
|
550
|
+
serial, both of which address a board by its serial number: the run
|
|
551
|
+
aborts with "Device without serial".
|
|
552
|
+
Fix it by running 'serial' (see
|
|
553
|
+
RECIPES) and pasting the value in.
|
|
554
|
+
.Pp
|
|
555
|
+
Optional keys describe a board whose probe or console differs from
|
|
556
|
+
the default:
|
|
557
|
+
.Bd -literal
|
|
558
|
+
epsilon { serial = '000760040233', interface = jlink, baud = 115200,
|
|
559
|
+
port = 7 }
|
|
560
|
+
.Ed
|
|
561
|
+
.Bl -tag -width power_cycle
|
|
562
|
+
.It Cm interface
|
|
563
|
+
The openocd interface script, without the .cfg:
|
|
564
|
+
.Cm cmsis-dap
|
|
565
|
+
(the default, a DAPLink probe such as the MDK's) or
|
|
566
|
+
.Cm jlink
|
|
567
|
+
(a J\-Link OB, as on the DWM1001\-DEV).
|
|
568
|
+
Used by
|
|
569
|
+
.Ic flash , reset
|
|
570
|
+
and
|
|
571
|
+
.Ic connect --reset .
|
|
572
|
+
With
|
|
573
|
+
.Cm jlink ,
|
|
574
|
+
serial= is the J\-Link serial number as udev reports it; leading zeros
|
|
575
|
+
are accepted.
|
|
576
|
+
.It Cm target
|
|
577
|
+
The openocd target script, without the .cfg:
|
|
578
|
+
.Cm nrf52
|
|
579
|
+
(the default, which is what the whole bench runs) or whatever openocd
|
|
580
|
+
calls the chip on a board of another family.
|
|
581
|
+
Used wherever interface= is.
|
|
582
|
+
The two are independent: the probe says how to reach the chip, the
|
|
583
|
+
target says which chip it is.
|
|
584
|
+
.It Cm transport
|
|
585
|
+
The transport openocd selects:
|
|
586
|
+
.Cm swd
|
|
587
|
+
(the default) or whatever the chip and the probe both speak, commonly
|
|
588
|
+
.Cm jtag .
|
|
589
|
+
.Cm none
|
|
590
|
+
selects nothing and leaves the choice to the interface script; it is
|
|
591
|
+
spelt as for
|
|
592
|
+
.Cm work_area ,
|
|
593
|
+
in any case, or null, or \-.
|
|
594
|
+
Anything else that is not a name \(em a boolean such as no, a number, an
|
|
595
|
+
empty string \(em is refused.
|
|
596
|
+
Making
|
|
597
|
+
.Cm target
|
|
598
|
+
a key and leaving this one fixed would be half a fix: a chip reached
|
|
599
|
+
over JTAG would take the right target script and then fail on a
|
|
600
|
+
transport it has not got.
|
|
601
|
+
.It Cm work_area
|
|
602
|
+
How much target RAM openocd may borrow for its flash algorithms,
|
|
603
|
+
default 0x4000, written as openocd wants it.
|
|
604
|
+
.Cm none
|
|
605
|
+
says nothing and leaves the target script to choose.
|
|
606
|
+
16 KB is nothing to a large part and more than some have in total, so
|
|
607
|
+
it belongs to the chip rather than to this tool.
|
|
608
|
+
.It Cm baud
|
|
609
|
+
The console speed
|
|
610
|
+
.Ic connect
|
|
611
|
+
opens, default 230400 (what the MDK overlay sets).
|
|
612
|
+
The stock DWM1001\-DEV devicetree runs its console at 115200.
|
|
613
|
+
.It Cm tally
|
|
614
|
+
Which tally reads this board's console, overriding the file's own
|
|
615
|
+
.Cm tally
|
|
616
|
+
line.
|
|
617
|
+
See
|
|
618
|
+
.Sx TALLIES .
|
|
619
|
+
.It Cm power_cycle
|
|
620
|
+
The moments at which the board must have its port powered off and on
|
|
621
|
+
again: one name, or a list of them.
|
|
622
|
+
Known:
|
|
623
|
+
.Bl -tag -width after-flash
|
|
624
|
+
.It Cm after-flash
|
|
625
|
+
After a successful flash.
|
|
626
|
+
The DWM1001\-DEV needs it: after openocd's reset init / write / reset
|
|
627
|
+
run its DW1000 no longer reports transmissions (the board resolves
|
|
628
|
+
nothing and logs "our TX timestamps are missing") until the module is
|
|
629
|
+
power\-cycled; a plain SWD reset is not enough.
|
|
630
|
+
.El
|
|
631
|
+
.Pp
|
|
632
|
+
A name nothing acts on is not an error, so a new moment can be recorded
|
|
633
|
+
here before the command that honours it exists.
|
|
634
|
+
It lives here, and not only as the
|
|
635
|
+
.Ic flash --power-cycle
|
|
636
|
+
option, so that a flash by hand on the hub cannot forget it.
|
|
637
|
+
.El
|
|
638
|
+
.Pp
|
|
639
|
+
\&'device' is the hub these ports are on: the serial number of its
|
|
640
|
+
FT232 control adapter, a USB path such as 1-1.2.4.4, or the serial line
|
|
641
|
+
itself if the value has a '/' in it.
|
|
642
|
+
Quote a serial that is all digits: an unquoted one is read as a number,
|
|
643
|
+
and a number has no leading zeros, so 00760040233 arrives as 760040233
|
|
644
|
+
and matches nothing.
|
|
645
|
+
The refusal lists what the host really has, which is the moment to
|
|
646
|
+
notice.
|
|
647
|
+
.Pp
|
|
648
|
+
The key is newer than the rest, which matters when a configuration and a
|
|
649
|
+
.Nm
|
|
650
|
+
are deployed separately: every top-level key the tool does not know is
|
|
651
|
+
taken for a board, and a board must declare a port, so this line meets
|
|
652
|
+
an older
|
|
653
|
+
.Nm
|
|
654
|
+
as "devlist entry 'device' has no port".
|
|
655
|
+
Nothing is switched and nothing is damaged \(em the command refuses at
|
|
656
|
+
load \(em but upgrade the tool before adding the line.
|
|
657
|
+
A configuration is one bench and a bench is one hub, so the file that says
|
|
658
|
+
which board is on which port is where to say which hub those ports
|
|
659
|
+
belong to; with it, \-C alone selects a bench on a host that owns two.
|
|
660
|
+
Write the serial, or the USB path, rather than the serial line \(em a
|
|
661
|
+
ttyUSB number is the lowest index free when the adapter was probed, so
|
|
662
|
+
it depends on what else attached first and is reused when something
|
|
663
|
+
detaches, and neither of the other two does.
|
|
664
|
+
See
|
|
665
|
+
.Fl d
|
|
666
|
+
under
|
|
667
|
+
.Sx OPTIONS
|
|
668
|
+
for how to read one.
|
|
669
|
+
\&'hub' is which KIND of hub that is: 'exsys', the default and
|
|
670
|
+
everything described so far, or 'usb' for any hub that switches its own
|
|
671
|
+
ports.
|
|
672
|
+
\&'switch' is what such a hub's 'off' does to the socket: 'link', the
|
|
673
|
+
default, takes the port off the bus and leaves the board powered, and
|
|
674
|
+
\&'vbus' cuts the power.
|
|
675
|
+
It applies to 'hub = usb' alone, and an ExSYS hub refuses it rather
|
|
676
|
+
than ignoring it.
|
|
677
|
+
Both are described under
|
|
678
|
+
.Sx THE HUB ,
|
|
679
|
+
and \-\-hub overrides the first for a one\-off.
|
|
680
|
+
.Pp
|
|
681
|
+
\&'protect' says what must never be powered down: ports by number,
|
|
682
|
+
configuration entries by name, and every port the file does not mention
|
|
683
|
+
unless it says otherwise.
|
|
684
|
+
It is described under
|
|
685
|
+
.Sx PROTECTED PORTS .
|
|
686
|
+
\&'tally' sets the bench's default tally, described under
|
|
687
|
+
.Sx TALLIES .
|
|
688
|
+
\&'types' holds settings a device can inherit, described next.
|
|
689
|
+
.Ss Types
|
|
690
|
+
A bench is usually a handful of boards of two or three kinds, and what
|
|
691
|
+
a kind is \(em which probe, which chip, which transport, how fast its
|
|
692
|
+
console runs \(em is the same on every board of that kind.
|
|
693
|
+
Written out per device that is the same four lines eleven times, and a
|
|
694
|
+
reader has to compare them all to find the one that differs.
|
|
695
|
+
.Pp
|
|
696
|
+
\&'types' says it once:
|
|
697
|
+
.Bd -literal
|
|
698
|
+
types {
|
|
699
|
+
nrf52840-mdk {
|
|
700
|
+
interface = cmsis-dap
|
|
701
|
+
target = nrf52
|
|
702
|
+
transport = swd
|
|
703
|
+
baud = 230400
|
|
704
|
+
}
|
|
705
|
+
dwm1001-dev {
|
|
706
|
+
interface = jlink
|
|
707
|
+
target = nrf52
|
|
708
|
+
transport = swd
|
|
709
|
+
baud = 115200
|
|
710
|
+
power_cycle = after-flash
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
alpha { type = nrf52840-mdk, serial = '1026...9902', port = 1 }
|
|
715
|
+
delta { type = dwm1001-dev, serial = '000760040233', port = 7 }
|
|
716
|
+
epsilon { type = nrf52840-mdk, baud = 9600, port = 2 }
|
|
717
|
+
.Ed
|
|
718
|
+
.Pp
|
|
719
|
+
A device's own key wins over its type's: a type is what a kind of board
|
|
720
|
+
has in common, and an entry saying otherwise is saying it about itself.
|
|
721
|
+
\&'epsilon' above is an nRF52840\-MDK whose console has been moved.
|
|
722
|
+
.Pp
|
|
723
|
+
Three rules, each of them refusing something at load rather than
|
|
724
|
+
letting it read as working:
|
|
725
|
+
.Bl -bullet
|
|
726
|
+
.It
|
|
727
|
+
A type nothing defines is an error.
|
|
728
|
+
A board that asked for the jlink type and silently got the cmsis\-dap
|
|
729
|
+
default is a flash through the wrong probe, reported as a success.
|
|
730
|
+
.It
|
|
731
|
+
A type may not set
|
|
732
|
+
.Cm port
|
|
733
|
+
or
|
|
734
|
+
.Cm serial .
|
|
735
|
+
Both name one particular board \(em a port is where a single board is
|
|
736
|
+
plugged in, a serial is one physical probe \(em so a type that set
|
|
737
|
+
either would be saying that every board of that kind is the same board.
|
|
738
|
+
.It
|
|
739
|
+
Types do not nest.
|
|
740
|
+
A type is a block of settings, not a thing that can have a type of its
|
|
741
|
+
own.
|
|
742
|
+
.El
|
|
743
|
+
.Pp
|
|
744
|
+
A misspelled 'protetc' becomes a device named protetc, which would
|
|
745
|
+
silently unprotect every port the block named.
|
|
746
|
+
That one is caught: every
|
|
747
|
+
device entry must carry a port, so the misspelling is refused at load
|
|
748
|
+
with "configuration entry 'protetc' has no port".
|
|
749
|
+
A key misspelled INSIDE the block is caught by name, the block taking
|
|
750
|
+
\&'undeclared', 'ports' and 'nodes' and nothing else \(em a 'port = [ 13 ]'
|
|
751
|
+
quietly ignored would read as protection and be none.
|
|
752
|
+
Validation stops there,
|
|
753
|
+
though \(em a serial, an interface or a baud that is wrong is wrong
|
|
754
|
+
silently \(em so after editing this file still run 'usb status' and read
|
|
755
|
+
the names and the protected column before you trust it.
|
|
756
|
+
.Sh PROTECTED PORTS
|
|
757
|
+
Some things on the hub are there for power alone: a single\-board computer,
|
|
758
|
+
a powered peripheral, anything the bench feeds but does not drive.
|
|
759
|
+
Nothing
|
|
760
|
+
communicates with them, so nothing notices if their VBUS disappears \(em they
|
|
761
|
+
simply reboot, uncleanly, mid\-write.
|
|
762
|
+
One configuration block keeps that from
|
|
763
|
+
happening, with three keys.
|
|
764
|
+
.Pp
|
|
765
|
+
\&'undeclared' decides the fate of every port the configuration does not mention:
|
|
766
|
+
.Bl -tag -width "undeclared = yes"
|
|
767
|
+
.It Li "undeclared = yes"
|
|
768
|
+
The default.
|
|
769
|
+
Only ports declared in the configuration may be powered down.
|
|
770
|
+
.It Li "undeclared = no"
|
|
771
|
+
Any port the hub has may be powered down.
|
|
772
|
+
.El
|
|
773
|
+
.Pp
|
|
774
|
+
\&'ports' and 'nodes' name what is never powered down whichever way that
|
|
775
|
+
falls, so either protects a port even when that port is a declared
|
|
776
|
+
device.
|
|
777
|
+
\&'ports' takes port numbers, 'nodes' the names of configuration entries:
|
|
778
|
+
.Bd -literal
|
|
779
|
+
protect {
|
|
780
|
+
undeclared = yes
|
|
781
|
+
ports = [ 13, 14, 15, 16 ]
|
|
782
|
+
nodes = [ rpi ]
|
|
783
|
+
}
|
|
784
|
+
.Ed
|
|
785
|
+
.Pp
|
|
786
|
+
Prefer the name where there is an entry to name.
|
|
787
|
+
The port number is then written once rather than twice, the protection
|
|
788
|
+
follows the board if it moves socket, and 'usb status' prints the name
|
|
789
|
+
next to the protected port instead of a dash.
|
|
790
|
+
A name no entry declares is refused at load: a misspelling there would
|
|
791
|
+
protect nothing while reading, in the file, exactly like protection.
|
|
792
|
+
A name whose entry says 'port = none' is allowed and protects nothing,
|
|
793
|
+
there being no port to keep powered.
|
|
794
|
+
.Pp
|
|
795
|
+
Together:
|
|
796
|
+
.Bd -literal
|
|
797
|
+
tribble\-control powers down a port only if the configuration allows it,
|
|
798
|
+
and never one the configuration protects.
|
|
799
|
+
.Ed
|
|
800
|
+
.Pp
|
|
801
|
+
This is enforced at every path that can cut power, not just the obvious
|
|
802
|
+
one: 'usb off', 'usb toggle', 'usb set' with a port set to off, the
|
|
803
|
+
all\-ports\-off that begins \-\-method power, and 'connect \-\-off'.
|
|
804
|
+
You do not
|
|
805
|
+
have to reason about which commands are dangerous; they all go through the
|
|
806
|
+
same gate.
|
|
807
|
+
.Pp
|
|
808
|
+
So a bare 'usb off' means "every switchable port", not "every port the
|
|
809
|
+
hub has".
|
|
810
|
+
Naming a
|
|
811
|
+
protected port is an error, not a silent skip:
|
|
812
|
+
.Bd -literal
|
|
813
|
+
$ tribble\-control \-C tribble.conf usb off 14
|
|
814
|
+
tribble\-control: refusing to power down port(s) 14: protected by the
|
|
815
|
+
configuration (use \-\-force)
|
|
816
|
+
.Ed
|
|
817
|
+
.Pp
|
|
818
|
+
Without a configuration there is no safe set, so power\-down is
|
|
819
|
+
refused outright.
|
|
820
|
+
.Pp
|
|
821
|
+
\-F/\-\-force lifts both rules and restores the old "every port" behaviour.
|
|
822
|
+
It is the only way to deliberately reboot a power\-only device, and it is a
|
|
823
|
+
hard VBUS cut, not a shutdown: the device loses power mid\-write, with
|
|
824
|
+
whatever consequences that has for its filesystem.
|
|
825
|
+
Shut it down over the
|
|
826
|
+
network first if you care about what is on it.
|
|
827
|
+
It cannot strand you,
|
|
828
|
+
though \(em the host runs off its own supply, not off the hub.
|
|
829
|
+
.Pp
|
|
830
|
+
Powering *on* is never guarded: 'usb on' with no arguments still turns on
|
|
831
|
+
every port the hub has, which is the state the bench should normally sit
|
|
832
|
+
in.
|
|
833
|
+
.Sh DEVICE SELECTION
|
|
834
|
+
Flashing one of six identical boards means telling openocd which one.
|
|
835
|
+
There are three ways, chosen with \-m/\-\-method:
|
|
836
|
+
.Bd -literal
|
|
837
|
+
┌─────────┬─────────────────┬──────────────┬────────────────────────┐
|
|
838
|
+
│ method │ addresses a │ requires │ power while the job │
|
|
839
|
+
│ │ board by │ │ runs │
|
|
840
|
+
├─────────┼─────────────────┼──────────────┼────────────────────────┤
|
|
841
|
+
│ serial │ its debug probe │ serial= for │ every selected port │
|
|
842
|
+
│ │ serial number │ every board │ on; boards in parallel │
|
|
843
|
+
├─────────┼─────────────────┼──────────────┼────────────────────────┤
|
|
844
|
+
│ usb │ its USB path, │ a USB path │ every selected port │
|
|
845
|
+
│ │ root.bank.slot │ for the hub │ on; boards in sequence │
|
|
846
|
+
├─────────┼─────────────────┼──────────────┼────────────────────────┤
|
|
847
|
+
│ power │ being the only │ nothing │ exactly one board at │
|
|
848
|
+
│ │ board powered │ │ a time, rest cut │
|
|
849
|
+
└─────────┴─────────────────┴──────────────┴────────────────────────┘
|
|
850
|
+
.Ed
|
|
851
|
+
.Pp
|
|
852
|
+
Which to use:
|
|
853
|
+
.Bl -tag -width serial
|
|
854
|
+
.It Cm serial
|
|
855
|
+
The default for
|
|
856
|
+
.Ic flash
|
|
857
|
+
and
|
|
858
|
+
.Ic reset .
|
|
859
|
+
Boards stay powered and are done in parallel, so it is much faster and
|
|
860
|
+
far less disruptive.
|
|
861
|
+
Aborts if any selected board lacks a serial=.
|
|
862
|
+
.It Cm power
|
|
863
|
+
Needs no configuration at all \(em it identifies a board by being the
|
|
864
|
+
only one powered \(em and is the fallback for a board whose serial= is
|
|
865
|
+
missing or wrong.
|
|
866
|
+
Slowest by far: every board costs a power cycle plus the warm\-up, so
|
|
867
|
+
the whole bench is sequential rounds.
|
|
868
|
+
It also leaves every switchable declared board POWERED OFF when it
|
|
869
|
+
finishes, because each port is switched off again after its turn.
|
|
870
|
+
A board whose port the configuration protects stays powered, and says so.
|
|
871
|
+
Run
|
|
872
|
+
.Ic usb on
|
|
873
|
+
afterwards to bring the bench back up.
|
|
874
|
+
.Pp
|
|
875
|
+
Because a protected or undeclared port stays powered, a probe on one
|
|
876
|
+
would be a second adapter in front of openocd, which then picks between
|
|
877
|
+
them by itself.
|
|
878
|
+
So once a board is powered, the run is refused if more than one probe
|
|
879
|
+
console is present: use serial, or \-\-force to power those ports down
|
|
880
|
+
too.
|
|
881
|
+
A probe that shows no CDC console cannot be counted.
|
|
882
|
+
.It Cm usb
|
|
883
|
+
What
|
|
884
|
+
.Ic connect
|
|
885
|
+
uses.
|
|
886
|
+
Addresses by USB topology, so it needs no serials.
|
|
887
|
+
On Linux the topology is read from /sys/bus/usb; on FreeBSD it is
|
|
888
|
+
walked out of the sysctl tree, which cannot see a device no driver has
|
|
889
|
+
claimed.
|
|
890
|
+
.El
|
|
891
|
+
.Pp
|
|
892
|
+
Each command accepts only the methods that make sense for it, and uses the
|
|
893
|
+
first as its default:
|
|
894
|
+
.Bd -literal
|
|
895
|
+
command methods accepted default
|
|
896
|
+
\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-
|
|
897
|
+
usb (none: acts on ports) n/a
|
|
898
|
+
serial usb, power usb
|
|
899
|
+
flash serial, power serial
|
|
900
|
+
reset serial serial
|
|
901
|
+
connect usb, serial usb
|
|
902
|
+
.Ed
|
|
903
|
+
.Pp
|
|
904
|
+
\-\-method usb derives the board's USB location from the hub's own geometry,
|
|
905
|
+
four banks of four:
|
|
906
|
+
.Bd -literal
|
|
907
|
+
port 5 ─┬─▸ bank 2 bank is (port minus 1) div 4, plus 1
|
|
908
|
+
└─▸ slot 1 slot is (port minus 1) mod 4, plus 1
|
|
909
|
+
|
|
910
|
+
hub root path ............. 1\-1.2
|
|
911
|
+
openocd adapter usb location 1\-1.2.2.1
|
|
912
|
+
└───┘ │ │
|
|
913
|
+
│ │ └── slot
|
|
914
|
+
│ └──── bank
|
|
915
|
+
└──────── hub root
|
|
916
|
+
.Ed
|
|
917
|
+
.Pp
|
|
918
|
+
That geometry is the ExSYS hub's own.
|
|
919
|
+
A usb hub has none to account for, so a port there is one component
|
|
920
|
+
below the hub's own path: a board on port 3 of the hub at 1\-1.1 is at
|
|
921
|
+
1\-1.1.3.
|
|
922
|
+
.Pp
|
|
923
|
+
The location is documentation of intent rather than a selector: openocd
|
|
924
|
+
0.12 ignores 'adapter usb location' for CMSIS\-DAP, reaching the same
|
|
925
|
+
adapter whichever path it is given, including one that does not exist.
|
|
926
|
+
What selects is 'adapter serial', which this method passes as well
|
|
927
|
+
whenever the configuration has one.
|
|
928
|
+
A board with no serial= is therefore
|
|
929
|
+
addressed by nothing in particular, and with more than one adapter
|
|
930
|
+
powered that is a board chosen at random.
|
|
931
|
+
.Pp
|
|
932
|
+
After any power\-on, \-W/\-\-warm\-up seconds (default 5) pass before the boards
|
|
933
|
+
are touched, to let them enumerate.
|
|
934
|
+
.Sh COMMANDS
|
|
935
|
+
Every command takes device names or port numbers interchangeably, and
|
|
936
|
+
operates on every board on the bench when given neither: each declared
|
|
937
|
+
device but those with port = none.
|
|
938
|
+
.Bl -tag -width Ds
|
|
939
|
+
.It Ic usb Cm status | on | off | toggle | set Oo Ar PORT | DEVNAME Oc ...
|
|
940
|
+
Drive hub port power directly.
|
|
941
|
+
\&'set' takes PORT:STATE pairs, where
|
|
942
|
+
STATE is any of on/off/1/0/true/false/t/f.
|
|
943
|
+
With no arguments, 'on'
|
|
944
|
+
means every port the hub has, while 'off' and 'toggle' mean every
|
|
945
|
+
switchable port (see PROTECTED PORTS).
|
|
946
|
+
On a hub whose
|
|
947
|
+
.Cm switch
|
|
948
|
+
is link, everything that powers down says so, naming the ports that
|
|
949
|
+
stay powered.
|
|
950
|
+
.Pp
|
|
951
|
+
\-\-default=BOOL sets what happens to ports 'set' does not name; it goes
|
|
952
|
+
before the word 'set'.
|
|
953
|
+
Without \-\-force it is applied only to
|
|
954
|
+
switchable ports, so it cannot sweep a protected port off.
|
|
955
|
+
\&'status' is read\-only: it asks the hub for its port states and prints
|
|
956
|
+
every port with its device name, its state, and whether the configuration
|
|
957
|
+
lets tribble\-control switch it.
|
|
958
|
+
Run it before anything involving
|
|
959
|
+
\-\-force.
|
|
960
|
+
Note that 'usb on' does not wait out \-\-warm\-up; it returns as soon as
|
|
961
|
+
the hub acknowledges.
|
|
962
|
+
.Pp
|
|
963
|
+
Selection method: none.
|
|
964
|
+
Exit status: 0, or 1 on error.
|
|
965
|
+
.It Ic serial Oo Ar PORT | DEVNAME Oc ...
|
|
966
|
+
Report each board's debug\-probe serial number, read from the USB
|
|
967
|
+
descriptor the kernel already holds.
|
|
968
|
+
Prints one line
|
|
969
|
+
per board, "Serial for alpha: 1026...".
|
|
970
|
+
Use it to populate the configuration.
|
|
971
|
+
.Pp
|
|
972
|
+
Selection methods: usb (default), power.
|
|
973
|
+
Under
|
|
974
|
+
.Cm usb
|
|
975
|
+
it powers the boards' own
|
|
976
|
+
ports up and leaves the rest of the bench alone \(em asking a board its
|
|
977
|
+
serial is not a reason to black out the hub.
|
|
978
|
+
.Cm power
|
|
979
|
+
is the fallback that needs no topology at all, at the price of cutting
|
|
980
|
+
the bench; see
|
|
981
|
+
.Sx TRAPS .
|
|
982
|
+
Exit status: 1 if any
|
|
983
|
+
board could not be read.
|
|
984
|
+
.Pp
|
|
985
|
+
The serial comes from the operating system rather than from openocd,
|
|
986
|
+
which does not report it: openocd 0.12 prints neither a CMSIS\-DAP
|
|
987
|
+
"Serial# =" line nor a J\-Link "S/N" one, at any debug level.
|
|
988
|
+
Asking
|
|
989
|
+
the OS also means no board has to be the only one powered, which
|
|
990
|
+
asking openocd would have required, since it cannot choose between
|
|
991
|
+
adapters by itself.
|
|
992
|
+
.It Ic flash Ar FIRMWARE Oo Ar PORT | DEVNAME Oc ...
|
|
993
|
+
openocd 'flash write_image erase FIRMWARE' then 'reset run', against
|
|
994
|
+
the board's target= script (nrf52 by default) over its interface=
|
|
995
|
+
script (cmsis\-dap by default), on its transport= (swd by default).
|
|
996
|
+
FIRMWARE is resolved by
|
|
997
|
+
openocd relative to the current directory, and is checked to be a
|
|
998
|
+
readable file before any port is switched.
|
|
999
|
+
Every selected board is attempted even if an earlier one failed; the
|
|
1000
|
+
exit status reflects the whole run.
|
|
1001
|
+
A board whose configuration entry lists after\-flash under power_cycle (see
|
|
1002
|
+
CONFIGURATION: the DWM1001\-DEV) has its port powered off and on again after
|
|
1003
|
+
a successful flash; \-\-power\-cycle, before FIRMWARE, does the same for
|
|
1004
|
+
any board.
|
|
1005
|
+
.Pp
|
|
1006
|
+
Selection methods: serial (default), power.
|
|
1007
|
+
Exit status: 1 if any
|
|
1008
|
+
board failed.
|
|
1009
|
+
.It Ic reset Oo Ar PORT | DEVNAME Oc ...
|
|
1010
|
+
openocd 'reset run'.
|
|
1011
|
+
.Pp
|
|
1012
|
+
Selection method: serial only, so it cannot address a board that has
|
|
1013
|
+
no serial= in the configuration.
|
|
1014
|
+
Exit status: 1 if any board failed.
|
|
1015
|
+
.It Ic connect Oo Ar PORT | DEVNAME Oc ...
|
|
1016
|
+
Open each board's CDC console at its baud= (default 230400) and
|
|
1017
|
+
stream it, prefixing every line with <DEVNAME>.
|
|
1018
|
+
Every line is also handed to the board's tally, and on exit each board
|
|
1019
|
+
prints a SUMMARY line with whatever that tally has to say.
|
|
1020
|
+
What the lines MEAN is not decided here \(em see
|
|
1021
|
+
.Sx TALLIES .
|
|
1022
|
+
.Pp
|
|
1023
|
+
Boards are streamed concurrently, one thread each, which is what
|
|
1024
|
+
makes a two\-way\-ranging capture meaningful; the "in sequence" in the
|
|
1025
|
+
method table above describes the order boards are set up in, not the
|
|
1026
|
+
monitoring.
|
|
1027
|
+
.Pp
|
|
1028
|
+
\-\-off powers down every declared board first, for a clean start \-\-
|
|
1029
|
+
every declared board, not only the ones named on the command line \-\-
|
|
1030
|
+
and then powers the selected ones back up.
|
|
1031
|
+
.Pp
|
|
1032
|
+
\-\-reset resets each board over SWD once its console is open.
|
|
1033
|
+
Without
|
|
1034
|
+
it you see only what a board says from the moment the reader attaches,
|
|
1035
|
+
which on an already\-running board is nothing at all until the next
|
|
1036
|
+
ranging exchange: the banner and the driver's init lines \(em including
|
|
1037
|
+
any "Failed to initialize" \(em were printed seconds after power\-on and
|
|
1038
|
+
are gone.
|
|
1039
|
+
Use it whenever you care about why a board is quiet, and
|
|
1040
|
+
note that \-\-off alone does NOT substitute: the port is powered back up
|
|
1041
|
+
before the console is opened, so boot output still escapes.
|
|
1042
|
+
.Pp
|
|
1043
|
+
\-\-duration=SECONDS bounds the capture; the default is 600.
|
|
1044
|
+
.Pp
|
|
1045
|
+
\-\-command=CMD types CMD at each board's shell once it is up (two
|
|
1046
|
+
seconds after a \-\-reset, half a second otherwise) and is the way to
|
|
1047
|
+
reach anything the firmware gates behind a run\-time setting.
|
|
1048
|
+
The
|
|
1049
|
+
case it exists for: redskin compiles spank's log level to warning,
|
|
1050
|
+
but the ranging results are logged at info, so a capture counts zero
|
|
1051
|
+
exchanges on a bench that is in fact working perfectly \-\-
|
|
1052
|
+
.Bd -literal
|
|
1053
|
+
\-\-command='spank syslog info' # the whole info stream
|
|
1054
|
+
\-\-command='spank report all' # just the distances, cheaper
|
|
1055
|
+
.Ed
|
|
1056
|
+
.Pp
|
|
1057
|
+
turns them on without reflashing.
|
|
1058
|
+
Prefer the second: the report path
|
|
1059
|
+
is written straight out by the port instead of going through the
|
|
1060
|
+
syslog, so it is not silenced by the compiled\-in level and costs the
|
|
1061
|
+
firmware less in a loop that is timing sensitive.
|
|
1062
|
+
It is sent once,
|
|
1063
|
+
to every selected board, on a separate write handle; the command is
|
|
1064
|
+
not echoed by tribble\-control, but the board's own echo and reply
|
|
1065
|
+
appear in the capture like any other output.
|
|
1066
|
+
Give it once \-\-
|
|
1067
|
+
repeating the option keeps only the last.
|
|
1068
|
+
ALWAYS run it under 'stdbuf \-oL' if you are piping the output
|
|
1069
|
+
anywhere.
|
|
1070
|
+
Without that, the pipe buffers in 4 KB blocks and 'tee'
|
|
1071
|
+
shows nothing for minutes.
|
|
1072
|
+
.Pp
|
|
1073
|
+
\-\-interactive is \-\-command without the limit of one command decided
|
|
1074
|
+
in advance: standard input is forwarded to the board, a line at a
|
|
1075
|
+
time, and the console stays open until end of input instead of for
|
|
1076
|
+
a \-\-duration.
|
|
1077
|
+
One device only \(em there is one standard input, and
|
|
1078
|
+
two boards sharing it could not be told apart or addressed
|
|
1079
|
+
separately.
|
|
1080
|
+
What the board replies appears in the stream like
|
|
1081
|
+
anything else, prefixed with its name, so what was typed and what
|
|
1082
|
+
came back read in order.
|
|
1083
|
+
It is meant to be run through a terminal \(em 'bench connect' opens it
|
|
1084
|
+
over ssh \-t, which is what supplies the editing and the echo of the
|
|
1085
|
+
line being typed; a pipe works too, and sends what it is given.
|
|
1086
|
+
.Pp
|
|
1087
|
+
\-\-tally=NAME reads every selected board's console with tally NAME
|
|
1088
|
+
for this run, whatever the configuration says; \-\-tally=DEV=NAME does
|
|
1089
|
+
so for board DEV alone.
|
|
1090
|
+
See
|
|
1091
|
+
.Sx TALLIES .
|
|
1092
|
+
.Pp
|
|
1093
|
+
A console that cannot be opened or read, or whose tally raises, prints
|
|
1094
|
+
.Dl <DEVNAME> ERROR: message
|
|
1095
|
+
instead of its SUMMARY line.
|
|
1096
|
+
.Pp
|
|
1097
|
+
Selection methods: usb (default), serial.
|
|
1098
|
+
Exit status:
|
|
1099
|
+
1 on error, or if any selected board's console was not found or could
|
|
1100
|
+
not be read; otherwise 0, which says nothing about what the boards
|
|
1101
|
+
printed.
|
|
1102
|
+
.El
|
|
1103
|
+
.Sh TALLIES
|
|
1104
|
+
.Nm
|
|
1105
|
+
opens a board's console, prefixes each line with the board's name and
|
|
1106
|
+
prints it.
|
|
1107
|
+
What a line MEANS it does not know, and deliberately does not: the
|
|
1108
|
+
strings worth counting belong to whatever firmware is on the bench this
|
|
1109
|
+
month, they change when that firmware changes, and none of them are
|
|
1110
|
+
facts about a USB hub.
|
|
1111
|
+
.Pp
|
|
1112
|
+
A tally is where that knowledge goes.
|
|
1113
|
+
.Ic connect
|
|
1114
|
+
hands it every line and asks it, once the capture ends, for the text of
|
|
1115
|
+
the board's SUMMARY line.
|
|
1116
|
+
Two come built in:
|
|
1117
|
+
.Bl -tag -width lines
|
|
1118
|
+
.It Cm lines
|
|
1119
|
+
How many lines the board printed.
|
|
1120
|
+
The default, and all a tool that knows nothing about the firmware can
|
|
1121
|
+
honestly say.
|
|
1122
|
+
.It Cm none
|
|
1123
|
+
Nothing: the lines are printed, and no SUMMARY follows them.
|
|
1124
|
+
.El
|
|
1125
|
+
.Pp
|
|
1126
|
+
Any other is a block, registered by a Ruby file named with
|
|
1127
|
+
.Fl r :
|
|
1128
|
+
.Bd -literal
|
|
1129
|
+
# twr-tally.rb
|
|
1130
|
+
class TwrTally
|
|
1131
|
+
def initialize(device) = @ok = 0
|
|
1132
|
+
def <<(line)
|
|
1133
|
+
@ok += 1 if line =~ /whatever this firmware calls success/
|
|
1134
|
+
self
|
|
1135
|
+
end
|
|
1136
|
+
def summary = "ok=#{@ok}"
|
|
1137
|
+
end
|
|
1138
|
+
|
|
1139
|
+
TribbleControl::Tally.register(:twr) {|device| TwrTally.new(device) }
|
|
1140
|
+
.Ed
|
|
1141
|
+
.Pp
|
|
1142
|
+
The object the block returns needs two methods:
|
|
1143
|
+
.Ic <<
|
|
1144
|
+
takes a line and returns anything, and
|
|
1145
|
+
.Ic summary
|
|
1146
|
+
returns the SUMMARY text, or nil for no SUMMARY line at all.
|
|
1147
|
+
The block is called once per board per run, so a tally may keep
|
|
1148
|
+
whatever state it likes without sharing it with another board's.
|
|
1149
|
+
.Pp
|
|
1150
|
+
Which tally a board uses is a configuration key.
|
|
1151
|
+
At the top of the file it sets the bench's default, and inside a device
|
|
1152
|
+
entry it overrides that for one board:
|
|
1153
|
+
.Bd -literal
|
|
1154
|
+
tally = twr # every board on this bench
|
|
1155
|
+
|
|
1156
|
+
D4 { port = 7, tally = lines } # except this one
|
|
1157
|
+
.Ed
|
|
1158
|
+
.Pp
|
|
1159
|
+
The configuration is about boards, not about what is flashed on them,
|
|
1160
|
+
so a run can override it.
|
|
1161
|
+
.Ic connect Fl \-tally Ns = Ns Ar NAME
|
|
1162
|
+
reads every selected board with NAME, and
|
|
1163
|
+
.Fl \-tally Ns = Ns Ar DEV Ns = Ns Ar NAME
|
|
1164
|
+
reads board DEV with NAME; DEV is a device name or a port number, as on
|
|
1165
|
+
the command line.
|
|
1166
|
+
The option may be repeated, or given a comma\-separated list, and every
|
|
1167
|
+
value counts:
|
|
1168
|
+
.Bd -literal
|
|
1169
|
+
connect \-\-tally twr \-\-tally D4=none # D4 runs the probe firmware
|
|
1170
|
+
connect \-\-tally twr,D4=none # the same
|
|
1171
|
+
.Ed
|
|
1172
|
+
.Pp
|
|
1173
|
+
For each board the first that applies wins: its DEV=NAME, the run's
|
|
1174
|
+
NAME, its own
|
|
1175
|
+
.Cm tally
|
|
1176
|
+
key (or its type's), the file's
|
|
1177
|
+
.Cm tally ,
|
|
1178
|
+
then
|
|
1179
|
+
.Cm lines .
|
|
1180
|
+
Two run\-wide names, two names for one board, a DEV the run does not
|
|
1181
|
+
capture, or an empty NAME (\-\-tally= or a doubled comma) are refused
|
|
1182
|
+
rather than resolved by order or left to the configuration.
|
|
1183
|
+
.Pp
|
|
1184
|
+
Every board's tally is built before a port is switched, so a name
|
|
1185
|
+
nothing has registered stops the run before \-\-off cuts the bench.
|
|
1186
|
+
A name nothing has registered is an error, not a silent fall back to
|
|
1187
|
+
counting lines: a configuration asking for twr on a run that forgot
|
|
1188
|
+
.Fl r
|
|
1189
|
+
would otherwise capture the whole bench and report line counts, which
|
|
1190
|
+
reads exactly like a firmware that has gone quiet.
|
|
1191
|
+
.Sh RECIPES
|
|
1192
|
+
Read the serials of every board, to fill in the configuration.
|
|
1193
|
+
This cycles the
|
|
1194
|
+
bench and leaves it powered off:
|
|
1195
|
+
.Bd -literal
|
|
1196
|
+
tribble\-control \-C tribble.conf serial
|
|
1197
|
+
tribble\-control \-C tribble.conf usb on
|
|
1198
|
+
.Ed
|
|
1199
|
+
.Pp
|
|
1200
|
+
Add a board on a new port.
|
|
1201
|
+
\&'serial 7' will not work: an undeclared port
|
|
1202
|
+
has no name, and the tool refuses to power ports the configuration never
|
|
1203
|
+
mentions.
|
|
1204
|
+
Declare a stub first, then read the serial and fill it in:
|
|
1205
|
+
.Bd -literal
|
|
1206
|
+
echo "X1 { port = 11 }" >> tribble.conf
|
|
1207
|
+
tribble\-control \-C tribble.conf serial X1
|
|
1208
|
+
.Ed
|
|
1209
|
+
.Pp
|
|
1210
|
+
Pick a port nothing else declares.
|
|
1211
|
+
Two entries on one port is refused at
|
|
1212
|
+
load time, for every command including 'usb status', so a collision here
|
|
1213
|
+
leaves the configuration unusable until it is edited back.
|
|
1214
|
+
.Pp
|
|
1215
|
+
Flash the whole bench, then just two boards:
|
|
1216
|
+
.Bd -literal
|
|
1217
|
+
tribble\-control \-C tribble.conf flash zephyr.hex
|
|
1218
|
+
tribble\-control \-C tribble.conf flash zephyr.hex alpha beta
|
|
1219
|
+
.Ed
|
|
1220
|
+
.Pp
|
|
1221
|
+
Flash in parallel, leaving the bench powered.
|
|
1222
|
+
Needs a serial for every
|
|
1223
|
+
board named, so fix the gaps first (see CONFIGURATION):
|
|
1224
|
+
.Bd -literal
|
|
1225
|
+
tribble\-control \-C tribble.conf \-\-method serial flash zephyr.hex
|
|
1226
|
+
.Ed
|
|
1227
|
+
.Pp
|
|
1228
|
+
Run a ranging capture to a log, for ten minutes:
|
|
1229
|
+
.Bd -literal
|
|
1230
|
+
stdbuf \-oL tribble\-control \-C tribble.conf connect \-\-off gamma epsilon \e
|
|
1231
|
+
| tee twr.log
|
|
1232
|
+
.Ed
|
|
1233
|
+
.Pp
|
|
1234
|
+
Find out why a board is silent \(em capture its boot, including the driver
|
|
1235
|
+
init lines, for one minute:
|
|
1236
|
+
.Bd -literal
|
|
1237
|
+
stdbuf \-oL tribble\-control \-C tribble.conf connect \-\-off \-\-reset \e
|
|
1238
|
+
\-\-duration=60 gamma beta | tee boot.log
|
|
1239
|
+
.Ed
|
|
1240
|
+
.Pp
|
|
1241
|
+
Capture ranging results from a stock redskin build.
|
|
1242
|
+
Without the command
|
|
1243
|
+
the log level hides them and the SUMMARY reads ok=0 / tx\-rate=NaN:
|
|
1244
|
+
.Bd -literal
|
|
1245
|
+
stdbuf \-oL tribble\-control \-C tribble.conf connect \-\-off \-\-reset \e
|
|
1246
|
+
\-\-command='spank syslog info' \-\-duration=60 gamma beta | tee twr.log
|
|
1247
|
+
.Ed
|
|
1248
|
+
.Pp
|
|
1249
|
+
Power\-cycle one board without disturbing the others:
|
|
1250
|
+
.Bd -literal
|
|
1251
|
+
tribble\-control \-C tribble.conf usb off gamma && sleep 2 && \e
|
|
1252
|
+
tribble\-control \-C tribble.conf usb on gamma
|
|
1253
|
+
.Ed
|
|
1254
|
+
.Pp
|
|
1255
|
+
Deliberately reboot a device on a protected port (the only case for
|
|
1256
|
+
\-\-force).
|
|
1257
|
+
This is a hard power cut; shut the device down over the
|
|
1258
|
+
network first:
|
|
1259
|
+
.Bd -literal
|
|
1260
|
+
tribble\-control \-C tribble.conf \-\-force usb off 14 && sleep 2 && \e
|
|
1261
|
+
tribble\-control \-C tribble.conf usb on 14
|
|
1262
|
+
.Ed
|
|
1263
|
+
.Pp
|
|
1264
|
+
Find out what a usb hub's 'off' really does, before writing
|
|
1265
|
+
\&'switch = vbus' in a configuration.
|
|
1266
|
+
Put a board whose LED lights up on a port, watch the LED, and cut that
|
|
1267
|
+
port:
|
|
1268
|
+
.Bd -literal
|
|
1269
|
+
tribble\-control \-\-hub usb \-C dock.conf usb status
|
|
1270
|
+
tribble\-control \-\-hub usb \-C dock.conf usb off gamma
|
|
1271
|
+
.Ed
|
|
1272
|
+
.Pp
|
|
1273
|
+
An LED that goes out is vbus; an LED that stays lit while the board
|
|
1274
|
+
disappears from the host is link.
|
|
1275
|
+
Do it on the socket the bench will actually use: the USB 2 and USB 3
|
|
1276
|
+
sides of one physical socket are different ports on different hubs, and
|
|
1277
|
+
a hub may switch neither.
|
|
1278
|
+
.Pp
|
|
1279
|
+
The script shipped as examples/vbus\-check runs that recipe: it takes
|
|
1280
|
+
the options you would give
|
|
1281
|
+
.Nm
|
|
1282
|
+
and the port, cuts the port for five seconds, restores it even on
|
|
1283
|
+
Ctrl\-C, and prints the 'switch =' line your answer implies.
|
|
1284
|
+
.Bd -literal
|
|
1285
|
+
examples/vbus\-check \-\-hub usb \-C dock.conf gamma
|
|
1286
|
+
examples/vbus\-check \-n \-\-hub usb \-d AC0528515619 \-F 2 # dry run
|
|
1287
|
+
.Ed
|
|
1288
|
+
.Pp
|
|
1289
|
+
List the switchable hubs this host has, to fill in 'device':
|
|
1290
|
+
.Bd -literal
|
|
1291
|
+
tribble\-control \-\-hub usb usb status
|
|
1292
|
+
.Ed
|
|
1293
|
+
.Pp
|
|
1294
|
+
With one candidate that command drives it.
|
|
1295
|
+
With two or more it refuses and lists them \(em serial, ugen name, USB
|
|
1296
|
+
path and port count \(em which is what to copy into the configuration.
|
|
1297
|
+
.Pp
|
|
1298
|
+
Flash from a script, failing the build if any board failed:
|
|
1299
|
+
.Bd -literal
|
|
1300
|
+
#!/bin/sh
|
|
1301
|
+
cd /root || exit 1
|
|
1302
|
+
exec tribble\-control \-C tribble.conf flash zephyr.hex
|
|
1303
|
+
.Ed
|
|
1304
|
+
.Sh TRAPS
|
|
1305
|
+
Exit status.
|
|
1306
|
+
Any command exits 1 if it aborts with an error \(em a refused
|
|
1307
|
+
power\-down, an unknown device name, a hub that answers E01.
|
|
1308
|
+
On top of
|
|
1309
|
+
that, flash, reset and serial exit 1 when they ran to completion but some
|
|
1310
|
+
board failed; usb and connect report nothing about the work itself, so a
|
|
1311
|
+
0 from 'connect' says only that it started.
|
|
1312
|
+
Beware that piping into
|
|
1313
|
+
\&'tee' hands you tee's status, not tribble\-control's \(em which is exactly
|
|
1314
|
+
what the capture recipe does, so do not use that shape in a script
|
|
1315
|
+
without a pipefail or a temporary file.
|
|
1316
|
+
.Pp
|
|
1317
|
+
\-\-method power leaves every switchable declared board powered off when
|
|
1318
|
+
it finishes.
|
|
1319
|
+
Nothing defaults to it any more: flash defaults to serial, reset is
|
|
1320
|
+
serial only, and serial and connect default to usb.
|
|
1321
|
+
You get it by asking
|
|
1322
|
+
for it with \-m power, and then you want 'usb on' afterwards to bring the
|
|
1323
|
+
bench back.
|
|
1324
|
+
.Pp
|
|
1325
|
+
connect stops after 600 seconds unless \-\-duration says otherwise; Ctrl\-C
|
|
1326
|
+
is the other way out of a shorter run.
|
|
1327
|
+
Under \-\-interactive there is no
|
|
1328
|
+
timer at all: it ends on end of input (Ctrl\-D) or on Ctrl\-C.
|
|
1329
|
+
.Pp
|
|
1330
|
+
A SUMMARY counting nothing is not proof that a board said nothing.
|
|
1331
|
+
A tally counts the strings one firmware prints, so the wrong tally on a
|
|
1332
|
+
board, or the right one on a firmware whose log level hides the lines,
|
|
1333
|
+
both report a healthy board as an idle one.
|
|
1334
|
+
Check which tally the board is using
|
|
1335
|
+
.Pq Sx TALLIES
|
|
1336
|
+
and that the firmware is logging at all before concluding the radio is
|
|
1337
|
+
dead; \-\-command is how a log level is raised at run time.
|
|
1338
|
+
.Pp
|
|
1339
|
+
\-\-debug is what makes a run verbose; the default is quiet.
|
|
1340
|
+
What it exists to reveal is the openocd command line issued for each
|
|
1341
|
+
board.
|
|
1342
|
+
\-\-debug=FILE also writes the log where it says.
|
|
1343
|
+
If you have a script that greps a run for its openocd invocations, it
|
|
1344
|
+
now has to ask for them.
|
|
1345
|
+
.Pp
|
|
1346
|
+
FreeBSD does everything Linux does, by different means, with one
|
|
1347
|
+
limit worth knowing.
|
|
1348
|
+
Nothing there states a USB path: it is walked out of the sysctl tree,
|
|
1349
|
+
each device's %location giving the port it occupies on its parent and
|
|
1350
|
+
%parent naming that parent, up to a root hub.
|
|
1351
|
+
Note also that openocd is not at
|
|
1352
|
+
/usr/bin/openocd there: pass \-\-openocd=/usr/local/bin/openocd, or just
|
|
1353
|
+
\-\-openocd=openocd and let PATH answer.
|
|
1354
|
+
.Pp
|
|
1355
|
+
The limit is that FreeBSD has no node for a device NO driver claimed
|
|
1356
|
+
\(em there is no dev.ugen \(em so such a device cannot be seen at all.
|
|
1357
|
+
A probe that enumerates and attaches nothing is invisible there rather
|
|
1358
|
+
than serial\-less, and
|
|
1359
|
+
.Fl m Cm usb
|
|
1360
|
+
will report no serial for it.
|
|
1361
|
+
Every probe the bench carries attaches something: a DAPLink is umodem,
|
|
1362
|
+
umass and usbhid at once, a J\-Link OB is umodem, and all of them
|
|
1363
|
+
report the device's serial.
|
|
1364
|
+
.Pp
|
|
1365
|
+
.Ic connect
|
|
1366
|
+
works anyway, with
|
|
1367
|
+
.Fl m Cm serial :
|
|
1368
|
+
the console is found by the serial of the probe in front of the board,
|
|
1369
|
+
which both a DAPLink and a J\-Link OB report, and which the configuration
|
|
1370
|
+
already carries in order to address that board for flashing.
|
|
1371
|
+
No USB tree is walked at all, on either host, which is what makes it
|
|
1372
|
+
the method to reach for when a topology is in doubt.
|
|
1373
|
+
.Pp
|
|
1374
|
+
.Ic serial
|
|
1375
|
+
works there too, with
|
|
1376
|
+
.Fl m Cm power .
|
|
1377
|
+
It has to identify a board it has no serial for yet, which is what
|
|
1378
|
+
.Cm power
|
|
1379
|
+
is for: it cuts every switchable port, brings up one board at a time,
|
|
1380
|
+
and the probe then enumerated is the only one there is.
|
|
1381
|
+
No topology, no descriptor path, nothing Linux has that FreeBSD has
|
|
1382
|
+
not.
|
|
1383
|
+
It costs a cycle of the whole bench and leaves it powered off \(em run
|
|
1384
|
+
.Ic usb on
|
|
1385
|
+
afterwards \(em which is why
|
|
1386
|
+
.Cm usb
|
|
1387
|
+
remains the default wherever the hub's USB path is known.
|
|
1388
|
+
.Pp
|
|
1389
|
+
A probe on a port the configuration protects stays powered through all of
|
|
1390
|
+
that, so it is enumerated alongside the board being asked.
|
|
1391
|
+
.Nm
|
|
1392
|
+
says so and stops rather than attributing one board's serial to
|
|
1393
|
+
another.
|
|
1394
|
+
.Pp
|
|
1395
|
+
\-\-method usb trusts the 4\-by\-4 geometry.
|
|
1396
|
+
A board on port 16 would resolve
|
|
1397
|
+
to 1\-1.2.4.4, which is where the FT232 control adapter already sits, so
|
|
1398
|
+
port 16 is not usable for a board addressed that way.
|
|
1399
|
+
.Pp
|
|
1400
|
+
Two hubs on one host are two benches, and only the configuration can tell
|
|
1401
|
+
them apart.
|
|
1402
|
+
Auto\-detection matches an FTDI 0403:6001, which every FT232 on the host
|
|
1403
|
+
is, so it is refused outright once there is more than one \(em name the
|
|
1404
|
+
hub with
|
|
1405
|
+
.Cm device
|
|
1406
|
+
in each configuration, by the serial of its FT232, and the command that
|
|
1407
|
+
already says which configuration says which hub as well.
|
|
1408
|
+
A command that reaches the wrong hub is not an error anywhere: the
|
|
1409
|
+
ports exist, the frames are accepted, and the boards that go dark are
|
|
1410
|
+
on the other bench.
|
|
1411
|
+
.Pp
|
|
1412
|
+
The hub password defaults to 'pass' (\-p/\-\-password to change it).
|
|
1413
|
+
It
|
|
1414
|
+
guards writes to the hub, not reads.
|
|
1415
|
+
.Pp
|
|
1416
|
+
\&'switch = link' means nothing restarts.
|
|
1417
|
+
A board on a port taken off the bus vanishes from the host exactly as a
|
|
1418
|
+
power cut would, so every command that powers down still works and
|
|
1419
|
+
\-\-method power still selects a board by being the only one visible \(em
|
|
1420
|
+
but the board keeps running and keeps its state.
|
|
1421
|
+
Every power\-down says so once, naming the ports that stay powered, and
|
|
1422
|
+
.Ic flash
|
|
1423
|
+
skips the after\-flash power cycle with a warning instead of pretending:
|
|
1424
|
+
a cycle that only re\-enumerates the probe would leave the board in the
|
|
1425
|
+
very state power_cycle exists to clear.
|
|
1426
|
+
.Pp
|
|
1427
|
+
The power bit is not the same bit on both kinds of hub.
|
|
1428
|
+
A USB 2 hub reports it in 0x0100 of wPortStatus; a SuperSpeed hub
|
|
1429
|
+
reports it in 0x0200 and puts the link state in bits 5\-8, so reading a
|
|
1430
|
+
SuperSpeed port with the USB 2 bit answers "unpowered" for a port that
|
|
1431
|
+
is fine.
|
|
1432
|
+
Which hub descriptor the hub ANSWERS \(em 0x29 or 0x2a \(em is what
|
|
1433
|
+
decides how its status word is read from then on.
|
|
1434
|
+
.Pp
|
|
1435
|
+
.Xr usbconfig 8
|
|
1436
|
+
exits 0 for a request the hub refused, printing REQUEST = <ERROR>, and
|
|
1437
|
+
exits 0 for a device it could not even find.
|
|
1438
|
+
The printed text is the truth; the status says nothing.
|
|
1439
|
+
.Pp
|
|
1440
|
+
A dock's hub chain may reset on its own.
|
|
1441
|
+
The pair of TUSB8041 hubs on the dock this was written against detached
|
|
1442
|
+
and re\-attached every few minutes under test, taking every board with
|
|
1443
|
+
them.
|
|
1444
|
+
A hub that flaps is a poor bench hub whatever its descriptor declares,
|
|
1445
|
+
and the tool cannot tell that apart from a bench somebody unplugged.
|
|
1446
|
+
.Pp
|
|
1447
|
+
The LED test is the only proof that a hub switches VBUS.
|
|
1448
|
+
The read\-back after a switch proves the hub did what it was told, not
|
|
1449
|
+
that the socket lost power: a hub with no power switch wired clears the
|
|
1450
|
+
bit and drops the link, reports itself unpowered, and leaves the board
|
|
1451
|
+
running.
|
|
1452
|
+
Watch a board's LED through 'usb off', on the socket the bench will
|
|
1453
|
+
use, and write the answer down as
|
|
1454
|
+
.Cm switch .
|
|
1455
|
+
.Sh FILES
|
|
1456
|
+
.Bl -tag -width /usr/bin/openocd
|
|
1457
|
+
.It Pa ./tribble-control.conf
|
|
1458
|
+
The configuration, used when
|
|
1459
|
+
.Fl C
|
|
1460
|
+
is not given and this file exists in the current directory.
|
|
1461
|
+
Named explicitly with
|
|
1462
|
+
.Fl C ,
|
|
1463
|
+
it may be at any path and under any name: it describes a bench rather
|
|
1464
|
+
than the tool, so it lives with whatever owns the bench.
|
|
1465
|
+
See
|
|
1466
|
+
.Sx CONFIGURATION .
|
|
1467
|
+
.It Pa /usr/bin/openocd
|
|
1468
|
+
The openocd binary, overridable with
|
|
1469
|
+
.Fl -openocd .
|
|
1470
|
+
.It Pa /usr/sbin/usbconfig
|
|
1471
|
+
How a usb hub is switched, and not overridable: this program switches
|
|
1472
|
+
benches, and what it runs must not depend on whoever's PATH it was
|
|
1473
|
+
started with.
|
|
1474
|
+
.It Pa /sbin/sysctl
|
|
1475
|
+
How the hubs of a
|
|
1476
|
+
.Fx
|
|
1477
|
+
host are found, read as 'sysctl \-e dev.uhub'.
|
|
1478
|
+
.El
|
|
1479
|
+
.Sh SEE ALSO
|
|
1480
|
+
.Xr openocd 1 ,
|
|
1481
|
+
.Xr usbconfig 8
|
|
1482
|
+
.Sh AUTHORS
|
|
1483
|
+
.An Stephane D'Alu Aq Mt sdalu@sdalu.com
|