Melange
Posts: 17
Joined: Sat Apr 24, 2021 7:50 am

Re: Using the SPI Slave peripheral to interface a simple CLOCK/DATA signal pair

Tue May 04, 2021 5:41 pm

joan wrote:
Tue May 04, 2021 5:23 pm
As I say I am not convinced your C code was doing what you meant it to do.
How do you mean?

User avatar
joan
Posts: 15621
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Using the SPI Slave peripheral to interface a simple CLOCK/DATA signal pair

Tue May 04, 2021 5:49 pm

It did not seem to be capturing data as described by the data format you gave. That is why I gave an alternative working single callback solution and its why I wrote the Python test script.

If you are convinced it works properly could you provide test data, either clock/data or just data bits to feed into a test program. You could use piscope to capture real data (clock and data) and save to file.

Melange
Posts: 17
Joined: Sat Apr 24, 2021 7:50 am

Re: Using the SPI Slave peripheral to interface a simple CLOCK/DATA signal pair

Tue May 04, 2021 6:16 pm

joan wrote:
Tue May 04, 2021 5:49 pm
It did not seem to be capturing data as described by the data format you gave. That is why I gave an alternative working single callback solution and its why I wrote the Python test script.

If you are convinced it works properly could you provide test data, either clock/data or just data bits to feed into a test program. You could use piscope to capture real data (clock and data) and save to file.
I posted a captured 64-bit sequence earlier here.

The device sends an uninterrupted, constant stream of identical 64 bit sequences at 2 kHz, so when we capture any 128 bits in this endless stream it is invariantly true that the lower and upper 64 bits must be identical or we have one or more bit errors/losses. The same is invariantly true if we pack these captured 128 bits into 16 bytes, the lower and upper 8 bytes must be identical.

All my code does is to capture a sequence of 128 bits, compare the lower and upper 64 bits and then report its findings. It works perfectly fine for hours when I activate both optimisations I mentioned earlier (have you tried that?), and it fails quickly when I don't. Why is that the case?

Melange
Posts: 17
Joined: Sat Apr 24, 2021 7:50 am

Re: Using the SPI Slave peripheral to interface a simple CLOCK/DATA signal pair

Wed May 05, 2021 3:40 am

I overlooked the somewhat new gpiochip API in the linux kernel, stumbled upon it last night.

Using it's python bindings it is very simple to accomplish what I've been trying to do, here a short working example of how to read from a pair of GPIOs (not the code I'll be using, just a short proof):

Code: Select all

#
# chardev gpio example
# read and print sequences of 128 bits from DATA GPIO on rising CLOCK edge
#
# install libgpiod Python 3 bindings using:
#   sudo apt-get install python3-libgpiod
#

import gpiod
import sys

GPIOCHIP = "/dev/gpiochip0"
GPIO_CLOCK = 19
GPIO_DATA = 20

def main(chip):
    bit_count = 0
    data = None

    lines = chip.get_lines([GPIO_CLOCK, GPIO_DATA])
    lines.request(consumer=sys.argv[0], type=gpiod.LINE_REQ_EV_BOTH_EDGES)
    while True:
        ev_lines = lines.event_wait(sec=1)
        if ev_lines:
            for line in ev_lines:
                ev = line.event_read()
                if ev.source.offset() == GPIO_CLOCK:
                    if data is not None and ev.type == gpiod.LineEvent.RISING_EDGE:
                        print(data, end='')
                        bit_count += 1
                        if bit_count == 128:
                            print()
                            bit_count = 0
                else:
                    data = 1 if ev.type == gpiod.LineEvent.RISING_EDGE else 0

if __name__ == '__main__':
    with gpiod.Chip(GPIOCHIP) as chip:
        try:
            main(chip)
        except KeyboardInterrupt:
            print()
This way my code is generic, meaning not tied exclusively to the Raspberry Pi. There is also no helping background process in user space. Also note that it is single-threaded, we're receiving GPIO events through a (pollable) event queue keeping the sequential order of the event's occurrence. Events are timestamped, too, but I'm not using these here.

I'll stick with this solution.

Melange
Posts: 17
Joined: Sat Apr 24, 2021 7:50 am

Re: Using the SPI Slave peripheral to interface a simple CLOCK/DATA signal pair

Thu May 06, 2021 11:03 am

Here I found a solid explanation for the SPI Slave instabilities that I observed (sometimes it works, sometimes it doesn't): SPI Slave (BSC Slave) Errata.

So the SPI Slave is "special" in the regard that its behaviour seems to be controlled by the LSB of the first byte that it receives from the master that I have no control over, which yields a 50:50 chance of success in my case. It's not a generic SPI Slave afterall.

Return to “C/C++”