summaryrefslogtreecommitdiff
path: root/extra/usb_spi/stm32spi.py
blob: a8948c0002968e57e5e247ea670f78dfb7895c76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/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()