#!/usr/bin/env python2 # Copyright 2016 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. # Test program to access SPI via stm32 raiden debug spi. import usb import usb.core import usb.util class SSpiBus(object): """SPI bus class to access devices on the bus. Usage: bus = SSpiBus() # read 1 byte from register(0x16) bus.wr_rd([0x16], 1) # write 2 bytes to register(0x20) bus.wr_rd([0x20, 0x01, 0x02]) Instance Variables: _dev: pyUSB device object _read_ep: pyUSB read endpoint for this interface _write_ep: pyUSB write endpoint for this interface """ def __init__(self, vendor=0x18d1, product=0x501a, interface=2, serialname=None): # Find the stm32. dev = usb.core.find(idVendor=vendor, idProduct=product) if dev is None: raise Exception("SPI", "USB device not found") print "Found stm32: %04x:%04x" % (vendor, product) self._dev = dev # Get an endpoint instance. cfg = dev.get_active_configuration() intf = usb.util.find_descriptor(cfg, bInterfaceNumber=interface) self._intf = intf print "InterfaceNumber: %s" % intf.bInterfaceNumber read_ep = usb.util.find_descriptor( intf, # match the first IN endpoint custom_match=\ lambda e: \ usb.util.endpoint_direction(e.bEndpointAddress) == \ usb.util.ENDPOINT_IN ) self._read_ep = read_ep print "Reader endpoint: 0x%x" % read_ep.bEndpointAddress write_ep = usb.util.find_descriptor( intf, # match the first OUT endpoint custom_match=\ lambda e: \ usb.util.endpoint_direction(e.bEndpointAddress) == \ usb.util.ENDPOINT_OUT ) self._write_ep = write_ep print "Writer endpoint: 0x%x" % write_ep.bEndpointAddress self.enable(True) print "Set up stm32 spi" def enable(self, enable): # USB_RIR_OUT = 0 | USB_TYPE_VENDOR = (0x02 << 5) | # USB_RECIP_INTERFACE = 0x01 bmRequestType = 0x41 # USB_SPI_REQ_ENABLE = 0x0000, USB_SPI_REQ_DISABLE = 0x0001 if enable: bmRequest = 0x0 else: bmRequest = 0x1 print "ctrl_transfer(0x%x, 0x%x, 0, 0x%x, null)" % ( bmRequestType, bmRequest, self._intf.bInterfaceNumber) ret = self._dev.ctrl_transfer( bmRequestType, bmRequest, 0, self._intf.bInterfaceNumber, '') print "ctrl_transfer ret - %s" % ret def wr_rd(self, write_list, read_count=None): """Implements hdctools wr_rd() interface. This function writes byte values list to I2C device, then reads byte values from the same device. Args: write_list: list of output byte values [0~255]. read_count: number of byte values to read from device. Interface: write: [write_count, read_count, data ... ] read: [data .. ] """ print "SSpi.wr_rd(write_list=%s, read_count=%s)" % ( write_list, read_count) # Clean up args from python style to correct types. write_length = 0 if write_list: write_length = len(write_list) if not read_count: read_count = 0 # Send wr_rd command to stm32. cmd = [write_length, read_count] + write_list print "WR: %s" % cmd ret = self._write_ep.write(cmd, 100) print "RET: %s " % ret # Read back response if necessary. bytesread = self._read_ep.read(read_count + 2, 1000) print "BYTES: %s " % bytesread if len(bytesread) < 2: raise Exception("SPI", "Read status failed.") print "STATUS: 0x%02x%02x" % (int(bytesread[1]), int(bytesread[0])) return bytesread[2:] def main(): bus = SSpiBus() # write 2 bytes to register(0x20) bus.wr_rd([0x90, 0x00, 0x00, 0x00], 2) # read 1 byte from register(0x16) bus.wr_rd([0x9f], 3) if __name__ == "__main__": main()