oep-client-python 0.0.7__py3-none-any.whl → 0.0.8__py3-none-any.whl
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.
- oep_client/__init__.py +1 -1
- oep_client/endpoint.py +65 -14
- oep_client/fake.py +23 -2
- oep_client/registry.py +4 -4
- oep_client/riscv.py +20 -7
- {oep_client_python-0.0.7.dist-info → oep_client_python-0.0.8.dist-info}/METADATA +1 -1
- {oep_client_python-0.0.7.dist-info → oep_client_python-0.0.8.dist-info}/RECORD +10 -10
- {oep_client_python-0.0.7.dist-info → oep_client_python-0.0.8.dist-info}/WHEEL +0 -0
- {oep_client_python-0.0.7.dist-info → oep_client_python-0.0.8.dist-info}/entry_points.txt +0 -0
- {oep_client_python-0.0.7.dist-info → oep_client_python-0.0.8.dist-info}/licenses/LICENSE +0 -0
oep_client/__init__.py
CHANGED
oep_client/endpoint.py
CHANGED
|
@@ -254,15 +254,26 @@ class Endpoint:
|
|
|
254
254
|
self.pairs: dict[int, list[tuple[int, int]]] = {} # wire fn -> allowed (swdio, swclk), declared order
|
|
255
255
|
self.max_connections: dict[int, int] = {}
|
|
256
256
|
self.reset_channels: dict[int, set[int]] = {} # wire fn -> channels attach_under_reset may take (role 3)
|
|
257
|
+
self.pin_roles: dict[int, dict[int, set[int]]] = {} # wire fn -> role -> candidates (role_channels wires)
|
|
257
258
|
for fn, name in self.names.items():
|
|
258
259
|
if name in WIRES:
|
|
259
260
|
self.pairs[fn] = [self._group_pair(name, t) for t in self.static[fn] if t[0] == catalog.CHANNEL_GROUP]
|
|
261
|
+
roles: dict[int, set[int]] = {}
|
|
262
|
+
for t in self.static[fn]:
|
|
263
|
+
if t[0] == catalog.ROLE_CHANNELS and t[2] in (1, 2):
|
|
264
|
+
roles.setdefault(t[2], set()).update(
|
|
265
|
+
catalog.bitmap_to_channels(struct.unpack_from("<H", t, 3)[0], t[5:2 + t[1]]))
|
|
266
|
+
if roles:
|
|
267
|
+
self.pin_roles[fn] = roles
|
|
260
268
|
self.reset_channels[fn] = {
|
|
261
269
|
c for t in self.static[fn] if t[0] == catalog.ROLE_CHANNELS and t[2] == PIN_ROLE_RESET
|
|
262
270
|
for c in catalog.bitmap_to_channels(struct.unpack_from("<H", t, 3)[0], t[5:2 + t[1]])}
|
|
263
271
|
self.max_connections[fn] = next((t[2] for t in self.static[fn] if t[0] == fake.MAX_CONNECTIONS), 1)
|
|
264
272
|
self.targets: dict[tuple[int, tuple[int, int]], FakeTarget] = {
|
|
265
273
|
(fn, p): FakeTarget() for fn in sorted(self.pairs) for p in self.pairs[fn]}
|
|
274
|
+
for fn in sorted(self.pin_roles): # any pair: one target, on the first pair
|
|
275
|
+
first = self._role_pairs(fn)[0]
|
|
276
|
+
self.targets[(fn, first)] = FakeTarget()
|
|
266
277
|
self.target = next(iter(self.targets.values()), FakeTarget())
|
|
267
278
|
self.mechanisms = set()
|
|
268
279
|
for fn, name in self.names.items():
|
|
@@ -329,6 +340,38 @@ class Endpoint:
|
|
|
329
340
|
def target_id(self, value: int | None) -> None:
|
|
330
341
|
self.target.target_id = value
|
|
331
342
|
|
|
343
|
+
def _role_pairs(self, fn: int) -> list[tuple[int, int]]:
|
|
344
|
+
"""A role_channels wire's pairs in the count = 0 order (oep-if-debug §1): swdio ascending, then swclk."""
|
|
345
|
+
roles = self.pin_roles[fn]
|
|
346
|
+
if self.names[fn] == "oep.wire.swio":
|
|
347
|
+
return [(d, 0xFFFF) for d in sorted(roles.get(1, ()))]
|
|
348
|
+
return [(d, c) for d in sorted(roles.get(1, ())) for c in sorted(roles.get(2, ())) if d != c]
|
|
349
|
+
|
|
350
|
+
def _allowed_pairs(self, fn: int) -> list[tuple[int, int]]:
|
|
351
|
+
return self._role_pairs(fn) if fn in self.pin_roles else self.pairs.get(fn, [])
|
|
352
|
+
|
|
353
|
+
def _allows(self, fn: int, pair: tuple[int, int]) -> bool:
|
|
354
|
+
if fn in self.pin_roles:
|
|
355
|
+
roles = self.pin_roles[fn]
|
|
356
|
+
swio = self.names[fn] == "oep.wire.swio"
|
|
357
|
+
return pair[0] in roles.get(1, ()) and (pair[1] == 0xFFFF if swio else
|
|
358
|
+
pair[1] in roles.get(2, ()) and pair[1] != pair[0])
|
|
359
|
+
return pair in self.pairs.get(fn, [])
|
|
360
|
+
|
|
361
|
+
def _held(self, fn: int | None = None, pair: tuple[int, int] | None = None) -> set[int]:
|
|
362
|
+
"""Channels something holds (core §8.1): the plan, the slots' pairs, the live connections' pairs - except
|
|
363
|
+
wire `fn`'s own connection on `pair` (attaching there again, or scanning through it)."""
|
|
364
|
+
held = {a[2] for a in self.plan}
|
|
365
|
+
held |= {p for s in self.slots.values() for p in s.pair if p != 0xFFFF and not (s.wire_fn == fn and s.pair == pair)}
|
|
366
|
+
held |= {p for c in self.conns.values() for p in c.pair if p != 0xFFFF and not (c.fn == fn and c.pair == pair)}
|
|
367
|
+
return held
|
|
368
|
+
|
|
369
|
+
def _target(self, fn: int, pair: tuple[int, int]) -> FakeTarget:
|
|
370
|
+
tg = self.targets.get((fn, pair))
|
|
371
|
+
if tg is None: # a pair nothing is wired to
|
|
372
|
+
tg = self.targets[(fn, pair)] = FakeTarget(present=False)
|
|
373
|
+
return tg
|
|
374
|
+
|
|
332
375
|
@staticmethod
|
|
333
376
|
def _group_pair(name: str, t: bytes) -> tuple[int, int]:
|
|
334
377
|
roles = {t[3 + 3 * i]: struct.unpack_from("<H", t, 4 + 3 * i)[0] for i in range((t[1] - 1) // 3)}
|
|
@@ -603,6 +646,7 @@ class Endpoint:
|
|
|
603
646
|
named = {fn for fn, _, _ in got}
|
|
604
647
|
kept = {a for a in self.plan if a[0] not in named}
|
|
605
648
|
slot_pins = {p for s in self.slots.values() for p in s.pair if p != 0xFFFF}
|
|
649
|
+
slot_pins |= {p for c in self.conns.values() for p in c.pair if p != 0xFFFF} # a live connection's pins too
|
|
606
650
|
for fn, role, ch in got:
|
|
607
651
|
roles = {"oep.fixture.gpio": {1}, "oep.fixture.uart": {1, 2}}.get(self.names.get(fn, ""), set())
|
|
608
652
|
if role not in roles or any(k[2] == ch for k in kept) or ch in slot_pins:
|
|
@@ -646,17 +690,24 @@ class Endpoint:
|
|
|
646
690
|
|
|
647
691
|
# ---- oep.wire.rvswd / swio ------------------------------------------------------------------
|
|
648
692
|
def _wire(self, fn: int, op: int, t: Take) -> tuple[int, int, bytes]:
|
|
649
|
-
allowed = self.pairs.get(fn, [])
|
|
650
693
|
if op == 0x01: # scan: count(u8) pairs -> tried count found...
|
|
651
694
|
count = t.take("B")
|
|
652
695
|
pairs = [t.take("HH") for _ in range(count)]
|
|
653
|
-
t.tail()
|
|
654
|
-
if
|
|
655
|
-
raise Reject(m.
|
|
656
|
-
|
|
696
|
+
got, _ = t.tail({0x01})
|
|
697
|
+
if 0x01 in got and (count or len(got[0x01]) != 2):
|
|
698
|
+
raise Reject(m.MALFORMED) # skip goes with count 0 only
|
|
699
|
+
live = [c.pair for c in self.conns.values() if c.fn == fn]
|
|
700
|
+
full = len(live) >= self.max_connections.get(fn, 1) # every seat taken: the live pairs only
|
|
701
|
+
if any(not self._allows(fn, p) or set(p) & self._held(fn, p) or (full and p not in live) for p in pairs):
|
|
702
|
+
raise Reject(m.UNAVAILABLE) # not allowed, held (§8.1), or no seat to try it on
|
|
703
|
+
if not pairs: # the count-0 list, from `skip` on (oep-if-debug §1)
|
|
704
|
+
skip = struct.unpack("<H", got[0x01])[0] if 0x01 in got else 0
|
|
705
|
+
pairs = [p for p in self._allowed_pairs(fn)
|
|
706
|
+
if not set(p) & self._held(fn, p) and (not full or p in live)][skip:]
|
|
707
|
+
pairs = pairs[:255] # tried is a u8
|
|
657
708
|
found = []
|
|
658
709
|
for p in pairs:
|
|
659
|
-
tg = self.
|
|
710
|
+
tg = self._target(fn, p)
|
|
660
711
|
if tg.present: # a live connection's pair: read over it, no restart
|
|
661
712
|
found.append(struct.pack("<BHHI", 1, *p, tg.dmstatus()))
|
|
662
713
|
return m.COMPLETED, m.SUCCESS, struct.pack("<BB", len(pairs), len(found)) + b"".join(found)
|
|
@@ -675,7 +726,7 @@ class Endpoint:
|
|
|
675
726
|
raise Reject(m.MALFORMED)
|
|
676
727
|
idle_clock = got[0x04][0] if 0x04 in got else 0
|
|
677
728
|
pair = self._pick_pair(fn, got)
|
|
678
|
-
tg = self.
|
|
729
|
+
tg = self._target(fn, pair)
|
|
679
730
|
speed = min(4_000_000, struct.unpack("<I", got[0x01])[0]) if 0x01 in got else 4_000_000
|
|
680
731
|
cid = self._conn_at(fn, pair)
|
|
681
732
|
flags = 0
|
|
@@ -729,14 +780,14 @@ class Endpoint:
|
|
|
729
780
|
return m.REJECTED, m.UNKNOWN_OPERATION, b""
|
|
730
781
|
|
|
731
782
|
def _pick_pair(self, fn: int, got: dict[int, bytes]) -> tuple[int, int]:
|
|
732
|
-
allowed = self.pairs.get(fn, [])
|
|
733
783
|
if 0x03 in got:
|
|
734
784
|
if len(got[0x03]) != 4:
|
|
735
785
|
raise Reject(m.MALFORMED)
|
|
736
786
|
pair = struct.unpack("<HH", got[0x03])
|
|
737
|
-
if pair
|
|
738
|
-
raise Reject(m.UNAVAILABLE) #
|
|
787
|
+
if not self._allows(fn, pair) or set(pair) & self._held(fn, pair):
|
|
788
|
+
raise Reject(m.UNAVAILABLE) # not allowed here, or its pins are held (§8.1)
|
|
739
789
|
return pair
|
|
790
|
+
allowed = self._allowed_pairs(fn)
|
|
740
791
|
if len(allowed) != 1:
|
|
741
792
|
raise Reject(m.UNAVAILABLE) # the host chooses among several
|
|
742
793
|
return allowed[0]
|
|
@@ -779,7 +830,7 @@ class Endpoint:
|
|
|
779
830
|
|
|
780
831
|
def _target_of(self, cid: int) -> FakeTarget:
|
|
781
832
|
c = self.conns[cid]
|
|
782
|
-
return self.
|
|
833
|
+
return self._target(c.fn, c.pair)
|
|
783
834
|
|
|
784
835
|
# ---- oep.target.riscv-dm --------------------------------------------------------------------
|
|
785
836
|
@staticmethod
|
|
@@ -1181,7 +1232,7 @@ class Endpoint:
|
|
|
1181
1232
|
places = [(s.wire_fn, s.pair) for s in slots.values()]
|
|
1182
1233
|
if len(set(places)) != len(places):
|
|
1183
1234
|
raise Reject(m.UNAVAILABLE)
|
|
1184
|
-
for fn in self.pairs:
|
|
1235
|
+
for fn in self.pairs: # every wire (pin_roles wires have an empty list)
|
|
1185
1236
|
if sum(1 for s in slots.values() if s.wire_fn == fn and s.attach == SLOT_ATTACH["at_boot"]) > \
|
|
1186
1237
|
self.max_connections.get(fn, 1):
|
|
1187
1238
|
raise Reject(m.UNAVAILABLE)
|
|
@@ -1244,7 +1295,7 @@ class Endpoint:
|
|
|
1244
1295
|
raise Reject(m.MALFORMED)
|
|
1245
1296
|
if not SLOT_NAME.fullmatch(name.decode("ascii", "replace")):
|
|
1246
1297
|
raise Reject(m.MALFORMED)
|
|
1247
|
-
if self.names.get(wire_fn) not in WIRES or
|
|
1298
|
+
if self.names.get(wire_fn) not in WIRES or not self._allows(wire_fn, (swdio, swclk)):
|
|
1248
1299
|
raise Reject(m.UNAVAILABLE)
|
|
1249
1300
|
if mech not in self.mechanisms:
|
|
1250
1301
|
raise Reject(m.UNSUPPORTED)
|
|
@@ -1301,7 +1352,7 @@ class Endpoint:
|
|
|
1301
1352
|
s = self.slots[n]
|
|
1302
1353
|
rt = self.slot_rt[n]
|
|
1303
1354
|
rt.last_try_ms = self.now()
|
|
1304
|
-
tg = self.
|
|
1355
|
+
tg = self._target(s.wire_fn, s.pair)
|
|
1305
1356
|
cid = self._conn_at(s.wire_fn, s.pair)
|
|
1306
1357
|
if cid is None:
|
|
1307
1358
|
if not tg.present:
|
oep_client/fake.py
CHANGED
|
@@ -139,7 +139,8 @@ def _core(firmware: str, model: str, unit_id: bytes, channels: int, reserved: li
|
|
|
139
139
|
return Offered(0, 0, "oep.core", (
|
|
140
140
|
catalog.text(CORE_FIRMWARE, firmware), catalog.text(CORE_MODEL, model), catalog.tlv(CORE_UNIT_ID, unit_id),
|
|
141
141
|
catalog.u16(CORE_CHANNELS, channels), catalog.tlv(CORE_RESERVED, struct.pack("<H", base) + bits),
|
|
142
|
-
catalog.text(CORE_PROFILE, profile)) + tuple(_label(c, n) for c, n in labels.items())
|
|
142
|
+
) + ((catalog.text(CORE_PROFILE, profile),) if profile else ()) + tuple(_label(c, n) for c, n in labels.items())
|
|
143
|
+
+ extra)
|
|
143
144
|
|
|
144
145
|
|
|
145
146
|
def p4_x035() -> FakeProbe:
|
|
@@ -230,4 +231,24 @@ def p4_bench() -> FakeProbe:
|
|
|
230
231
|
])
|
|
231
232
|
|
|
232
233
|
|
|
233
|
-
|
|
234
|
+
def rp2350_pins() -> FakeProbe:
|
|
235
|
+
"""A board firmware whose wire takes its pins from the host (oep-if-debug §1, role_channels): any two of GP0-GP29
|
|
236
|
+
but GP19 (the Pro Micro RP2350's PSRAM CS) are an RVSWD pair, a reset line or fixture pins. USB CDC (serial port 0).
|
|
237
|
+
The fake target answers on (0, 1), the first pair."""
|
|
238
|
+
reserved = [19]
|
|
239
|
+
pins = [p for p in range(30) if p not in reserved]
|
|
240
|
+
return FakeProbe("rp2350-pins", 1024, [
|
|
241
|
+
_core("3.0.0", "sparkfun-promicro-rp2350", bytes.fromhex("e66138935f2b1f2c"), 30, reserved, "",
|
|
242
|
+
{}, _transports([(TRANSPORT["usb_cdc"], 0)])),
|
|
243
|
+
Offered(1, 1, "oep.wire.rvswd", _roles({1: pins, 2: pins, 3: pins}) + (
|
|
244
|
+
catalog.u32(MAX_CLOCK_HZ, 5_000_000), catalog.u8(IMPLEMENTATION, 1), catalog.u8(MAX_CONNECTIONS, 1))),
|
|
245
|
+
Offered(2, 1, "oep.target.riscv-dm", (catalog.u32(FEATURES, 0b1111), catalog.u8(IMPLEMENTATION, 1),
|
|
246
|
+
catalog.u16(MAX_LENGTH, 1000))),
|
|
247
|
+
Offered(3, 1, "oep.target.console", (catalog.tlv(MECHANISMS, bytes([0, 1, 2])),)),
|
|
248
|
+
Offered(4, 2, "oep.fixture.gpio", _roles({1: pins})),
|
|
249
|
+
Offered(5, 3, "oep.fixture.uart", _roles({1: pins, 2: pins}) + (
|
|
250
|
+
catalog.u32(MAX_CLOCK_HZ, 3_000_000), catalog.u8(IMPLEMENTATION, 2))),
|
|
251
|
+
])
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
PROFILES = {"p4-x035": p4_x035, "esp32-v003": esp32_v003, "p4-bench": p4_bench, "rp2350-pins": rp2350_pins}
|
oep_client/registry.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from types import SimpleNamespace as _NS
|
|
4
4
|
|
|
5
|
-
REGISTRY_HASH = "
|
|
5
|
+
REGISTRY_HASH = "08b7d1656bf59269"
|
|
6
6
|
SCHEMA = 1
|
|
7
7
|
PROTOCOL_REVISION = 1
|
|
8
8
|
CONFIRM_REQUEST_MAGIC = 'OEP?'
|
|
@@ -25,13 +25,13 @@ CORE = _NS(name="oep.core", revision=1, op={"confirm": 0x01, "list": 0x02, "desc
|
|
|
25
25
|
closed_tail={0x40}, tlv={"plan_apply": {"role_assignment": 0x90}, "open": {"owner": 0x01}, "lock_state_answer": {"owner": 0x01}, "locked_payload": {"owner": 0x01}, "describe": {"firmware": 0x40, "model": 0x41, "unit_id": 0x42, "channels": 0x43, "reserved": 0x44, "profile": 0x45, "label": 0x46, "resets_on_open": 0x47, "transport": 0x49, "oep_pid": 0x4A, "plan_roles": 0x4B}}, event={"heartbeat": 0x01}, enum={"transport_kind": {"uart_bridge": 0x01, "usb_cdc": 0x02, "usb_serial_jtag": 0x03, "vendor_bulk": 0x04, "hid": 0x05, "tcp": 0x06}}, own={})
|
|
26
26
|
INTERFACES["oep.core"] = CORE
|
|
27
27
|
WIRE_RVSWD = _NS(name="oep.wire.rvswd", revision=1, op={"scan": 0x01, "attach": 0x02, "detach": 0x03, "attach_under_reset": 0x04, "connections": 0x05}, lock_free={0x05},
|
|
28
|
-
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "pins": 0x03, "idle_clock": 0x04}, "attach_under_reset": {"max_speed": 0x01, "pins": 0x03, "idle_clock": 0x04}, "attach_answer": {"target_id": 0x10}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "target_id_scheme": {"wch_dmi_7f": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "swclk": 0x02, "reset": 0x03}, "idle_clock": {"high": 0x00, "low": 0x01}}, own={})
|
|
28
|
+
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "scan": {"skip": 0x01}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "pins": 0x03, "idle_clock": 0x04}, "attach_under_reset": {"max_speed": 0x01, "pins": 0x03, "idle_clock": 0x04}, "attach_answer": {"target_id": 0x10}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "target_id_scheme": {"wch_dmi_7f": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "swclk": 0x02, "reset": 0x03}, "idle_clock": {"high": 0x00, "low": 0x01}}, own={})
|
|
29
29
|
INTERFACES["oep.wire.rvswd"] = WIRE_RVSWD
|
|
30
30
|
WIRE_SWIO = _NS(name="oep.wire.swio", revision=1, op={"scan": 0x01, "attach": 0x02, "detach": 0x03, "attach_under_reset": 0x04, "connections": 0x05}, lock_free={0x05},
|
|
31
|
-
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "pins": 0x03}, "attach_under_reset": {"max_speed": 0x01, "pins": 0x03}, "attach_answer": {"target_id": 0x10}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "target_id_scheme": {"wch_dmi_7f": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "reset": 0x03}}, own={})
|
|
31
|
+
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "scan": {"skip": 0x01}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "pins": 0x03}, "attach_under_reset": {"max_speed": 0x01, "pins": 0x03}, "attach_answer": {"target_id": 0x10}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "target_id_scheme": {"wch_dmi_7f": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "reset": 0x03}}, own={})
|
|
32
32
|
INTERFACES["oep.wire.swio"] = WIRE_SWIO
|
|
33
33
|
WIRE_SWD = _NS(name="oep.wire.swd", revision=1, op={"scan": 0x01, "attach": 0x02, "detach": 0x03, "connections": 0x05}, lock_free={0x05},
|
|
34
|
-
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "targetsel": 0x02, "pins": 0x03}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "pin_role": {"swdio": 0x01, "swclk": 0x02}}, own={})
|
|
34
|
+
closed_tail={}, tlv={"describe": {"max_connections": 0x40}, "scan": {"skip": 0x01}, "detach": {"force": 0x01}, "attach": {"max_speed": 0x01, "targetsel": 0x02, "pins": 0x03}}, event={}, enum={"connection_users": {"host_session": 0x01, "slot": 0x02}, "pin_role": {"swdio": 0x01, "swclk": 0x02}}, own={})
|
|
35
35
|
INTERFACES["oep.wire.swd"] = WIRE_SWD
|
|
36
36
|
TARGET_RISCV_DM = _NS(name="oep.target.riscv-dm", revision=1, op={"dmi": 0x01, "halt": 0x02, "resume": 0x03, "reset": 0x04, "read_block": 0x05, "write_block": 0x06, "run": 0x07, "step": 0x08}, lock_free={},
|
|
37
37
|
closed_tail={}, tlv={"describe": {}, "reset": {"method": 0x01}}, event={}, enum={"dmi_step": {"write": 0x01, "read": 0x02, "poll_reads": 0x03, "wait_us": 0x04, "poll_us": 0x05}, "reset_mode": {"run": 0x00, "run_verified": 0x01, "halt_at_reset": 0x02}, "reset_method": {"probe_default": 0x00, "ndmreset": 0x01, "system_reset": 0x02}}, own={})
|
oep_client/riscv.py
CHANGED
|
@@ -76,23 +76,36 @@ class WireBase(Interface):
|
|
|
76
76
|
TAG_MAX_SPEED = 0x01
|
|
77
77
|
TAG_PINS = 0x03 # swdio(u16) swclk(u16, 0xFFFF on one wire), critical (oep-if-debug §1)
|
|
78
78
|
|
|
79
|
+
TAG_SKIP = 0x01 # scan, count 0 only: pairs of the count-0 list to skip (oep-if-debug §1)
|
|
80
|
+
|
|
79
81
|
def scan(self, pairs: list[tuple[int, int]] | None = None) -> list[Found]:
|
|
80
|
-
"""Try `pairs` of (swdio, swclk); None = every pair the probe allows (describe's
|
|
81
|
-
role_channels). A pair the probe does not allow
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
"""Try `pairs` of (swdio, swclk); None = every pair the probe allows and nothing holds (describe's
|
|
83
|
+
channel_group / role_channels, oep-if-debug §1). A pair the probe does not allow, or one whose pins something
|
|
84
|
+
holds, refuses the whole scan (rejected unavailable). The probe tries at most 255 pairs a request and stops early
|
|
85
|
+
when its answer would not fit one frame; this goes on until every pair is tried (count 0: with skip until
|
|
86
|
+
tried = 0)."""
|
|
84
87
|
out = []
|
|
88
|
+
pairs = list(pairs or [])
|
|
89
|
+
skip = 0
|
|
85
90
|
while True:
|
|
86
|
-
|
|
91
|
+
chunk = pairs[:255]
|
|
92
|
+
body = bytes([len(chunk)]) + b"".join(struct.pack("<HH", d, c) for d, c in chunk)
|
|
93
|
+
if not pairs and skip:
|
|
94
|
+
body += m.tlv(self.TAG_SKIP, struct.pack("<H", skip))
|
|
87
95
|
rd = m.Reader(self._call(self.SCAN, body).payload)
|
|
88
96
|
tried, count = rd.take("BB")
|
|
89
97
|
for _ in range(count):
|
|
90
98
|
kind, dio, clk, status = rd.take("BHHI")
|
|
91
99
|
out.append(Found(kind, (dio, clk), status))
|
|
92
100
|
rd.tail()
|
|
93
|
-
if
|
|
101
|
+
if tried == 0:
|
|
94
102
|
return out
|
|
95
|
-
|
|
103
|
+
if pairs:
|
|
104
|
+
pairs = pairs[tried:]
|
|
105
|
+
if not pairs:
|
|
106
|
+
return out
|
|
107
|
+
else:
|
|
108
|
+
skip += tried
|
|
96
109
|
|
|
97
110
|
def detach(self, conn: int) -> None:
|
|
98
111
|
self._call(self.DETACH, struct.pack("<H", conn))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: oep-client-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a fake probe
|
|
5
5
|
Project-URL: Homepage, https://github.com/Open-Embedded-Probe/oep-client-python
|
|
6
6
|
Project-URL: Repository, https://github.com/Open-Embedded-Probe/oep-client-python
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
oep_client/__init__.py,sha256=
|
|
1
|
+
oep_client/__init__.py,sha256=6mobCxy7gb0xBip7N4wVAbSsDJZjvzzWtMDUU5jpXu8,163
|
|
2
2
|
oep_client/__main__.py,sha256=qtVGdpAHULBtLY2SedabJf-uwDZZhMf_YmrbqRzM57U,14669
|
|
3
3
|
oep_client/arm.py,sha256=JLyUhLSPcmsk73schZcaJYoOKuHzrvnU8kPmfrEvVuo,12331
|
|
4
4
|
oep_client/capture.py,sha256=hs8mQU1gE1P67GOivxw2C2Ur8wimWqCdhtk1nqGN71Q,18092
|
|
@@ -10,9 +10,9 @@ oep_client/console.py,sha256=YYcuc9Qxe3kihla8wynYbDaLVr7wBLEvswrM-cMK3Tk,6859
|
|
|
10
10
|
oep_client/core.py,sha256=Cyyaknjipkg6tS76dZe5GMqjmOoQjlfeP0WFtMHkJNs,10403
|
|
11
11
|
oep_client/decode.py,sha256=M-bRARrA2qGZLoJn0BdXeTb4WjL_2Hb2nk_g1IGXIw4,2382
|
|
12
12
|
oep_client/dump.py,sha256=GAnmu2abuDmGmbWcbbEfC3EUuPp5Hady9vQVNcQ-724,6743
|
|
13
|
-
oep_client/endpoint.py,sha256=
|
|
13
|
+
oep_client/endpoint.py,sha256=Cmzrjsrv--70cUu2UVNpJ0RZVJesV9DNJweg1jOYe0s,77818
|
|
14
14
|
oep_client/esp32_targets.py,sha256=b8tNH-nb2KC-XgNfWg5l3TO0cyhZOF-gJajaVxNVSGQ,4988
|
|
15
|
-
oep_client/fake.py,sha256=
|
|
15
|
+
oep_client/fake.py,sha256=oaEMn0cjIalcQKPQ2mZ5KL-E6U_43Ppr3-dj96dS7Q0,14513
|
|
16
16
|
oep_client/fake_serial.py,sha256=uKl0UNcifhdeykQtm8gnRRhqV7TT4vPwBFuBhbf-9BI,4504
|
|
17
17
|
oep_client/fake_serve.py,sha256=Ke_hGRiOayCyut-uYOa0PaOFzy-zlvPHGwjs4HEZkAQ,14644
|
|
18
18
|
oep_client/fixture.py,sha256=653hCD-Iz0Lfs8dT4Hdg3QyubbbOGs1_xjq_3nb8foU,5564
|
|
@@ -23,14 +23,14 @@ oep_client/interfaces.py,sha256=TNvof5blyLjO1Mc0OentKcMVBD_5e4riRG18UgEh2ZE,5380
|
|
|
23
23
|
oep_client/link.py,sha256=J9VtBWfTgNoIgUQuj8SsH9hHesQM2uEN545IoxKVS8E,19406
|
|
24
24
|
oep_client/message.py,sha256=MEM1UT6KFM7AsT56jvBLt_FJK_6SJ7O_nGAiipW0_zo,9912
|
|
25
25
|
oep_client/names.py,sha256=ztCZFWs__aR-a5G14TnJP-Q4YfLhbyrzvOVOMJuG93k,3653
|
|
26
|
-
oep_client/registry.py,sha256=
|
|
27
|
-
oep_client/riscv.py,sha256=
|
|
26
|
+
oep_client/registry.py,sha256=6FVVEs1b6krGygH21zma84mmMB_B65dh8S7PrjYrME0,10056
|
|
27
|
+
oep_client/riscv.py,sha256=H9kE_oUsnaBzqdTXDAVgDQkDvsrn5ZwsVi8dF1W_BDM,23117
|
|
28
28
|
oep_client/rp2350.py,sha256=7OMyj270k3AY1e3-ljicPwOjf9jOlokbT6QNkA0b0yY,4227
|
|
29
29
|
oep_client/target.py,sha256=R8BvYfFfYNhZF0MysJkNb8b69YgBlmeGXNX8ReZIe5k,1068
|
|
30
30
|
oep_client/uiapduino.py,sha256=IEPG3LbZPksi8g3wmAf6T0CRWSfYKW1_qrH_GBVQdxY,6090
|
|
31
31
|
oep_client/usb_stream.py,sha256=VJMCxsOlQCk005FcS92pqTh33fRSFBizoL__L0VbUMA,10242
|
|
32
|
-
oep_client_python-0.0.
|
|
33
|
-
oep_client_python-0.0.
|
|
34
|
-
oep_client_python-0.0.
|
|
35
|
-
oep_client_python-0.0.
|
|
36
|
-
oep_client_python-0.0.
|
|
32
|
+
oep_client_python-0.0.8.dist-info/METADATA,sha256=TKbEmCwYIw03I3j7Rt-N1El8OQdlAvTQcLtVvb2mNMY,7368
|
|
33
|
+
oep_client_python-0.0.8.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
34
|
+
oep_client_python-0.0.8.dist-info/entry_points.txt,sha256=h6_8QX89Ww1ogALEGG5g4kspT3IOV6O51lwKqf5BWco,49
|
|
35
|
+
oep_client_python-0.0.8.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
|
|
36
|
+
oep_client_python-0.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|