Skip to content

Commit e3799ca

Browse files
authored
feat(hardware): add write-eeprom script (#21438)
# Overview Add a script that's able to take the results of a dump_eeprom.py run and re-write it to an eeprom Very helpful in debugging eeprom migration because we can re-write the old data for testing.
1 parent 467f267 commit e3799ca

1 file changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/usr/bin/env python3
2+
"""blow away and reset EEPROM file systems."""
3+
4+
import argparse
5+
import asyncio
6+
import logging
7+
from logging.config import dictConfig
8+
from typing import Any, Dict, List
9+
10+
from typing_extensions import Final
11+
12+
from opentrons_hardware.drivers.can_bus import CanMessenger, build
13+
from opentrons_hardware.firmware_bindings import utils
14+
from opentrons_hardware.firmware_bindings.constants import NodeId
15+
from opentrons_hardware.firmware_bindings.messages import (
16+
fields,
17+
message_definitions,
18+
payloads,
19+
)
20+
from opentrons_hardware.scripts.can_args import add_can_args, build_settings
21+
22+
logger = logging.getLogger(__name__)
23+
24+
LOG_CONFIG = {
25+
"version": 1,
26+
"disable_existing_loggers": False,
27+
"formatters": {
28+
"basic": {"format": "%(asctime)s %(name)s %(levelname)s %(message)s"}
29+
},
30+
"handlers": {
31+
"stream_handler": {
32+
"class": "logging.StreamHandler",
33+
"formatter": "basic",
34+
"level": logging.DEBUG,
35+
},
36+
},
37+
"loggers": {
38+
"": {
39+
"handlers": ["stream_handler"],
40+
"level": logging.DEBUG,
41+
},
42+
},
43+
}
44+
45+
TARGETS: Final[Dict[str, NodeId]] = {
46+
"head": NodeId.head,
47+
"gantry-x": NodeId.gantry_x,
48+
"gantry-y": NodeId.gantry_y,
49+
"pipette-left": NodeId.pipette_left,
50+
"pipette-right": NodeId.pipette_right,
51+
"gripper": NodeId.gripper,
52+
}
53+
54+
55+
async def run(args: argparse.Namespace) -> None:
56+
"""Script entrypoint."""
57+
eeprom_data = []
58+
with open(args.file, "r") as f:
59+
eeprom_data = ["".join(line.split()) for line in f]
60+
61+
async with (
62+
build.driver(build_settings(args)) as driver,
63+
CanMessenger(driver) as messenger,
64+
):
65+
await rewrite_eeprom(
66+
messenger,
67+
TARGETS[args.target],
68+
256 if args.old_version else 16384,
69+
eeprom_data,
70+
)
71+
await asyncio.sleep(3)
72+
73+
74+
async def rewrite_eeprom(
75+
messenger: CanMessenger, node: NodeId, limit: int, eeprom_data: List[str]
76+
) -> None:
77+
"""Wipe out all of the data used for the general purpose file system."""
78+
start = 0
79+
max_write = 8
80+
for line in eeprom_data:
81+
write_len = min(max_write, limit - start)
82+
write_msg = message_definitions.WriteToEEPromRequest(
83+
payload=payloads.EEPromDataPayload(
84+
address=utils.UInt16Field(start),
85+
data_length=utils.UInt16Field(write_len),
86+
data=fields.EepromDataField.from_string(line),
87+
)
88+
)
89+
start += write_len
90+
await messenger.send(node, write_msg)
91+
92+
93+
def main() -> None:
94+
"""Entry point."""
95+
parser = argparse.ArgumentParser(description=__doc__)
96+
97+
add_can_args(parser)
98+
parser.add_argument(
99+
"--target",
100+
help="The FW subsystem to be cleared.",
101+
type=str,
102+
required=True,
103+
choices=TARGETS.keys(),
104+
)
105+
parser.add_argument(
106+
"--file",
107+
help="dump file to write.",
108+
type=str,
109+
default="/var/log/eeprom_dump.hex",
110+
required=False,
111+
)
112+
parser.add_argument(
113+
"--less-logs",
114+
help="Set log level to INFO, so we see less logs.",
115+
action="store_true",
116+
default=False,
117+
)
118+
parser.add_argument(
119+
"--old-version",
120+
help="Enable this flag to clear eeprom on the older 256 Byte eeproms.",
121+
action="store_true",
122+
default=False,
123+
)
124+
125+
args = parser.parse_args()
126+
127+
def _set_log_lvl_warn(d: Dict[str, Any]) -> None:
128+
for k in d.keys():
129+
if isinstance(d[k], dict):
130+
_set_log_lvl_warn(d[k])
131+
elif k == "level":
132+
d[k] = logging.WARNING
133+
134+
if args.less_logs:
135+
_set_log_lvl_warn(LOG_CONFIG)
136+
dictConfig(LOG_CONFIG)
137+
asyncio.run(run(args))
138+
139+
140+
if __name__ == "__main__":
141+
main()

0 commit comments

Comments
 (0)