aos/tools/imx8x/board_ctrl.py
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

163 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python3
##########################################################################
# Copyright (c) 2019 ETH Zurich.
# All rights reserved.
#
# This file is distributed under the terms in the attached LICENSE file.
# If you do not find this file, copies can be found by writing to:
# ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
# Attn: Systems Group.
#
# Script to control the Toradex boards over the USB UART
#
##########################################################################
import os
import sys
import time
import usb
import argparse
import cmd
class AOSBoard:
BITMODE_CBUS = 0x20
SIO_SET_BITMODE_REQUEST = 0x0b
def __init__(self, dev):
self._dev = dev
def _ftdi_set_bitmode(self, bitmask):
"""
FTDIs CBUS bitmode expect the following value:
CBUS Bits
3210 3210
|------ Output Control 0->LO, 1->HI
|----------- Input/Output 0->Input, 1->Output
This script assumes:
- CBUS3 connected to RESET_EXT#
- CBUS2 connected to OE# (recovery mode)
"""
bm_request_type = usb.util.build_request_type(
usb.util.CTRL_OUT,
usb.util.CTRL_TYPE_VENDOR,
usb.util.CTRL_RECIPIENT_DEVICE
)
wValue = bitmask | (AOSBoard.BITMODE_CBUS << 32)
self._dev.ctrl_transfer(bm_request_type, AOSBoard.SIO_SET_BITMODE_REQUEST, wValue)
def on(self):
# Set CBUS3 tristate, module run...
self._ftdi_set_bitmode(0x00)
def off(self):
# Set CBUS3 low, module in reset...
self._ftdi_set_bitmode(0x80)
def reset(self):
self.off()
time.sleep(0.1)
self.on()
def enter_recovery(self):
# Set recovery bit low
self._ftdi_set_bitmode(0x40)
time.sleep(0.2)
# Set reset bit low
self._ftdi_set_bitmode(0xC0)
time.sleep(0.1)
# Set reset bit tristate
self._ftdi_set_bitmode(0x40)
time.sleep(0.01)
# Set recovery bit tristate
self._ftdi_set_bitmode(0x00)
class BoardShell(cmd.Cmd):
def __init__(self, board):
super().__init__()
self._board = board
self.prompt = "aos-ctrl> "
def do_on(self, args):
"Turn the board on."
self._board.on()
def do_off(self, args):
"Turn the board off."
self._board.off()
def do_reset(self, args):
"Reset the board."
self._board.reset()
def do_recovery(self, args):
"Reset the board and enter recovery mode."
self._board.enter_recovery()
def do_exit(self, args):
"Exit the command prompt."
return True
def postcmd(self, stop, line):
return stop
def get_usb_backend():
if sys.platform == "win32":
# On Windows we can use libusb1 in combination with usbdk
# https://github.com/libusb/libusb/wiki/Windows#Driver_Installation
import usb.backend.libusb1
libusb_path = os.environ.get("LIBUSB_PATH")
backend = usb.backend.libusb1.get_backend(find_library=lambda x: libusb_path)
if backend is None:
print("Couldn't find libusb backend. Try setting LIBUSB_PATH environment variable.", file=sys.stderr)
return None
# PyUSB doesn't expose libusb option to use usbdk
# Workaround: https://github.com/pyusb/pyusb/issues/200#issuecomment-392621726
from ctypes import c_void_p, c_int
backend.lib.libusb_set_option.argtypes = [c_void_p, c_int]
backend.lib.libusb_set_option(backend.ctx, 1)
return backend
return None
def main(args):
dev = usb.core.find(
custom_match=lambda d: \
d.idVendor == 0x0403 and
d.idProduct == 0x6001 and
(
(args.board is None) or
(d.serial_number == args.board)
),
backend=get_usb_backend()
)
if dev is None:
if args.board is None:
print("No board found.", file=sys.stderr)
else:
print("Board with serial '%s' not found." % (args.board), file=sys.stderr)
exit(1)
board = AOSBoard(dev)
shell = BoardShell(board)
if args.command is None:
shell.cmdloop()
else:
shell.onecmd(args.command)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Controls the Toradex Colibri boards")
parser.add_argument(
"--board", "-b", metavar="SERIAL", type=str,
help="Serial of the board to control"
)
parser.add_argument(
"command", metavar="CMD", type=str, nargs='?',
help="Commands to run"
)
args = parser.parse_args()
main(args)