Skip to content

Commit efb3ccf

Browse files
dcpleungnashif
authored andcommitted
boards: mec172xevb_assy6906: support remote flashing
This allows mec172xevb_assy6906 to support misc-flasher to run arbitrary script to flash the SPI chip. A script is also provided as an example. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
1 parent cf9c344 commit efb3ccf

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

boards/arm/mec172xevb_assy6906/board.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ board_finalize_runner_args(dediprog
99
"--spi-image=${PROJECT_BINARY_DIR}/${SPI_IMAGE_NAME}"
1010
"--vcc=0"
1111
)
12+
13+
# This allows a custom script to be used for flashing the SPI chip.
14+
include(${ZEPHYR_BASE}/boards/common/misc.board.cmake)
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2023 Intel Corporation
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
'''
8+
This script allows flashing a mec172xevb_assy6906 board
9+
attached to a remote system.
10+
11+
Usage:
12+
west flash -r misc-flasher -- mec172x_remote_flasher.py <remote host>
13+
14+
Note:
15+
1. SSH access to remote host with write access to remote /tmp.
16+
Since the script does multiple SSH connections, it is a good idea
17+
to setup public key authentication and ssh-agent.
18+
2. Dediprog "dpcmd" available in path on remote host.
19+
(Can be compiled from https://github.com/DediProgSW/SF100Linux)
20+
3. SSH user must have permission to access USB devices,
21+
since dpcmd needs USB access to communicate with
22+
the Dediprog programmer attached to remote host.
23+
24+
To use with twister, a hardware map file is needed.
25+
Here is a sample map file:
26+
27+
- connected: true
28+
available: true
29+
id: mec172xevb_assy6906
30+
platform: mec172xevb_assy6906
31+
product: mec172xevb_assy6906
32+
runner: misc-flasher
33+
runner_params:
34+
- <ZEPHYR_BASE>/boards/arm/mec172xevb_assy6906/support/mec172x_remote_flasher.py
35+
- <remote host>
36+
serial_pty: "nc,<remote host>,<ser2net port>"
37+
38+
The sample map file assumes the serial console is exposed via ser2net,
39+
and that it can be accessed using nc (netcat).
40+
41+
To use twister:
42+
./scripts/twister --hardware-map <hw map file> --device-testing
43+
44+
Required:
45+
* Fabric (https://www.fabfile.org/)
46+
'''
47+
48+
import argparse
49+
import hashlib
50+
import pathlib
51+
import sys
52+
53+
from datetime import datetime
54+
55+
import fabric
56+
from invoke.exceptions import UnexpectedExit
57+
58+
def calc_sha256(spi_file):
59+
'''
60+
Calculate a SHA256 of the SPI binary content plus current
61+
date string.
62+
63+
This is used for remote file name to avoid file name
64+
collision.
65+
'''
66+
sha256 = hashlib.sha256()
67+
68+
# Use SPI file content to calculate SHA.
69+
with open(spi_file, "rb") as fbin:
70+
spi_data = fbin.read()
71+
sha256.update(spi_data)
72+
73+
# Add a date/time to SHA to hopefully
74+
# further avoid file name collision.
75+
now = datetime.now().isoformat()
76+
sha256.update(now.encode("utf-8"))
77+
78+
return sha256.hexdigest()
79+
80+
def parse_args():
81+
'''
82+
Parse command line arguments.
83+
'''
84+
parser = argparse.ArgumentParser(allow_abbrev=False)
85+
86+
# Fixed arguments
87+
parser.add_argument("build_dir",
88+
help="Build directory")
89+
parser.add_argument("remote_host",
90+
help="Remote host name or IP address")
91+
92+
# Arguments about remote machine
93+
remote = parser.add_argument_group("Remote Machine")
94+
remote.add_argument("--remote-tmp", required=False,
95+
help="Remote temporary directory to store SPI binary "
96+
"[default=/tmp for Linux remote]")
97+
remote.add_argument("--dpcmd", required=False, default="dpcmd",
98+
help="Full path to dpcmd on remote machine")
99+
100+
# Remote machine type.
101+
# This affects how remote path is constructed.
102+
remote_type = remote.add_mutually_exclusive_group()
103+
remote_type.add_argument("--remote-is-linux", required=False,
104+
default=True, action="store_true",
105+
help="Set if remote machine is a Linux-like machine [default]")
106+
remote_type.add_argument("--remote-is-win", required=False,
107+
action="store_true",
108+
help="Set if remote machine is a Windows machine")
109+
110+
return parser.parse_args()
111+
112+
def main():
113+
'''
114+
Main
115+
'''
116+
args = parse_args()
117+
118+
# Check for valid arguments and setup variables.
119+
if not args.remote_tmp:
120+
if args.remote_is_win:
121+
# Do not assume a default temporary on Windows,
122+
# as it is usually under user's directory and
123+
# we do not know enough to construct a valid path
124+
# at this time.
125+
print("[ERROR] --remote-tmp is required for --remote-is-win")
126+
sys.exit(1)
127+
128+
if args.remote_is_linux:
129+
remote_tmp = pathlib.PurePosixPath("/tmp")
130+
else:
131+
if args.remote_is_win:
132+
remote_tmp = pathlib.PureWindowsPath(args.remote_tmp)
133+
elif args.remote_is_linux:
134+
remote_tmp = pathlib.PurePosixPath(args.remote_tmp)
135+
136+
# Construct full path to SPI binary.
137+
spi_file_path = pathlib.Path(args.build_dir)
138+
spi_file_path = spi_file_path.joinpath("zephyr", "spi_image.bin")
139+
140+
# Calculate a sha256 digest for SPI file.
141+
# This is used for remote file to avoid file name collision
142+
# if there are multiple MEC17x attached to remote machine
143+
# and all are trying to flash at same time.
144+
sha256 = calc_sha256(spi_file_path)
145+
146+
# Construct full path on remote to store
147+
# the transferred SPI binary.
148+
remote_file_name = remote_tmp.joinpath(f"mec172x_{sha256}.bin")
149+
150+
print(f"[INFO] Build directory: {args.build_dir}")
151+
print(f"[INFO] Remote host: {args.remote_host}")
152+
153+
# Connect to remote host via SSH.
154+
ssh = fabric.Connection(args.remote_host, forward_agent=True)
155+
156+
print("[INFO] Sending file...")
157+
print(f"[INFO] Local SPI file: {spi_file_path}")
158+
print(f"[INFO] Remote SPI file: {remote_file_name}")
159+
160+
# Open SFTP channel, and send the SPI binary over.
161+
sftp = ssh.sftp()
162+
sftp.put(str(spi_file_path), str(remote_file_name))
163+
164+
# Run dpcmd to flash the device.
165+
try:
166+
dpcmd_cmd = f"{args.dpcmd} --auto {str(remote_file_name)} --verify"
167+
print(f"[INFO] Invoking: {dpcmd_cmd}...")
168+
ssh.run(dpcmd_cmd)
169+
except UnexpectedExit:
170+
print("[ERR ] Cannot flashing SPI binary!")
171+
172+
# Remove temporary file.
173+
print(f"[INFO] Removing remote file {remote_file_name}")
174+
sftp.remove(str(remote_file_name))
175+
176+
sftp.close()
177+
ssh.close()
178+
179+
if __name__ == "__main__":
180+
main()

0 commit comments

Comments
 (0)