summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Rodriguez Buchillon <coconutruben@chromium.org>2020-12-08 13:27:46 -0800
committerCommit Bot <commit-bot@chromium.org>2020-12-11 02:57:42 +0000
commite96554d35c8f0e24a02767c1d9b2860c28e6974a (patch)
tree5d146f13a1b42f1de7a917c4f98b2cd97e162e02
parent590ac3bc3f34bb0c9d92f35c853adb5bca252892 (diff)
downloadchrome-ec-e96554d35c8f0e24a02767c1d9b2860c28e6974a.tar.gz
servo_updater: make more robust on resets
long-term, we need to pull this into hdctools, rather than reimplement everything twice. Short term, this is a fine solution. It essentially makes sure that 1. we only keep one pty/stm32uart/stm32usb object around for communication 2. we always reset it properly when it could need a reset e.g. when the stm32 is rebooting, or a new firmware was flashed 3. it expands the timeout for the chip to come back to 2s the tiny_servod will eventually also land in hdctools, though for now it just ensures that we can reset the pyusb communication without larger issues and a larger refactor. BUG=chromium:1152838 BRANCH=None // Timeout before change, runs after change TEST=sudo servo_updater --board servo_micro // Timeout before change, runs after change TEST=sudo servo_updater --board sweetberry // Timeout before change, runs after change TEST=sudo servo_updater --board servo_micro --force // to show the serialname support. This is a fake serial, and it gets stuck waiting TEST=sudo servo_updater -s MICRO-S-2009020022 --board servo_micro // to show the serialname support. This is a real serial and it proceeds TEST=sudo servo_updater -s MICRO-S-2009020022 --board servo_micro Change-Id: I747ca69881c13c1aadd8e90a35badecbf4e6a09e Signed-off-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2580854 Reviewed-by: Otabek Kasimov <otabek@google.com> Reviewed-by: Garry Wang <xianuowang@chromium.org> (cherry picked from commit c1ff0aed409b5ddf03538448e2e4c773b97986f4) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2585855
-rw-r--r--extra/tigertool/ecusb/tiny_servod.py50
-rwxr-xr-xextra/usb_updater/servo_updater.py86
2 files changed, 88 insertions, 48 deletions
diff --git a/extra/tigertool/ecusb/tiny_servod.py b/extra/tigertool/ecusb/tiny_servod.py
new file mode 100644
index 0000000000..aec87995a4
--- /dev/null
+++ b/extra/tigertool/ecusb/tiny_servod.py
@@ -0,0 +1,50 @@
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Helper class to facilitate communication to servo ec console."""
+
+from ecusb import pty_driver
+from ecusb import stm32uart
+
+
+class TinyServod(object):
+ """Helper class to wrap a pty_driver with interface."""
+
+ def __init__(self, vid, pid, interface, serialname=None, debug=False):
+ """Build the driver and interface.
+
+ Args:
+ vid: servo device vid
+ pid: servo device pid
+ interface: which usb interface the servo console is on
+ serialname: the servo device serial (if available)
+ """
+ self._vid = vid
+ self._pid = pid
+ self._interface = interface
+ self._serial = serialname
+ self._debug = debug
+ self._init()
+
+ def _init(self):
+ self.suart = stm32uart.Suart(vendor=self._vid,
+ product=self._pid,
+ interface=self._interface,
+ serialname=self._serial,
+ debuglog=self._debug)
+ self.suart.run()
+ self.pty = pty_driver.ptyDriver(self.suart, [])
+
+ def reinitialize(self):
+ """Reinitialize the connect after a reset/disconnect/etc."""
+ self.close()
+ self._init()
+
+ def close(self):
+ """Close out the connection and release resources.
+
+ Note: if another TinyServod process or servod itself needs the same device
+ it's necessary to call this to ensure the usb device is available.
+ """
+ self.suart.close()
diff --git a/extra/usb_updater/servo_updater.py b/extra/usb_updater/servo_updater.py
index 80a63636d8..e093f55422 100755
--- a/extra/usb_updater/servo_updater.py
+++ b/extra/usb_updater/servo_updater.py
@@ -19,7 +19,7 @@ import json
import fw_update
import ecusb.tiny_servo_common as c
-
+from ecusb import tiny_servod
class ServoUpdaterException(Exception):
"""Raised on exceptions generated by servo_updater."""
@@ -82,48 +82,25 @@ def flash2(vidpid, serialno, binfile):
else:
raise ServoUpdaterException("%s exit with res = %d" % (cmd, res))
-def connect(vidpid, iface, serialno, debuglog=False):
- """Connect to console.
-
- Args:
- vidpid: vidpid of desired device.
- iface: interface to connect.
- serialno: serial number, to differentiate multiple devices.
- debuglog: do chatty log.
-
- Returns:
- a connected pty object.
- """
- # Make sure device is up.
- c.wait_for_usb(vidpid, serialname=serialno)
-
- # make a console.
- pty = c.setup_tinyservod(vidpid, iface,
- serialname=serialno, debuglog=debuglog)
-
- return pty
-
-def select(vidpid, iface, serialno, region, debuglog=False):
+def select(tinys, region):
"""Ensure the servo is in the expected ro/rw partition."""
if region not in ["rw", "ro"]:
raise Exception("Region must be ro or rw")
- pty = connect(vidpid, iface, serialno)
-
if region is "ro":
cmd = "reboot"
else:
cmd = "sysjump %s" % region
- pty._issue_cmd(cmd)
- time.sleep(1)
- pty.close()
+ tinys.pty._issue_cmd(cmd)
+ time.sleep(2)
+ tinys.reinitialize()
-def do_version(vidpid, iface, serialno):
+def do_version(tinys):
"""Check version via ec console 'pty'.
Args:
- see connect()
+ tinys: TinyServod object
Returns:
detected version number
@@ -133,26 +110,23 @@ def do_version(vidpid, iface, serialno):
# ...
# Build: tigertail_v1.1.6749-74d1a312e
"""
- pty = connect(vidpid, iface, serialno)
-
cmd = '\r\nversion\r\n'
regex = 'Build:\s+(\S+)[\r\n]+'
- results = pty._issue_cmd_get_results(cmd, [regex])[0]
- pty.close()
+ results = tinys.pty._issue_cmd_get_results(cmd, [regex])[0]
return results[1].strip(' \t\r\n\0')
-def do_updater_version(vidpid, iface, serialno):
+def do_updater_version(tinys):
"""Check whether this uses python updater or c++ updater
Args:
- see connect()
+ tinys: TinyServod object
Returns:
updater version number. 2 or 6.
"""
- vers = do_version(vidpid, iface, serialno)
+ vers = do_version(tinys)
# Servo versions below 58 are from servo-9040.B. Versions starting with _v2
# are newer than anything _v1, no need to check the exact number. Updater
@@ -270,17 +244,22 @@ def main():
brdfile, binfile = findfiles(args.board, args.file)
serialno = args.serialno
- debuglog = (args.verbose is True)
with open(brdfile) as data_file:
data = json.load(data_file)
-
- vidpid = "%04x:%04x" % (int(data['vid'], 0), int(data['pid'], 0))
+ vid, pid = int(data['vid'], 0), int(data['pid'], 0)
+ vidpid = "%04x:%04x" % (vid, pid)
iface = int(data['console'], 0)
boardname = data['board']
+
+ # Make sure device is up.
+ c.wait_for_usb(vidpid, serialname=serialno)
+ # We need a tiny_servod to query some information. Set it up first.
+ tinys = tiny_servod.TinyServod(vid, pid, iface, serialno, args.verbose)
+
if not args.force:
- vers = do_version(vidpid, iface, serialno)
+ vers = do_version(tinys)
print("Current %s version is %s" % (boardname, vers))
newvers = find_available_version(boardname, binfile)
@@ -288,16 +267,20 @@ def main():
if newvers == vers:
print("No version update needed")
- if args.reboot is True:
- select(vidpid, iface, serialno, "ro", debuglog=debuglog)
+ if args.reboot:
+ select(tinys, 'ro')
return
else:
print("Updating to recommended version.")
- select(vidpid, iface, serialno, "ro", debuglog=debuglog)
+ # Make sure the servo MCU is in RO
+ select(tinys, 'ro')
- vers = do_updater_version(vidpid, iface, serialno)
+ vers = do_updater_version(tinys)
+ # To make sure that the tiny_servod here does not interfere with other
+ # processes, close it out.
+ tinys.close()
if vers == 2:
flash(brdfile, serialno, binfile)
elif vers == 6:
@@ -305,9 +288,15 @@ def main():
else:
raise ServoUpdaterException("Can't detect updater version")
- select(vidpid, iface, serialno, "rw", debuglog=debuglog)
+ # Make sure device is up.
+ c.wait_for_usb(vidpid, serialname=serialno)
+ # After we have made sure that it's back/available, reconnect the tiny servod.
+ tinys.reinitialize()
+
+ # Make sure the servo MCU is in RW
+ select(tinys, 'rw')
- vers = do_updater_version(vidpid, iface, serialno)
+ vers = do_updater_version(tinys)
if vers == 2:
flash(brdfile, serialno, binfile)
elif vers == 6:
@@ -315,7 +304,8 @@ def main():
else:
raise ServoUpdaterException("Can't detect updater version")
- select(vidpid, iface, serialno, "ro", debuglog=debuglog)
+ # Make sure the servo MCU is in RO
+ select(tinys, 'ro')
if __name__ == "__main__":
main()