Read of /dev/spidev1.0 always blocking

Hi,

INTRODUCTION:
I managed to configure the spi port to slave with device tree overlay.
verdin-imx8mp_spidev_overlay.dts (328 Bytes)

The SPI can receive the data properly, even though with the provided device tree overlay, the CS of the slave port is still forced high by the slave port. I circumvent this limitation, by setting the mode to
mode |= SPI_CS_HIGH; This solution is also adopted here https://community.toradex.com/t/verdin-imx8mp-spi-slave/18958

Module : verdin imx8m plus
Development board : Verdin Development Board with HDMI Adapter
Host OS : Ubuntu 22.04.2 LTS
Visual studio code 1.81.1 + ApolloX extension

ISSUE:
Now, I would like to read the /dev/spidev1.0 in non blocking mode.
Unfortunately, even if I open the file in non_blocking mode, the read function always block, until the required numbers of bytes has been transferred through SPI.
For example, in the provided main.c the program stops at the instruction

ssize_t bytesRead = read(fd, buffer, sizeof (buffer) - 1);

Could you please help me to understand why the read function is not returning immediately?

main.c (2.9 KB)

docker-compose.yml (380 Bytes)
Best Regards

Hello @VMB ,

Having a look at spidev documentation
https://git.toradex.com/cgit/linux-toradex.git/tree/Documentation/spi/spi-summary.rst?h=toradex_5.15-2.1.x-imx
we see :

The basic I/O primitive is spi_async(). Async requests may be issued in any context (irq handler, task, etc) and completion is reported using a callback provided with the message.
After any detected error, the chip is deselected and processing of that spi_message is aborted.

There are also synchronous wrappers like spi_sync(), and wrapperslike spi_read(), spi_write(), and spi_write_then_read(). These may be issued only in contexts that may sleep, and they’re all clean (and small, and “optional”) layers over spi_async().

Then in spidev documentation

https://git.toradex.com/cgit/linux-toradex.git/tree/Documentation/spi/spidev.rst?h=toradex_5.15-2.1.x-imx
we find the following:

At this time there is no async I/O support; everything is purely synchronous.

In fact, in spidev.c
https://git.toradex.com/cgit/linux-toradex.git/tree/drivers/spi/spidev.c?h=toradex_5.15-2.1.x-imx

there are no calls to spi_async(), only to spi_sync()

Best regards,
Josep

sing the SPI interface with /dev/spidev typically implies synchronous transfers. The SPI protocol itself doesn’t inherently support a “non-blocking” mode in the same way that something like a UART might, where you can read whatever bytes are currently in a buffer.

When you issue a read() on the SPI device, you’re essentially asking it to perform an SPI transfer (this might involve toggling the chip select, clocking out bytes, etc.). If the data isn’t ready or hasn’t been sent over SPI yet, the call will block until the transaction is complete. That’s the nature of the SPI device interface on Linux.

if you want to perform non-blocking operations, you can :

  • Use multi-threading where one thread is dedicated to SPI communication and the other can handle the rest of your operations.
  • Use the select() or poll() system calls to wait on multiple file descriptors. This allows you to wait for data to be ready on the SPI device or timeout if it takes too long. If the SPI descriptor becomes ready (i.e., data is available), then your read() call won’t block.
1 Like

Hi @josep.tx and @alex.tx,

thank you very much for the assistance.
I still have some doubts about what prevents the SPI to be read in non-blocking mode.

  1. Is the SPI protocol itself?

The SPI protocol itself doesn’t inherently support a “non-blocking” mode in the same way that something like a UART might, where you can read whatever bytes are currently in a buffer.

Here, I cannot understand how the SPI protocol itself can be blocking. And in which sense the behaviour of the SPI is different from the UART. My understanding is that SPI protocol has nothing to do with how the data is collected or stored.

  1. Is in the way spidev is implemented?

At this time there is no async I/O support; everything is purely synchronous.
In fact, in spidev.c
there are no calls to spi_async(), only to spi_sync()

Would it be possible in your opinion to improve spidev.c or any other file so that the read function call behaves in a non-blocking manner?

Best Regards

Hello @VMB

It might be possible ( I’m not an SPI expert in any way), based on the documentation info. But I have never done it.

Best regards,
Josep

Hi @josep.tx,

than you again.
I will try.

Best Regards

Hello @VMB

You’re welcome :slight_smile:

Please keep us updated about your progress.

Best regards,
Josep