summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Broch <tbroch@chromium.org>2014-08-18 17:53:35 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-08-20 21:07:26 +0000
commitf8fbd1e440f87502b85e71c14719b58cfa79ebea (patch)
treef49100c6cb7a0089da65742a7bde0b31db8545e2
parent6a99f7d0a432a1ab040b0548cfa32259b90e804b (diff)
downloadchrome-ec-f8fbd1e440f87502b85e71c14719b58cfa79ebea.tar.gz
flash_pd.py: Add retries for commands for collision resilience.
The original version of the script worked but as the USB PD protocol SM has been enhanced to handle more complicated scenarios the occurrence of collisions on the baseband comm has grown and script needs to account for that. Script now checks status of ACK from zinger 'DONE 0' and retries two additional times for commands that failed. If those three attempts are unsuccessful script raises exception and quits. Also added some more logging around retries and progress of chunk writes. BRANCH=none BUG=chrome-os-partner:30135 TEST=manual, util/flash_pd.py build/zinger/ec.RW.flat succeeds in programming zinger even in light of some retries. Change-Id: Iaa8a22c2510ea5f4ebd92e1715be5fe062e13c61 Signed-off-by: Todd Broch <tbroch@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/213131 Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rwxr-xr-xutil/flash_pd.py59
1 files changed, 44 insertions, 15 deletions
diff --git a/util/flash_pd.py b/util/flash_pd.py
index 2ae64b730e..f6ea1f2230 100755
--- a/util/flash_pd.py
+++ b/util/flash_pd.py
@@ -2,7 +2,11 @@
# Copyright (c) 2014 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.
-"""Flash PD PSU RW firmware over the USBPD comm channel using console."""
+"""Flash PD PSU RW firmware over the USBPD comm channel using console.
+
+ Example:
+ util/flash_pd.py ./build/zinger/ec.RW.flat
+"""
import array
import errno
@@ -118,21 +122,38 @@ class FlashPD(client.ServoClient):
if done or time.time() > deadline:
break
if not done:
- logging.error('\"%s\" missing', val)
+ logging.debug("Expect '%s' missing", val)
return (done, l)
- def flash_command(self, cmd, expect='DONE'):
+ def flash_command(self, cmd, expect='DONE 0', retries=2):
"""Send PD Flash command and interrogate output.
Args:
- cmd : string of 'pd port flash' command to execute
- expect : string of expected response after 'cmd'
+ cmd : string of 'pd port flash' command to execute
+ expect : string of expected response after 'cmd'
+ retries : integer number of times to repeat command if it fails.
Returns:
- found : boolean, whether response matches expected.
+ tuple :
+ found : boolean, whether response matches expected.
+ line : string of line returned by expect method.
+
+ Raises:
+ FlashPDError: if command failed to match expected return string after
+ retries.
"""
- self._serial.write('pd %d flash %s\n' % (self._options.multiport, cmd))
- (found, line) = self.expect(expect)
+ tries = retries + 1
+ for i in xrange(tries):
+ self._serial.write('pd %d flash %s\n' % (self._options.multiport, cmd))
+ (found, line) = self.expect(expect)
+ if i:
+ time.sleep(1)
+ logging.debug("pd flash cmd Retry%d for '%s'", i, cmd)
+ if found:
+ break
+ if (i + 1) == tries and not found:
+ raise FlashPDError("Failed pd flash cmd: '%s' after %d retries\n" %
+ (cmd, retries))
return (found, line)
def get_version(self):
@@ -154,6 +175,16 @@ class FlashPD(client.ServoClient):
raise FlashPDError('Unable to determine PD FW version')
return m.group(1)
+ def reboot(self):
+ """Reboot PSU.
+
+ Use 'version' to poll for success after DONE encountered.
+ Raises:
+ FlashPDError : If unable to reboot
+ """
+ self.flash_command('reboot', expect=r'DONE', retries=0)
+ self.flash_command('version', retries=10)
+
def flash_pd(options):
"""Flash power delivery firmware."""
@@ -182,9 +213,7 @@ def flash_pd(options):
# reset flashed hash to reboot in RO
ec.flash_command('hash' + ' 00000000' * 5)
# reboot in RO
- ec.flash_command('reboot')
- # delay to give time to reboot
- time.sleep(1.5)
+ ec.reboot()
# erase all RW partition
ec.flash_command('erase')
@@ -199,7 +228,7 @@ def flash_pd(options):
logging.info('Successfully erased flash.')
if options.eraseonly:
- ec.flash_command('reboot')
+ ec.reboot()
logging.info('After erase, FW version is %s', ec.get_version())
return
@@ -208,13 +237,13 @@ def flash_pd(options):
chunk = words[i * 6: (i + 1) * 6]
cmd = ' '.join(['%08x' % (w) for w in chunk])
ec.flash_command(cmd)
+ if not i % 0x10:
+ logging.info('Chunk %d of %d done.', i, len(words) / 6)
# write new firmware hash
ec.flash_command('hash ' + sha_str)
# reboot in RW
- ec.flash_command('reboot')
- # delay for reboot
- time.sleep(1.5)
+ ec.reboot()
logging.info('Flashing DONE.')
logging.info('SHA-1: %s', sha_str)