blob: 786c751c84ea1ea51092c6e99aabd879883d92a3 [file] [log] [blame] [edit]
#!/usr/bin/env python3
import argparse
import serial
import serial.tools.list_ports
import sys
import os
import os.path
import time
import threading
from tqdm import tqdm
parser = argparse.ArgumentParser(description='32blit binary flasher.')
parser.add_argument("command", help="Command to perform (e.g. 'save', 'dfu', 'reset')", default="save")
parser.add_argument("port", help="Name of the serial port (e.g. 'COM4', '/dev/ttyS4', etc.)")
parser.add_argument("--target", help="Target either 'sd' or 'flash'", default="sd", choices=["sd", "flash"])
parser.add_argument("--no-read", help="Do not wait to read responses", action="store_true")
parser.add_argument("file", help="Path to the binary file (e.g. 'build.stm32/voxel.bin')", nargs='?')
args = parser.parse_args()
print("32blit binary flasher.")
port = args.port
command = args.command
target = args.target
valid_ports = [port[0] for port in serial.tools.list_ports.comports()]
if port not in valid_ports:
print("Specified port '{0}' not valid".format(port))
sys.exit(os.EX_OSFILE)
serial_port = None
try:
serial_port = serial.Serial(port, 115200, timeout=1)
serial_port.reset_output_buffer()
except OSError:
print("Could not open port '{0}'".format(port))
print("The port may not exist or you may not have permission to access it.")
sys.exit(os.EX_OSFILE)
if not args.no_read:
# read thread constantly polls for responses from 32blit and
# outputs them to the screen
def read_serial(serial_port):
while True:
data = serial_port.read_until(b"\0").decode()
if data:
print(data)
read_thread = threading.Thread(target=read_serial, args=(serial_port,))
read_thread.start()
print(command)
if command == "save":
path = args.file
if not os.path.isfile(path):
print("Specified binary file '{0}' does not exist".format(path))
sys.exit(os.EX_NOINPUT)
file_size = os.stat(path).st_size
file_name = os.path.basename(path)
# send the save command to 32blit
data = "SAVE\x00{0}\x00{1}\x00".format(file_name, file_size)
serial_port.write(bytes(data, "ascii"))
# transmit the file data to 32blit
sent_byte_count = 0
chunk_size = 64
with open(path, "rb") as f:
progress = tqdm(total=file_size, desc="Flashing...", unit_scale=True, unit_divisor=1024, unit="B", ncols=70, dynamic_ncols=True)
while sent_byte_count < file_size:
# last chunk may be smaller than 64 bytes
if file_size - sent_byte_count < chunk_size:
chunk_size = file_size - sent_byte_count
# read chunk from file
data = f.read(chunk_size)
# transmit it to 32blit
serial_port.write(data)
sent_byte_count += chunk_size
# update progress bar
progress.update(chunk_size)
progress.close()
if command == "dfu":
# send the dfu command to 32blit
data = "DFU\x00"
serial_port.write(bytes(data, "ascii"))
if command == "reset":
# send the dfu command to 32blit
data = "RESET\x00"
serial_port.write(bytes(data, "ascii"))
if not args.no_read:
# wait for any responses
print("Reading responses from 32blit. Press Ctrl+C to quit.")
try:
while True:
pass
except KeyboardInterrupt:
read_thread.stop()
time.sleep(1)