We have upgraded the community system as part of the upgrade a password reset is required for all users before login in.

SPI Pins for the Omega2

  • Hi,

    There does not appear to be much clarity surrounding the SPI and the interfacing. The Pinout Diagram lists the GPIO pins as

    CS1 - GPIO6
    SCLK - GPIO7
    MOSI - GPIO8
    MISO - GPIO9

    The SPI default pins in both the Python and C modules are listed as

    CS/SS 7
    SCK 6
    MOSI 18
    MISO 1

    The example code makes

    spi.cs = 20
    spi.sck = 19

    and I presume leaves the MOSI and MISO as default (18 ? 1 ?)

    So I am left scratching my head as to what is what? Who has managed to connect successfully with the SPI? Next, I think I am going to have to break out the datasheets and the Oscilloscope, but I'd rather not ­čś×

    I am also guessing that there is no native kernel SPI interface and it is all bit-banging only? Yay!!!


  • @David-Lucas The pins listed on the diagram are the correct ones, the other pin-numbers you are seeing are for the Omega1. And yes, it is hardware-SPI, not bit-banged software.

  • said in SPI Pins for the Omega2:

    CS1 - GPIO6
    SCLK - GPIO7
    MOSI - GPIO8
    MISO - GPIO9

    This worked for me.
    Well, at least until some point. It allows me to write 16 bytes to the SPI bus, but if I try to send more, it doesn't work anymore. And if I try spi.writeBytes(position, bytes_list) (in python), it just inserts the byte position at the beginning of bytes_list, and has the same 16 bytes limitation.

    Did any of you experience this also ?

  • @Brice-Parent Aye, if you want to write more than 16 bytes, you have to do it in multiple takes.

  • @Brice-Parent What did you install to make it work on the omega2?
    I followed the documentation but I get an error while registering the spi device : "Failed to find spi-gpio-custom. Maybe it is a built in module ?"

  • @Pierre-Rossin├Ęs said in SPI Pins for the Omega2:

    @Brice-Parent What did you install to make it work on the omega2?
    I followed the documentation but I get an error while registering the spi device : "Failed to find spi-gpio-custom. Maybe it is a built in module ?"

    spi-gpio-custom is software-based bit-banged SPI. The hardware-SPI on GPIOs 6-9 should already be enabled by default. Just do ls -l /dev/spi* and the SPI-bus should show up.

  • @WereCatf It does show up, but when I use it with the python library as described here : https://docs.onion.io/omega2-docs/spi-python-module.html
    I get that error.

    My code is pretty simple :

    import onionSpi
    spi = onionSpi.OnionSpi(32766, 1)
    spi.sck = 7
    spi.mosi = 8
    spi.miso = 9
    spi.cs = 6

    I got the 32766, 1 part from the /dev/spi32766.1 file name

  • @WereCatf Thanks. But how do I do that? I see no equivalent of what I've found in other implementations (opening the communication, sending multiple writes, closing the com). I tried :

    pixels = []
    for i in range(16): 

    but it will write those 16 values twice, not add the second call at the end of the first.

    Also, spi.writeBytes only inserts the value of [address] at the beginning of the list of values, so it does not address the problem. The two follogins statements are equivalent :

    spi.write([0x66, 0x00, 0xFF])
    spi.writeBytes(0x66, [0x00, 0xFF])

    @Pierre-Rossin├Ęs What works for me, even if it only partially works, is the following :

    import onionSpi
    spi = onionSpi.OnionSpi(1, 32766)
    spi.speed = 1000000
    spi.mode = 0
    spi.lsbfirst = False
    spi.write([0] * 16)

    I'm not sure I need every single line though.

  • @Pierre-Rossin├Ęs Also, I don't remember what I've installed, but in my installed packages, I have (I only put the ones that seemed relevant to me) :

    fast-gpio - 0.1-1
    gpioctl-sysfs - 0.0.6-1
    libonionspi - 0.1-1
    pyOnionSpi - 0.1-1
    python-base - 2.7.13-3
    python-light - 2.7.13-3
    spi-tool - 0.1-1
    spi-tools - 1-cc6a41fdcec60610703ba6db488c621c64952898

    I don't remember having manually installed anything other that pyOnionSpi and maybe python-light (and I'm not even sure for those two...), and I particularly don't remember having installed a specific version of spi-tools like I see here... But anyway, that"s what makes it partially work here !

    Edit : But it looks like you just reversed the arguments when creating the OnionSpi object (use 1, 32766 instead of 32766, 1).

  • @Brice-Parent
    Indeed, my only mistake was to swap the arguments.
    I did not have the spi-tools package installed but I'm not sure it is really necessary.

    My code seems to work now.
    Thank you very much !

  • @Pierre-Rossin├Ęs Have you been able to write more than 16 bytes? (if you needed to of course)

  • @Brice-Parent I don't need it, I'm using the SPI to communicate with a very simple MCP3008

  • I would like to report two issues with using SPI in Python on the Omega2. The first is that the transmit and receive buffers are only 16 bytes. There should be a mechanism in the driver that allows for DMA or interrupts to allow the use of a list longer than 16 bytes. The reason I say this is that the best time between SPI bursts is about 150uS. In other words, the following code;
    spi.write([[0xAA, 0x55, 0xAA])
    spi.write([[0xAA, 0x55, 0xAA])

    will result in about 150uS between SPI transmissions. If the SPI driver would recognize that the list passed in is longer than the built-in queues and then use an interrupt or DMA to keep the queue full until the list was exhausted then a list with several hundred bytes could be sent as one continuous transmission. This would facilitate using the SPI device to drive strings of NeoPixels. As it stands now, only a string of one NeoPixel can be driven by the SPI device. This would also help in using the SPI to communicate with an SPI based tft LCD or any device that requires more than 16 bytes in a continuous burst.

    The second issue is that the first byte transmitted always sets the most significant bit to zero (when MSB first). So sending 0xAA results in 0x2A being sent. Not good. This only happens to the first byte of each burst. The only thing I changed from default was the bitrate.

    Finally, a complaint that seems to be echoed everywhere in the world of the Omega2. That is the lack of documentation. What is available has mistakes, references the Omega or leaves a lot of information out.

  • @James-Behrens I've open a ticket 12 days ago about that, without the 150uS delay that I didn't know about (I don't have a scope), but so far no answer from the team. I'll link it to your post for more info.

    Also, if you find a workaround to be able to use more than 16 bytes without having to wait for a software update, like a software SPI or another library, please tell me about it.

  • Have a look at this defect:


    That's surely the root cause of this issue in Omega2; it's in the upstream source and may represent a hardware limitation of the MT7688/7621 SoC.

  • ... and the more I look at this, I think this may not be a bug. The MT7688 hardware can handle only so many bytes per hardware transfer, but it looks like the Linux SPI permits a transfer to be broken into an array of transfers that are processed with a single Chip Select - chaining them together. So it may be some additional work is required in the C and Python libs.

  • So - about the leading bit of 'address' (which is not a pure SPI construct - there's no requirement for an address to be the first byte of a transfer, or even for transfers to be in bytes). On a hunch, I tried values of address with the top two bits being '10' (example, 0xaa, 0xb2, 0x88, etc.) and values of address with the top two bits being '11' (ex. 0xc0, 0xff, etc.) and found that anything with '10' in the top two bits loses the MSB (transfers it as '0') and anything with '11' in the top two bits transfers it correctly. My test hardware SPI slave is an Atmel ATmega1284P , with the clock phase/polarity set to 0 (which matches the default settings in the Linux driver) (any other settings in the AVR SPI slave corrupt the data). I tried reducing the clock rate and adding a delay but never helped.

    So I'm guessing there's a timing/phase issue there; I'll have to get the oscilloscope out and have a look.

  • @James-Behrens as you probably have seen in my messages; the Omega Python library needs to break up the SPI transfer into 16-byte chunks and chain them together in the SPI_IOC_MESSAGE() call - I think that'll solve the transfer limitation. The loss of the MSB in the first byte (aka address) happens when the top two bits are '10' and not when they're '11' and that's apparently something in the MT7688 SPI driver and/or timing of the SPI slave.

  • So here's a capture of CLK and MOSI from "spi-tool write 0xaa 0x11":


    Upper trace is MOSI, lower trace is CLK, aligned to the vertical grid (10uS). You see the CLK leading-edge transitions are in the middle of the data - it all looks right except the first '1' bit is missing (far left, the first clock transition occurs while MOSI is 0).

    This is "spi-tool write 0xca 0x11":


    So here, MOSI starts with an abbreviated '1' bit, only about 1/2 as long as it should be, though the rest of the data timing is correct.

    There are two problems:

    • list itemWhen the first two bits are '10', the leading '1' is completely not sent by the SPI peripheral.
    • list itemWhen the first two bits are '11', the leading '1' is about half as long as it should be.

    This makes me think something is amiss with the SPI peripheral - perhaps some timing in the MT7621 SPI driver?

  • Oh - a known bug in the MT7688:

Log in to reply

Looks like your connection to Community was lost, please wait while we try to reconnect.