oep-client-python 0.0.32__py3-none-any.whl → 0.0.33__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/__main__.py +8 -0
- oep_client/config.py +24 -0
- oep_client/endpoint.py +38 -12
- oep_client/registry.py +4 -4
- oep_client/riscv.py +16 -1
- oep_client/virtual_bench.py +5 -3
- {oep_client_python-0.0.32.dist-info → oep_client_python-0.0.33.dist-info}/METADATA +1 -1
- {oep_client_python-0.0.32.dist-info → oep_client_python-0.0.33.dist-info}/RECORD +12 -12
- {oep_client_python-0.0.32.dist-info → oep_client_python-0.0.33.dist-info}/WHEEL +0 -0
- {oep_client_python-0.0.32.dist-info → oep_client_python-0.0.33.dist-info}/entry_points.txt +0 -0
- {oep_client_python-0.0.32.dist-info → oep_client_python-0.0.33.dist-info}/licenses/LICENSE +0 -0
oep_client/__init__.py
CHANGED
oep_client/__main__.py
CHANGED
|
@@ -353,6 +353,12 @@ def _config_parser(sub) -> None:
|
|
|
353
353
|
idle.add_argument("channel", type=int)
|
|
354
354
|
idle.add_argument("mode", choices=sorted(config.IDLE))
|
|
355
355
|
idle.add_argument("--save", action="store_true")
|
|
356
|
+
rest = cs.add_parser("rvswd-rest", help="how rvswd rests a port's SWCLK: auto (the probe decides from the target_id), "
|
|
357
|
+
"or high / low fixed (the automatic choice off; debug §3.1)")
|
|
358
|
+
rest.add_argument("probe")
|
|
359
|
+
rest.add_argument("channel", type=int, help="the port's SWCLK channel")
|
|
360
|
+
rest.add_argument("mode", choices=sorted(config.REST_MODE))
|
|
361
|
+
rest.add_argument("--save", action="store_true")
|
|
356
362
|
dis = cs.add_parser("disable", help="channels the probe never drives or sets up (not on this board)")
|
|
357
363
|
dis.add_argument("probe")
|
|
358
364
|
dis.add_argument("channels", type=int, nargs="+")
|
|
@@ -435,6 +441,8 @@ def _config(args) -> int:
|
|
|
435
441
|
_change(hst, cfg, [config.Label(channel=args.channel, text=args.text)], args.save)
|
|
436
442
|
elif args.action == "idle":
|
|
437
443
|
_change(hst, cfg, [config.Idle(channel=args.channel, mode=args.mode)], args.save)
|
|
444
|
+
elif args.action == "rvswd-rest":
|
|
445
|
+
_change(hst, cfg, [config.RvswdRest(channel=args.channel, mode=args.mode)], args.save)
|
|
438
446
|
elif args.action == "disable":
|
|
439
447
|
_change(hst, cfg, [config.Disable(channel=ch) for ch in args.channels], args.save)
|
|
440
448
|
elif args.action == "remove":
|
oep_client/config.py
CHANGED
|
@@ -36,6 +36,7 @@ NAMES = tuple(_CFG.names["setting"]) # the standard i
|
|
|
36
36
|
ITEM = {k.replace("-", "_"): i + 1 for i, k in enumerate(NAMES)}
|
|
37
37
|
DESCRIBE = _CFG.tlv["describe"]
|
|
38
38
|
IDLE = {k.replace("_", "-"): v for k, v in _CFG.enum["idle_mode"].items()}
|
|
39
|
+
REST_MODE = dict(_CFG.enum["rvswd_rest_mode"]) # rvswd-rest: auto / high / low (debug §3.1)
|
|
39
40
|
STORAGE_STATE = {v: k for k, v in _CFG.enum["storage_state"].items()}
|
|
40
41
|
UNREADABLE = {v: k for k, v in _CFG.enum["storage_unreadable"].items()}
|
|
41
42
|
FORM = _CFG.enum["setting_form"]
|
|
@@ -140,6 +141,27 @@ class Passthrough:
|
|
|
140
141
|
return struct.pack("<HHIB", self.fn, self.rx, self.baud, self.format)
|
|
141
142
|
|
|
142
143
|
|
|
144
|
+
@dataclass
|
|
145
|
+
class RvswdRest:
|
|
146
|
+
"""How an rvswd attach without idle_clock rests the SWCLK on `channel` (the port's SWCLK; debug §3.1): auto - the
|
|
147
|
+
probe's choice from the target_id it reads (also with no item) - or high / low fixed, the automatic choice off for
|
|
148
|
+
that port. An attach's idle_clock TLV still decides."""
|
|
149
|
+
channel: int
|
|
150
|
+
mode: str = "auto"
|
|
151
|
+
NAME = "rvswd-rest"
|
|
152
|
+
|
|
153
|
+
def key(self) -> int:
|
|
154
|
+
return self.channel
|
|
155
|
+
|
|
156
|
+
def value(self) -> bytes:
|
|
157
|
+
return struct.pack("<H", self.key()) + self.data()
|
|
158
|
+
|
|
159
|
+
def data(self) -> bytes:
|
|
160
|
+
if self.mode not in REST_MODE:
|
|
161
|
+
raise ValueError(f"rvswd-rest mode {self.mode!r}: one of {', '.join(REST_MODE)}")
|
|
162
|
+
return bytes([REST_MODE[self.mode]])
|
|
163
|
+
|
|
164
|
+
|
|
143
165
|
@dataclass(kw_only=True)
|
|
144
166
|
class ConsolePassthrough:
|
|
145
167
|
"""Serial port `port` carries the target's debug console - read by the probe itself over `wire_fn` on (swdio, swclk)
|
|
@@ -293,6 +315,8 @@ def decode(name: str, key: int, d: bytes, setting: Setting | None = None, netifs
|
|
|
293
315
|
try:
|
|
294
316
|
if name == "label":
|
|
295
317
|
return Label(channel=key, text=d.decode("utf-8", "replace"))
|
|
318
|
+
if name == "rvswd-rest" and len(d) == 1 and d[0] in REST_MODE.values():
|
|
319
|
+
return RvswdRest(channel=key, mode={v: k for k, v in REST_MODE.items()}[d[0]])
|
|
296
320
|
if name == "idle" and len(d) == 1:
|
|
297
321
|
return Idle(channel=key, mode=_name(IDLE, d[0]))
|
|
298
322
|
if name == "disable" and not d:
|
oep_client/endpoint.py
CHANGED
|
@@ -117,7 +117,8 @@ RESET_MODE = _RV.enum["reset_mode"]
|
|
|
117
117
|
READ_FROM = reg.COMMON.enum["read_from"] # position, oldest, now, last_mark (common §1.2)
|
|
118
118
|
STEP_LEFT = _RV.tlv["step_answer"]["step_left"] # step's answer: the hart could not be halted again (§4.2)
|
|
119
119
|
ITEM = {k.replace("-", "_"): k for k in cfgmod.NAMES} # the standard items by name (probe.config §1, core §7.7)
|
|
120
|
-
CHANNEL_ITEMS = (ITEM["label"], ITEM["idle"], ITEM["disable"]) #
|
|
120
|
+
CHANNEL_ITEMS = (ITEM["label"], ITEM["idle"], ITEM["disable"], ITEM["rvswd_rest"]) # keyed by a channel (probe.config §1)
|
|
121
|
+
REST_MODE = cfgmod.REST_MODE
|
|
121
122
|
IDLE_MODE = _CFG.enum["idle_mode"]
|
|
122
123
|
CFG_DESCRIBE = cfgmod.DESCRIBE
|
|
123
124
|
SETTING_FORM = _CFG.enum["setting_form"]
|
|
@@ -137,7 +138,18 @@ I2C_FEATURES, SPI_FEATURES = _I2C.enum["features"], _SPI.enum["features"]
|
|
|
137
138
|
TARGET_ROLES = {"oep.fixture.gpio": {1}, "oep.fixture.uart": {1, 2}, _I2C.name: set(_I2C.enum["role"].values()),
|
|
138
139
|
_SPI.name: set(_SPI.enum["role"].values())} # the plan roles each fixture takes
|
|
139
140
|
UART_FORMAT_MASK = 0x1F # the defined format bits (fixture §2)
|
|
140
|
-
_T_SCAN, _T_ATTACH, _T_ATTACH_ANSWER = (
|
|
141
|
+
_T_SCAN, _T_ATTACH, _T_ATTACH_ANSWER, _T_CONNECTIONS_ANSWER = (
|
|
142
|
+
reg.WIRE_RVSWD.tlv[k] for k in ("scan", "attach", "attach_answer", "connections_answer"))
|
|
143
|
+
_IDLE_CLOCK = reg.WIRE_RVSWD.enum["idle_clock"]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def rvswd_rest(target_id: int | None) -> int:
|
|
147
|
+
"""The rest an rvswd attach without idle_clock uses (debug §3.1): low for a family in the registry's
|
|
148
|
+
idle_low_family (target_id >> target_id_family.shift), high otherwise and when no target_id was read."""
|
|
149
|
+
if target_id is None:
|
|
150
|
+
return _IDLE_CLOCK["high"]
|
|
151
|
+
family = target_id >> reg.WIRE_RVSWD.enum["target_id_family"]["shift"]
|
|
152
|
+
return _IDLE_CLOCK["low"] if family in reg.WIRE_RVSWD.enum["idle_low_family"].values() else _IDLE_CLOCK["high"]
|
|
141
153
|
_WIRE_INDEX = reg.WIRE_RVSWD.tlv["unsupported_payload"]["index"] # scan's candidate index (debug §1)
|
|
142
154
|
ATTACH_METHOD = reg.WIRE_RVSWD.enum["attach_method"]
|
|
143
155
|
GPIO_MODE_MAX = max(_GPIO.enum["mode"].values()) # 6: the modes revision 1 defines are 0-6 (fixture §1)
|
|
@@ -542,7 +554,7 @@ class Connection:
|
|
|
542
554
|
|
|
543
555
|
|
|
544
556
|
ITEM_SIZES = {ITEM["idle"]: 1, ITEM["disable"]: 0, ITEM["passthrough"]: 9, # the data of a fixed length (probe.config §1)
|
|
545
|
-
ITEM["console_passthrough"]: 13, ITEM["ipv4"]: 14}
|
|
557
|
+
ITEM["console_passthrough"]: 13, ITEM["ipv4"]: 14, ITEM["rvswd_rest"]: 1}
|
|
546
558
|
PASSTHROUGHS = (ITEM["passthrough"], ITEM["console_passthrough"])
|
|
547
559
|
|
|
548
560
|
|
|
@@ -2293,8 +2305,11 @@ class Endpoint:
|
|
|
2293
2305
|
if tg.havereset:
|
|
2294
2306
|
tg.havereset, flags = False, flags | ATTACH_FLAGS["havereset_acked"]
|
|
2295
2307
|
c = self.conns[cid]
|
|
2296
|
-
if
|
|
2297
|
-
|
|
2308
|
+
if rvswd: # the host's TLV, the setting, else from target_id (§3.1)
|
|
2309
|
+
setting = self.config.get((ITEM["rvswd_rest"], pair[1]), bytes([REST_MODE["auto"]]))[0]
|
|
2310
|
+
c.idle_clock = (idle_clock if idle_clock is not None
|
|
2311
|
+
else _IDLE_CLOCK["high"] if setting == REST_MODE["high"]
|
|
2312
|
+
else _IDLE_CLOCK["low"] if setting == REST_MODE["low"] else rvswd_rest(c.tid))
|
|
2298
2313
|
if reset is not None and tg.reset_line not in (None, channel):
|
|
2299
2314
|
if method == 1: # a line that resets nothing: halted where it ran
|
|
2300
2315
|
tg.halted, tg.dpc = True, tg.reset_vector + 0x2f8
|
|
@@ -2308,6 +2323,8 @@ class Endpoint:
|
|
|
2308
2323
|
if tg.halted and method == 1: # bit3: the probe saw hart 0 halted (§3)
|
|
2309
2324
|
flags |= ATTACH_FLAGS["halted"]
|
|
2310
2325
|
tail += m.tlv(_T_ATTACH_ANSWER["dpc"], struct.pack("<I", tg.dpc))
|
|
2326
|
+
if rvswd: # the rest in use, always (§3.1)
|
|
2327
|
+
tail += m.tlv(_T_ATTACH_ANSWER["idle_clock"], bytes([c.idle_clock]))
|
|
2311
2328
|
return self._answer(struct.pack("<IIBI", cid, tg.dmstatus(), flags, c.speed) + tail)
|
|
2312
2329
|
if op == O["detach"]:
|
|
2313
2330
|
cid = t.take("I")
|
|
@@ -2321,24 +2338,31 @@ class Endpoint:
|
|
|
2321
2338
|
first = t.take("B")
|
|
2322
2339
|
t.tail()
|
|
2323
2340
|
mine = sorted((c.order, cid) for cid, c in self.conns.items() if c.fn == fn)
|
|
2324
|
-
rows = []
|
|
2341
|
+
rows, rests = [], []
|
|
2325
2342
|
for _, cid in mine:
|
|
2326
2343
|
c = self.conns[cid]
|
|
2327
2344
|
tid = b"" if c.tid is None else struct.pack("<I", c.tid)
|
|
2328
2345
|
scheme = TARGET_ID_SCHEME["dmi_7f"] if tid else 0
|
|
2329
2346
|
rows.append(struct.pack("<IHHIBB", cid, *c.pair, c.speed, scheme, len(tid)) + tid)
|
|
2330
|
-
|
|
2347
|
+
rests.append(c.idle_clock)
|
|
2348
|
+
# rvswd: TLV idle_clock (entry_index, rest) for every entry of the page (§2.1, §3.1)
|
|
2349
|
+
return m.COMPLETED, m.SUCCESS, self._paged(rows, first, rests if rvswd else None)
|
|
2331
2350
|
return m.REJECTED, m.UNKNOWN_OPERATION, b""
|
|
2332
2351
|
|
|
2333
|
-
def _paged(self, rows: list[bytes], first: int) -> bytes:
|
|
2334
|
-
"""more(u8) count(u8) the rows from `first` that fit the frame (connections, streams: core §2.3's lists)
|
|
2352
|
+
def _paged(self, rows: list[bytes], first: int, rests: list[int] | None = None) -> bytes:
|
|
2353
|
+
"""more(u8) count(u8) the rows from `first` that fit the frame (connections, streams: core §2.3's lists);
|
|
2354
|
+
with `rests` (rvswd's connections), each row's TLV idle_clock (entry_index, rest) after them, counted in."""
|
|
2335
2355
|
budget = self.probe.max_frame - m.RESULT_HEADER - 2
|
|
2336
2356
|
out: list[bytes] = []
|
|
2337
|
-
|
|
2338
|
-
|
|
2357
|
+
tail: list[bytes] = []
|
|
2358
|
+
for i, row in enumerate(rows[first:]):
|
|
2359
|
+
extra = b"" if rests is None else m.tlv(_T_CONNECTIONS_ANSWER["idle_clock"], bytes([len(out), rests[first + i]]))
|
|
2360
|
+
if out and sum(map(len, out + tail)) + len(row) + len(extra) > budget:
|
|
2339
2361
|
break
|
|
2340
2362
|
out.append(row)
|
|
2341
|
-
|
|
2363
|
+
if extra:
|
|
2364
|
+
tail.append(extra)
|
|
2365
|
+
return bytes([int(first + len(out) < len(rows)), len(out)]) + b"".join(out) + b"".join(tail)
|
|
2342
2366
|
|
|
2343
2367
|
def _attach_methods(self, fn: int) -> set[int]:
|
|
2344
2368
|
"""method 0, and 1 when the wire declares features bit0 attach_halt (debug §3)."""
|
|
@@ -3275,6 +3299,8 @@ class Endpoint:
|
|
|
3275
3299
|
return True
|
|
3276
3300
|
if mode in (IDLE_MODE["pull_up"], IDLE_MODE["pull_down"]) and mode in self.no_pull.get(key, ()):
|
|
3277
3301
|
return True
|
|
3302
|
+
if name == ITEM["rvswd_rest"] and d[0] not in REST_MODE.values():
|
|
3303
|
+
return True # a mode the definition leaves unused (§1)
|
|
3278
3304
|
return False
|
|
3279
3305
|
|
|
3280
3306
|
def _shown(self, name: str, d: bytes) -> bytes:
|
oep_client/registry.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
from types import SimpleNamespace as _NS
|
|
5
5
|
|
|
6
|
-
REGISTRY_HASH = "
|
|
6
|
+
REGISTRY_HASH = "66b19f04290391f3"
|
|
7
7
|
SCHEMA = 1
|
|
8
8
|
PROTOCOL_REVISION = 1
|
|
9
9
|
CONFIRM_REQUEST_MAGIC = 'OEP?'
|
|
@@ -42,7 +42,7 @@ PROBE_LINK = _NS(name="oep.probe.link", revision=1, target=None, op={"source": 0
|
|
|
42
42
|
line_names={}, names={})
|
|
43
43
|
INTERFACES["oep.probe.link"] = PROBE_LINK
|
|
44
44
|
WIRE_RVSWD = _NS(name="oep.wire.rvswd", revision=1, target="RISC-V targets whose debug module is reached over the two-wire RVSWD line", op={"scan": 0x10, "attach": 0x11, "detach": 0x12, "connections": 0x13}, lock_free={0x13},
|
|
45
|
-
tlv={"describe": {"max_connections": 0x40}, "scan": {"max_speed": 0x01, "idle_clock": 0x03}, "attach": {"idle_clock": 0x03, "reset": 0x04}, "attach_answer": {"target_id": 0x01, "dpc": 0x02}, "unavailable_payload": {"index": 0x40}, "unsupported_payload": {"index": 0x40}}, event={}, enum={"scan_kind": {"riscv_dm": 0x01}, "attach_flags": {"havereset_acked": 0x01, "halted": 0x08}, "features": {"attach_halt": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "swclk": 0x02, "reset": 0x03}, "idle_clock": {"high": 0x00, "low": 0x01}}, own={},
|
|
45
|
+
tlv={"describe": {"max_connections": 0x40}, "scan": {"max_speed": 0x01, "idle_clock": 0x03}, "attach": {"idle_clock": 0x03, "reset": 0x04}, "attach_answer": {"target_id": 0x01, "dpc": 0x02, "idle_clock": 0x03}, "connections_answer": {"idle_clock": 0x02}, "unavailable_payload": {"index": 0x40}, "unsupported_payload": {"index": 0x40}}, event={}, enum={"scan_kind": {"riscv_dm": 0x01}, "attach_flags": {"havereset_acked": 0x01, "halted": 0x08}, "features": {"attach_halt": 0x01}, "attach_method": {"run": 0x00, "halt": 0x01}, "pin_role": {"swdio": 0x01, "swclk": 0x02, "reset": 0x03}, "idle_clock": {"high": 0x00, "low": 0x01}, "target_id_family": {"shift": 0x14}, "idle_low_family": {"ch32l103": 0x103}}, own={},
|
|
46
46
|
line_names={}, names={})
|
|
47
47
|
INTERFACES["oep.wire.rvswd"] = WIRE_RVSWD
|
|
48
48
|
WIRE_SWIO = _NS(name="oep.wire.swio", revision=1, target="RISC-V targets whose debug module is reached over the one-wire SWIO line", op={"scan": 0x10, "attach": 0x11, "detach": 0x12, "connections": 0x13}, lock_free={0x13},
|
|
@@ -94,6 +94,6 @@ FIXTURE_CAPTURE_GROUP = _NS(name="oep.fixture.capture-group", revision=1, target
|
|
|
94
94
|
line_names={}, names={})
|
|
95
95
|
INTERFACES["oep.fixture.capture-group"] = FIXTURE_CAPTURE_GROUP
|
|
96
96
|
PROBE_CONFIG = _NS(name="oep.probe.config", revision=1, target=None, op={"get": 0x10, "set": 0x11, "save": 0x12, "erase": 0x13, "unset": 0x14, "state": 0x15, "network": 0x16}, lock_free={0x10, 0x15, 0x16},
|
|
97
|
-
tlv={"describe": {"storage": 0x40, "setting": 0x41, "netif": 0x42}}, event={}, enum={"idle_mode": {"hi_z": 0x00, "pull_up": 0x01, "pull_down": 0x02, "output_low": 0x03, "output_high": 0x04}, "ipv4_mode": {"dhcp": 0x00, "static": 0x01}, "network_state": {"off": 0x00, "connecting": 0x01, "up": 0x02, "waiting": 0x03}, "network_reason": {"none": 0x00, "not_found": 0x01, "auth": 0x02, "no_address": 0x03, "other": 0x04}, "setting_form": {"named": 0x00, "bytes": 0x01, "text": 0x02, "u32": 0x03, "ipv4": 0x04, "bool": 0x05}, "setting_flag": {"secret": 0x01, "restart": 0x02}, "storage_state": {"none": 0x00, "applied": 0x01, "unreadable": 0x02, "partial": 0x03}, "storage_unreadable": {"none": 0x00, "form": 0x01, "item": 0x02, "capacity": 0x03}}, own={},
|
|
98
|
-
line_names={'nrst': 'the target reset line (Host only)', 'power_hi': 'target power on when high (Host only)', 'power_lo': 'target power on when low (Host only)'}, names={'setting': {'label': 'key channel; text 1-32 bytes', 'idle': 'key channel; mode(u8)', 'disable': 'key channel; no data', 'passthrough': 'key port; fn(u16) rx(u16) baud(u32) format(u8)', 'console-passthrough': 'key port; wire_fn(u16) swdio(u16) swclk(u16) max_speed(u32) console_fn(u16) mechanism(u8)', 'wifi': 'key entry; ssid_len(u8) ssid pass_len(u8) passphrase; passphrase write-only', 'ipv4': 'key netif; mode(u8) address(4) prefix(u8) gateway(4) dns(4)'}, 'netif': {'wifi': 'Wi-Fi station', 'ethernet': 'wired Ethernet'}})
|
|
97
|
+
tlv={"describe": {"storage": 0x40, "setting": 0x41, "netif": 0x42}}, event={}, enum={"idle_mode": {"hi_z": 0x00, "pull_up": 0x01, "pull_down": 0x02, "output_low": 0x03, "output_high": 0x04}, "rvswd_rest_mode": {"auto": 0x00, "high": 0x01, "low": 0x02}, "ipv4_mode": {"dhcp": 0x00, "static": 0x01}, "network_state": {"off": 0x00, "connecting": 0x01, "up": 0x02, "waiting": 0x03}, "network_reason": {"none": 0x00, "not_found": 0x01, "auth": 0x02, "no_address": 0x03, "other": 0x04}, "setting_form": {"named": 0x00, "bytes": 0x01, "text": 0x02, "u32": 0x03, "ipv4": 0x04, "bool": 0x05}, "setting_flag": {"secret": 0x01, "restart": 0x02}, "storage_state": {"none": 0x00, "applied": 0x01, "unreadable": 0x02, "partial": 0x03}, "storage_unreadable": {"none": 0x00, "form": 0x01, "item": 0x02, "capacity": 0x03}}, own={},
|
|
98
|
+
line_names={'swdio': 'the debug data line (2 wires: rvswd, swd) (Host only)', 'swclk': 'the debug clock line (2 wires: rvswd, swd) (Host only)', 'swio': 'the one debug wire (swio) (Host only)', 'rx': 'the fixture UART receive, wired to the target TX (Host only)', 'tx': 'the fixture UART transmit, wired to the target RX (Host only)', 'nrst': 'the target reset line (Host only)', 'power_hi': 'target power on when high (Host only)', 'power_lo': 'target power on when low (Host only)'}, names={'setting': {'label': 'key channel; text 1-32 bytes', 'idle': 'key channel; mode(u8)', 'disable': 'key channel; no data', 'passthrough': 'key port; fn(u16) rx(u16) baud(u32) format(u8)', 'console-passthrough': 'key port; wire_fn(u16) swdio(u16) swclk(u16) max_speed(u32) console_fn(u16) mechanism(u8)', 'wifi': 'key entry; ssid_len(u8) ssid pass_len(u8) passphrase; passphrase write-only', 'ipv4': 'key netif; mode(u8) address(4) prefix(u8) gateway(4) dns(4)', 'rvswd-rest': "key channel (the port's SWCLK); mode(u8): rvswd_rest_mode"}, 'netif': {'wifi': 'Wi-Fi station', 'ethernet': 'wired Ethernet'}})
|
|
99
99
|
INTERFACES["oep.probe.config"] = PROBE_CONFIG
|
oep_client/riscv.py
CHANGED
|
@@ -197,6 +197,10 @@ class WireBase(Interface):
|
|
|
197
197
|
ONE_WIRE = False # swio: swclk is 0xFFFF (§3)
|
|
198
198
|
DEFAULT_MAX_SPEED = 1_000_000 # when the wire declares no max_clock_hz either
|
|
199
199
|
|
|
200
|
+
def _is_rvswd(self) -> bool:
|
|
201
|
+
"""The rest TLVs are rvswd's (debug §3.1); the name as opened, else the class's."""
|
|
202
|
+
return getattr(self, "name", self.NAME) == "oep.wire.rvswd"
|
|
203
|
+
|
|
200
204
|
def _description(self) -> catalog.Description:
|
|
201
205
|
return catalog.decode_description(b"".join(catalog.tlv(t, v) for t, v in describe(self.host, self.fn)))
|
|
202
206
|
|
|
@@ -307,17 +311,22 @@ class WireBase(Interface):
|
|
|
307
311
|
for _ in range(count):
|
|
308
312
|
conn, swdio, swclk, speed, scheme, n = rd.take("IHHIBB")
|
|
309
313
|
tid = rd.bytes(n)
|
|
310
|
-
page.append([conn, (swdio, swclk), speed, (scheme, tid) if scheme else None, None])
|
|
314
|
+
page.append([conn, (swdio, swclk), speed, (scheme, tid) if scheme else None, None, None])
|
|
311
315
|
for tag, value in m.split_tlvs(rd.rest()):
|
|
312
316
|
# entry_index(u8) targetsel(u32), repeatable; bit 7 in an answer: an unknown tag (core §2.2, §2.3)
|
|
313
317
|
if tag == _SELECTED_TARGET and len(value) == 5 and value[0] < len(page):
|
|
314
318
|
page[value[0]][4] = struct.unpack_from("<I", value, 1)[0]
|
|
319
|
+
# rvswd: entry_index(u8) idle_clock(u8) for every entry (debug §2.1, §3.1)
|
|
320
|
+
if self._is_rvswd() and tag == _REST and len(value) == 2 and value[0] < len(page):
|
|
321
|
+
page[value[0]][5] = _REST_NAMES.get(value[1])
|
|
315
322
|
out += [ConnectionInfo(*row) for row in page]
|
|
316
323
|
if not more or not count or len(out) > 0xFF:
|
|
317
324
|
return out
|
|
318
325
|
|
|
319
326
|
|
|
320
327
|
_SELECTED_TARGET = reg.WIRE_SWD.tlv["connections_answer"]["selected_target"]
|
|
328
|
+
_REST = reg.WIRE_RVSWD.tlv["connections_answer"]["idle_clock"]
|
|
329
|
+
_REST_NAMES = {v: k for k, v in reg.WIRE_RVSWD.enum["idle_clock"].items()}
|
|
321
330
|
|
|
322
331
|
|
|
323
332
|
@dataclass(frozen=True)
|
|
@@ -329,6 +338,7 @@ class ConnectionInfo:
|
|
|
329
338
|
speed_hz: int
|
|
330
339
|
target_id: tuple[int, bytes] | None
|
|
331
340
|
targetsel: int | None = None
|
|
341
|
+
idle_clock: str | None = None # rvswd: "high" / "low", the rest the connection uses (debug §3.1)
|
|
332
342
|
|
|
333
343
|
|
|
334
344
|
class Wire(WireBase):
|
|
@@ -342,6 +352,7 @@ class Wire(WireBase):
|
|
|
342
352
|
SCHEME_DMI_7F = reg.COMMON.enum["target_id_scheme"]["dmi_7f"] # the u32 at DMI 0x7F (oep-if-debug §3)
|
|
343
353
|
|
|
344
354
|
TAG_DPC = reg.WIRE_RVSWD.tlv["attach_answer"]["dpc"]
|
|
355
|
+
TAG_REST = reg.WIRE_RVSWD.tlv["attach_answer"]["idle_clock"]
|
|
345
356
|
|
|
346
357
|
def __init__(self, hst: h.Host, name: str = "oep.wire.rvswd"):
|
|
347
358
|
super().__init__(hst, name)
|
|
@@ -397,6 +408,10 @@ class Wire(WireBase):
|
|
|
397
408
|
dpc = tail.get(self.TAG_DPC)
|
|
398
409
|
# dpc is a u32: a value of another length is broken, not used (core §2.3)
|
|
399
410
|
self.dpc = struct.unpack("<I", dpc)[0] if self.halted and dpc is not None and len(dpc) == 4 else None
|
|
411
|
+
# rvswd: the rest the connection uses, the host's or the probe's choice from target_id (debug §3.1)
|
|
412
|
+
rest = tail.get(self.TAG_REST) if self._is_rvswd() else None
|
|
413
|
+
names = {v: k for k, v in self.IDLE_CLOCK.items()}
|
|
414
|
+
self.idle_clock = names.get(rest[0]) if rest is not None and len(rest) == 1 else None
|
|
400
415
|
return conn, status
|
|
401
416
|
|
|
402
417
|
def attach_under_reset(self, channel: int, hold_ms: int = 20, max_speed: int | None = None,
|
oep_client/virtual_bench.py
CHANGED
|
@@ -262,7 +262,7 @@ def _setting(name: str, keys: int, form: int = 0, max_len: int = 0, flags: int =
|
|
|
262
262
|
|
|
263
263
|
|
|
264
264
|
def _config(fn: int, instance: int, storage: int = 4096, *, channels: int = 64, ports: int = 4, netifs=(), wifi_entries: int = 4,
|
|
265
|
-
own=()) -> Offered:
|
|
265
|
+
own=(), rvswd: bool = False) -> Offered:
|
|
266
266
|
"""oep.probe.config's declarations (probe.config §4): the standard items label / idle / disable (keys: the
|
|
267
267
|
channels), passthrough / console-passthrough (keys: the transports), with `netifs` (names) wifi / ipv4 and the
|
|
268
268
|
network op; `own`: the probe's own items as (name, form, keys, max_len, flags) (§1.6). storage 0 = none - no storage
|
|
@@ -274,6 +274,8 @@ def _config(fn: int, instance: int, storage: int = 4096, *, channels: int = 64,
|
|
|
274
274
|
if "wifi" in netifs:
|
|
275
275
|
settings.append(_setting("wifi", wifi_entries))
|
|
276
276
|
settings.append(_setting("ipv4", len(netifs) + 1))
|
|
277
|
+
if rvswd: # its automatic rest can be turned off per port (debug §3.1)
|
|
278
|
+
settings.append(_setting("rvswd-rest", channels))
|
|
277
279
|
settings += [_setting(name, keys, form, max_len, flags) for name, form, keys, max_len, flags in own]
|
|
278
280
|
return Offered(fn, instance, "oep.probe.config", ops_of("oep.probe.config", *drop)
|
|
279
281
|
+ ((catalog.u32(_CFG["storage"], storage),) if storage else ()) + tuple(settings)
|
|
@@ -388,7 +390,7 @@ def p4_x035() -> VirtualProbe:
|
|
|
388
390
|
max_stretch_us=100_000), # stretch
|
|
389
391
|
Offered(9, 0, "oep.fixture.spi-target", _roles({1: pins, 2: pins, 3: pins, 4: pins})
|
|
390
392
|
+ _spi_decl(max_length=64, max_hz=3_000_000, features=0b1, queue_depth=8)), # LSB first
|
|
391
|
-
_config(10, 0, channels=55, ports=4, netifs=("ethernet",)),
|
|
393
|
+
_config(10, 0, channels=55, ports=4, netifs=("ethernet",), rvswd=True),
|
|
392
394
|
# the P4's ADC1 (GPIO16-23): one ADC for all its channels, 611 Hz - 83.3 kHz in all; ESP32-style attenuations
|
|
393
395
|
Offered(11, 0, "oep.fixture.analog", _roles({k: list(range(16, 24)) for k in range(4)})
|
|
394
396
|
+ _analog_decl([(0, 0, 950), (1, 0, 1250), (2, 0, 1750), (3, 0, 3100)], 65536, 611, 83_333),
|
|
@@ -465,7 +467,7 @@ def p4_bench() -> VirtualProbe:
|
|
|
465
467
|
_console(3),
|
|
466
468
|
_gpio(4, pins),
|
|
467
469
|
_uart(5, 0, pins, 3_000_000),
|
|
468
|
-
_config(6, 0, channels=55, ports=4),
|
|
470
|
+
_config(6, 0, channels=55, ports=4, rvswd=True),
|
|
469
471
|
_link(7),
|
|
470
472
|
_plan(8),
|
|
471
473
|
_restart(9),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: oep-client-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.33
|
|
4
4
|
Summary: Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a virtual bench
|
|
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,11 +1,11 @@
|
|
|
1
|
-
oep_client/__init__.py,sha256=
|
|
2
|
-
oep_client/__main__.py,sha256=
|
|
1
|
+
oep_client/__init__.py,sha256=i55a89BxR1hu3ff6BPlfP_aEJn4skTGl0cJphRFGQdo,164
|
|
2
|
+
oep_client/__main__.py,sha256=l7KIG3-55GovEmb9dboeA-gInoNBwCXziCERHbBQCyY,32873
|
|
3
3
|
oep_client/arm.py,sha256=SszSLae8zErD4T-a1uQ6s6o3Lz7pe2SR8d3Qy-wi5rY,15633
|
|
4
4
|
oep_client/capture.py,sha256=AFyJ-_DRb3ztYlvmFCDh9siNaKrwChOx8xvoNH6CKsI,48884
|
|
5
5
|
oep_client/catalog.py,sha256=WkaksNn9cFvkTRnvtX4I9g1AvkFoldEiNQaKiyPQ7_E,10772
|
|
6
6
|
oep_client/ch32_flash.py,sha256=lY_HKxf2foSfhNda91lcWefgRnY9ebTljsg4zJEj-Ks,12885
|
|
7
7
|
oep_client/cobs.py,sha256=RbdPrqgzD3SukxOIXX9m2dZpVTud8xAYYEhm3rcW2nA,2513
|
|
8
|
-
oep_client/config.py,sha256=
|
|
8
|
+
oep_client/config.py,sha256=OTePLd-X1QC7xOk36BmhqfF8M7WwBXaDvuz_jiBmrIM,29575
|
|
9
9
|
oep_client/conformance.py,sha256=phKkP_vT_8b9MyQiJU0p7JoCnkrPbPdkolcEqaD61TI,62859
|
|
10
10
|
oep_client/conformance_allocator.py,sha256=83xXiJ7c-6-M86615Kvq6yDD0sf0Z6lIOKDtbYcKeyM,6274
|
|
11
11
|
oep_client/conformance_allocator_sample.py,sha256=GGv43xbDNSPjQ8_flNXe-QbkLOr-NCbPpWPOfbD_wH8,879
|
|
@@ -178,7 +178,7 @@ oep_client/core.py,sha256=VPtgaVe2K5-HJMi72DDbIpIirATAXjcJSKautKUFgOM,22677
|
|
|
178
178
|
oep_client/decode.py,sha256=6pTFVBT0MLAKedZLVKyd5yT8hjrRw4fdDjnoDiE9XRs,2380
|
|
179
179
|
oep_client/discovery.py,sha256=OS6c4Qa8N32zbOHmw75e1y6ff3SQrL0uLtyPi7BWKUA,20187
|
|
180
180
|
oep_client/dump.py,sha256=31v4Hg27Het3cu3joCm6ttTWxQHSvvNryyGo8pwHXO4,12788
|
|
181
|
-
oep_client/endpoint.py,sha256=
|
|
181
|
+
oep_client/endpoint.py,sha256=DmKqB_uLHQnvUBuv5q_jcofD_9spbWjCJ1_1tieFJMo,226457
|
|
182
182
|
oep_client/fixture.py,sha256=GbAPXAk9GQ0qG6STL-rY4-EqXftmKfNKVI2xZZUiFzA,18108
|
|
183
183
|
oep_client/frames.py,sha256=OrvoNugGB4ewfmILhwBiJfI9sQ09i-RzO47LESVbWXw,4800
|
|
184
184
|
oep_client/hardware.py,sha256=RboxkRxkQJ3DbNJEXyyiOFYlLFKGxrlcSwHho8zFC1U,30256
|
|
@@ -192,8 +192,8 @@ oep_client/message.py,sha256=-WgnHcmnhJ6pozYvZP_FS8dr0ZMg2Wp9rTdRReGvogU,13116
|
|
|
192
192
|
oep_client/names.py,sha256=ohrRvQNURraYyJ-BtjHRwxGt_GLq-t8IO0aOji9Dhe0,3531
|
|
193
193
|
oep_client/pins.py,sha256=YVM0JXjCKcMMMWChtWsQoSKU4-OTOnDbZjo_mo_5hD0,32574
|
|
194
194
|
oep_client/pytest_conformance.py,sha256=-bcJU2E1UE4xjQ7HZjaIgtp0l65cIibBTNFnaW2tews,2929
|
|
195
|
-
oep_client/registry.py,sha256=
|
|
196
|
-
oep_client/riscv.py,sha256=
|
|
195
|
+
oep_client/registry.py,sha256=eeUL7cquyunsaSQYofRNXH0y8sAFkX8sRtmwc7-GZjA,16688
|
|
196
|
+
oep_client/riscv.py,sha256=J0HHHrI-xrIt46zob3RpmOqy9XV12-futGeU1SC-xjY,59201
|
|
197
197
|
oep_client/rp2350.py,sha256=7OMyj270k3AY1e3-ljicPwOjf9jOlokbT6QNkA0b0yY,4227
|
|
198
198
|
oep_client/speed_record.py,sha256=6THUKbN7gQKpfIdUO2551P8mXiAFqbFDky72Xbki7L0,7229
|
|
199
199
|
oep_client/targets.py,sha256=zFekSr76NVO7tzdgyQsLDHLWRvkgylfwvGNTz_hQGf8,5041
|
|
@@ -203,7 +203,7 @@ oep_client/virtual_allocator_model.py,sha256=XBrbjG2Zupf0P28gjUhQVDw6UzO2jQXsYZ1
|
|
|
203
203
|
oep_client/virtual_analog_model.py,sha256=iV5pyJ1sy37D6VMy4qVmgzsmq4gLwEPMcdOGXPIin1Q,13872
|
|
204
204
|
oep_client/virtual_arm_adi_model.py,sha256=xlqhjr_QCF6MNVOnVelTanlNWpmaCJ5uWXf6V9WkqUM,8121
|
|
205
205
|
oep_client/virtual_attach_model.py,sha256=11UfEicbmTKcjps8JPzw99J59Dl_QGVbyyuFb0ixzso,10288
|
|
206
|
-
oep_client/virtual_bench.py,sha256=
|
|
206
|
+
oep_client/virtual_bench.py,sha256=WXLJICEhaTo5kapOujCcH-CEfIgtudlzanrUv_tVIss,35944
|
|
207
207
|
oep_client/virtual_bench_capture.py,sha256=hIIOUOqKcSxBnsCb9rcyzYFqSsBmuic7sAkF7zsBAIs,52208
|
|
208
208
|
oep_client/virtual_bench_mdns.py,sha256=cnJNBKg5zTduXUcH-wqN_ZBDGl7DyL-tL3CBn2jro0E,13305
|
|
209
209
|
oep_client/virtual_bench_serial.py,sha256=EvbdOYeGrM6CRti2b90I0PzpmmherfoJRaAg4v7Iq9Y,13205
|
|
@@ -261,8 +261,8 @@ oep_client/virtual_tlv_request_model.py,sha256=gp-eiN784NnloQBANG_4TnM6oUCmrj046
|
|
|
261
261
|
oep_client/virtual_uart_model.py,sha256=Sd_MWLjl1-6_bemsCuI2at9zpVJRBehFQgZ6By97PdQ,9386
|
|
262
262
|
oep_client/virtual_wire_options_model.py,sha256=1QNF16hRWmdFt0J7Zd1WKZdEc07vns6osMQLetMBlXw,9206
|
|
263
263
|
oep_client/virtual_writer_lease_model.py,sha256=E1MAQsGuShqONVdIeLubun7Cop0URNUSk8wicPicbt4,1728
|
|
264
|
-
oep_client_python-0.0.
|
|
265
|
-
oep_client_python-0.0.
|
|
266
|
-
oep_client_python-0.0.
|
|
267
|
-
oep_client_python-0.0.
|
|
268
|
-
oep_client_python-0.0.
|
|
264
|
+
oep_client_python-0.0.33.dist-info/METADATA,sha256=ruHISiMjzQOjtZv3t2Bcyo3LxM8292-_CCUMc0NUXLk,52711
|
|
265
|
+
oep_client_python-0.0.33.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
266
|
+
oep_client_python-0.0.33.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
|
|
267
|
+
oep_client_python-0.0.33.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
|
|
268
|
+
oep_client_python-0.0.33.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|