| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- #!/usr/bin/env python
- """
- The WiPy firmware update script. Transmits the specified firmware file
- over FTP, and then resets the WiPy and optionally verifies that software
- was correctly updated.
- Usage:
- ./update-wipy.py --file "path_to_mcuimg.bin" --verify
- Or:
- python update-wipy.py --file "path_to_mcuimg.bin"
- """
- import sys
- import argparse
- import time
- import socket
- from ftplib import FTP
- from telnetlib import Telnet
- def print_exception(e):
- print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno))
- def ftp_directory_exists(ftpobj, directory_name):
- filelist = []
- ftpobj.retrlines('LIST',filelist.append)
- for f in filelist:
- if f.split()[-1] == directory_name:
- return True
- return False
- def transfer_file(args):
- with FTP(args.ip, timeout=20) as ftp:
- print ('FTP connection established')
- if '230' in ftp.login(args.user, args.password):
- print ('Login successful')
- if '250' in ftp.cwd('/flash'):
- if not ftp_directory_exists(ftp, 'sys'):
- print ('/flash/sys directory does not exist')
- if not '550' in ftp.mkd('sys'):
- print ('/flash/sys directory created')
- else:
- print ('Error: cannot create /flash/sys directory')
- return False
- if '250' in ftp.cwd('sys'):
- print ("Entered '/flash/sys' directory")
- with open(args.file, "rb") as fwfile:
- print ('Firmware image found, initiating transfer...')
- if '226' in ftp.storbinary("STOR " + 'mcuimg.bin', fwfile, 512):
- print ('File transfer complete')
- return True
- else:
- print ('Error: file transfer failed')
- else:
- print ('Error: cannot enter /flash/sys directory')
- else:
- print ('Error: cannot enter /flash directory')
- else:
- print ('Error: ftp login failed')
- return False
- def reset_board(args):
- success = False
- try:
- tn = Telnet(args.ip, timeout=5)
- print("Connected via Telnet, trying to login now")
- if b'Login as:' in tn.read_until(b"Login as:", timeout=5):
- tn.write(bytes(args.user, 'ascii') + b"\r\n")
- if b'Password:' in tn.read_until(b"Password:", timeout=5):
- # needed because of internal implementation details of the WiPy's telnet server
- time.sleep(0.2)
- tn.write(bytes(args.password, 'ascii') + b"\r\n")
- if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5):
- print("Telnet login succeeded")
- tn.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program
- time.sleep(1)
- tn.write(b'\r\x02') # ctrl-B: enter friendly REPL
- if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5):
- tn.write(b"import machine\r\n")
- tn.write(b"machine.reset()\r\n")
- time.sleep(2)
- print("Reset performed")
- success = True
- else:
- print("Error: cannot enter friendly REPL")
- else:
- print("Error: telnet login failed")
- except Exception as e:
- print_exception(e)
- finally:
- try:
- tn.close()
- except Exception as e:
- pass
- return success
- def verify_update(args):
- success = False
- firmware_tag = ''
- def find_tag (tag):
- if tag in firmware_tag:
- print("Verification passed")
- return True
- else:
- print("Error: verification failed, the git tag doesn't match")
- return False
- retries = 0
- while True:
- try:
- # Specify a longer time out value here because the board has just been
- # reset and the wireless connection might not be fully established yet
- tn = Telnet(args.ip, timeout=10)
- print("Connected via telnet again, lets check the git tag")
- break
- except socket.timeout:
- if retries < 5:
- print("Timeout while connecting via telnet, retrying...")
- retries += 1
- else:
- print('Error: Telnet connection timed out!')
- return False
- try:
- firmware_tag = tn.read_until (b'with CC3200')
- tag_file_path = args.file.rstrip('mcuimg.bin') + 'genhdr/mpversion.h'
-
- if args.tag is not None:
- success = find_tag(bytes(args.tag, 'ascii'))
- else:
- with open(tag_file_path) as tag_file:
- for line in tag_file:
- bline = bytes(line, 'ascii')
- if b'MICROPY_GIT_HASH' in bline:
- bline = bline.lstrip(b'#define MICROPY_GIT_HASH ').replace(b'"', b'').replace(b'\r', b'').replace(b'\n', b'')
- success = find_tag(bline)
- break
- except Exception as e:
- print_exception(e)
- finally:
- try:
- tn.close()
- except Exception as e:
- pass
- return success
- def main():
- cmd_parser = argparse.ArgumentParser(description='Update the WiPy firmware with the specified image file')
- cmd_parser.add_argument('-f', '--file', default=None, help='the path of the firmware file')
- cmd_parser.add_argument('-u', '--user', default='micro', help='the username')
- cmd_parser.add_argument('-p', '--password', default='python', help='the login password')
- cmd_parser.add_argument('--ip', default='192.168.1.1', help='the ip address of the WiPy')
- cmd_parser.add_argument('--verify', action='store_true', help='verify that the update succeeded')
- cmd_parser.add_argument('-t', '--tag', default=None, help='git tag of the firmware image')
- args = cmd_parser.parse_args()
- result = 1
- try:
- if args.file is None:
- raise ValueError('the image file path must be specified')
- if transfer_file(args):
- if reset_board(args):
- if args.verify:
- print ('Waiting for the WiFi connection to come up again...')
- # this time is to allow the system's wireless network card to
- # connect to the WiPy again.
- time.sleep(5)
- if verify_update(args):
- result = 0
- else:
- result = 0
- except Exception as e:
- print_exception(e)
- finally:
- sys.exit(result)
- if __name__ == "__main__":
- main()
|