question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RPi4: 'Error 90 performing SPI data transfer.'

See original GitHub issue

“Describe the bug” I’m trying to receive analog readings from an esp32 connected to my Raspberry Pi 4 over SPI. The code below works perfectly on an Raspberry Pi 3B+, but when I try to run the exact same code on a Pi 4 then adc_0.Read(tmp) gives me this “unGoogleable” error: Error 90 performing SPI data transfer. Does anyone have any idea what the problem might be?

C#-code: (.NET Core 3.1)

using System;
using System.Device.Spi;

namespace SPITest1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var spiTester = new SpiTester();
            var result = spiTester.Test1();
        }

    }

    public class SpiTester
    {
        SpiDevice adc_0;
        private readonly int clockFrequency = 10_000_000;//48_000_000; //48MHz;
        private readonly SpiMode spiMode = SpiMode.Mode3;
        private readonly int dataBitLength = 8;

        private ushort[] sampleArray;
        private byte[] tmp;

        public SpiTester()
        {
            sampleArray = new ushort[16 * 1000];
            tmp = new byte[16 * 1000 * 2];

            SpiConnectionSettings spiSettings_0 = new SpiConnectionSettings(0, 0)
            {
                ClockFrequency = clockFrequency,
                Mode = spiMode,
                DataBitLength = dataBitLength
            };

            adc_0 = SpiDevice.Create(spiSettings_0);
        }
        public ushort[] Test1()
        {
            Array.Clear(sampleArray, 0, sampleArray.Length);
            Array.Clear(tmp, 0, tmp.Length);

            adc_0.Read(tmp);

            for (int i = 0; i < sampleArray.Length; i++)
            {
                sampleArray[i] = (ushort)(tmp[i * 2 + 1] | tmp[i * 2] << 8);
            }

            return sampleArray;
        }
    }
}

Arduino-code:

#include <Arduino.h>
#include <SPI.h>
#include <ESP32DMASPISlave.h>

typedef union
{
    uint16_t Sample;
    struct 
    {
        uint8_t LowBits;
        uint8_t HighBits;
    } SampleBits;
}t16Byte;

const int numberOfChannels = 16;
const int numberOfSamples = 1000;
static const uint32_t BUFFER_SIZE = 2 * (numberOfChannels * numberOfSamples);

ESP32DMASPI::Slave slave;
uint8_t* spi_slave_tx_buf;

t16Byte analogReadings[numberOfChannels * numberOfSamples];

void setup() 
{
    Serial.begin(115200);
    spi_slave_tx_buf = slave.allocDMABuffer(BUFFER_SIZE);

    slave.setDataMode(SPI_MODE3);
    slave.setMaxTransferSize(BUFFER_SIZE);
    slave.setDMAChannel(2);
    slave.setQueueSize(1);
    
    // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12
    slave.begin(HSPI);

    for (uint16_t i = 0; i < (numberOfChannels*numberOfSamples); i++)
    {
        analogReadings[i].Sample = i;
    }    
}

void loop() 
{
    if (slave.remained() == 0)
    {
        Serial.printf("Sending data!\n");
        
        for (int sampleIndex = 0; sampleIndex < BUFFER_SIZE-1; sampleIndex +=2)
        {
            spi_slave_tx_buf[sampleIndex] = analogReadings[sampleIndex/2].SampleBits.HighBits;
            spi_slave_tx_buf[sampleIndex+1] = analogReadings[sampleIndex/2].SampleBits.LowBits;
        }
        slave.queue(NULL, spi_slave_tx_buf, BUFFER_SIZE);
        slave.yield();
        
        Serial.printf("Data sendt!\n");
    }
    delay(500);
}

Expected behavior adc_0.Read(tmp); should give me an array of data from my esp32.

Actual behavior adc_0.Read(tmp); throws the following error:

Exception has occurred: CLR/System.IO.IOException
An unhandled exception of type 'System.IO.IOException' occurred in System.Device.Gpio.dll: 'Error 90 performing SPI data transfer.'
   at System.Device.Spi.UnixSpiDevice.Transfer(Byte* writeBufferPtr, Byte* readBufferPtr, Int32 buffersLength)
   at System.Device.Spi.UnixSpiDevice.Read(Span`1 buffer)
   at SPITest1.SpiTester.Test1() in C:\Users\jesper.andersson\source\repos\SPITest1\SPITest1\Program.cs:line 46
   at SPITest1.Program.Main(String[] args) in C:\Users\jesper.andersson\source\repos\SPITest1\SPITest1\Program.cs:line 12

dotnet --info

.NET Core SDK (reflecting any global.json):
 Version:   3.1.102
 Commit:    573d158fea

Runtime Environment:
 OS Name:     raspbian
 OS Version:  10
 OS Platform: Linux
 RID:         linux-arm
 Base Path:   /home/pi/dotnet/sdk/3.1.102/

Host (useful for support):
  Version: 3.1.2
  Commit:  916b5cba26

.NET Core SDKs installed:
  3.1.102 [/home/pi/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.App 3.1.1 [/home/pi/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.2 [/home/pi/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.1 [/home/pi/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.2 [/home/pi/dotnet/shared/Microsoft.NETCore.App]

Version of System.Device.Gpio : “1.0.0”

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
jesperandersson89commented, Mar 12, 2020

Fixed it! The error comes from trying to read mode bytes than the SPI-buffer on Rasbian allows by default. (4096) The solution is either to create a file /etc/modprobe.d/spidev.conf with contents: options spidev bufsiz=65536 (or preferred buffer size). OR Add this to /boot/cmdline.txt: spidev.bufsiz=65536 (or preferred buffer size).

Reboot and check your work with cat /sys/module/spidev/parameters/bufsiz

Suggesting that someone fixes the cryptic error 90 that https://github.com/dotnet/iot/blob/master/src/System.Device.Gpio/System/Device/Spi/Devices/UnixSpiDevice.Linux.cs throws on line 227?

The problem here is Marshal.GetLastWin32Error(), because error 90 does not exist. Ref. https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-

Edit*: (Hmmm… error 90 is EMSGSIZE - “Message too long” in unix… so maybe I should have figured it out sooner?)

0reactions
joperezrcommented, Mar 12, 2020

Awesome I’m glad you found the issue and I thank you for posting the fix here so people in the future can come back to this if they ever hit it. Feel free to open an issue for fixing error messages from our API since I agree we should try to flush as much info as possible here.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TFT Display not working on RPi4 - Raspberry Pi Forums
So I follow this procedure on both RPis, on the 3B+ the display works, on the 4 it doesn't. I don't modify the...
Read more >
SPI failed to write. errno: 90, Message too long - Software ...
I have a raspberry pi 4 with the newest Hyperion (hyperion/stable,now 2.0.12~bullseye) release. I have installed an LED SK6812 strip on the ...
Read more >
Raspberry Pi Python data transfer error.
I'm developing a project on a Raspberry pi CM4 module with Open PLC. My project is as follows; I collect data from various...
Read more >
Enable SPI and I2C on Ubuntu 20.04 Raspberry Pi
Update, a step-by-step guide to enabling I2C: · Navigate to raspi-config on archive.raspberrypi.org. · This results in an error, reporting missing ...
Read more >
What is the maximum speed of SPI in Raspberry Pi 4B?
I need this for fast data exchange with FPGA so I have pretty much any choice of interface for communication. I also thought...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found