Raspberry Pi CM5 IoT In C - Getting Started With SPI
Written by Harry Fairhead   
Monday, 29 December 2025
Article Index
Raspberry Pi CM5 IoT In C - Getting Started With SPI
SPI Protocol
SPIDev
Full Listing

Putting all of this together gives us the complete program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
int main(int argc, char **argv)
{
    checkSPI0();
    uint8_t tx[] = {0xAA};
    uint8_t rx[] = {0};
    struct spi_ioc_transfer tr =
        {
            .tx_buf = (unsigned long)tx,
            .rx_buf = (unsigned long)rx,
            .len = 1,
            .delay_usecs = 0,
            .speed_hz = 500000,
            .bits_per_word = 8,
        };
    int fd = open("/dev/spidev0.0", O_RDWR);   
    int status = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (status < 0)
        printf("can't send data");
    printf("%X,%X", tx[0],rx[0]);
    close(fd);
}

Note: The checkSPI0 function needs to be added to this listing.

If you run the program and don't get any data, or receive the wrong data, then the most likely reason is that you have connected the wrong two pins, or not connected them at all. If you connect a logic analyzer to the four pins involved you will see the data transfer:

If you look carefully you will see the CS0 line go low before the master places the first data bit on the MOSI, and hence on the MISO line. Notice that the clock rises in the middle of each data bit, making this a mode 0 transfer.

SPI1

If you need to configure the SPI interface you can use the ioctl calls. For example:

    static uint8_t mode = 1;
    int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        printf("can't set spi mode");
    static uint8_t bits = 8;
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        printf("can't set bits per word");
    static uint32_t speed = 500000;
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        printf("can't set max speed hz");

After this you should see mode 1 selected and the clock going high at the start of each bit.

All of the SPI interfaces all have a set of drivers that follow a standard pattern, where n is the port number. They use one or two chips selects respectively:

  • spin-1cs, cs0_pin = pin

  • spin-2cs, cs0_pin = pin1,cs1_pin = pin2

If you don’t specify a pin to be used for the chip select then the default used is the pin shown above.

SPI1 also has the possibility of using three chip selects:

  • spi1-3cs, cs0_pin = pin1,cs1_pin = pin2,cs2_pin = pin3

It is also worth knowing that the drivers do not use the SPI hardware’s chip select implementation. Instead they use a general GPIO line and set it high and low under software control. This means you can use any GPIO line as a chip select, not just the ones supported by the hardware.

You can also use the csm_spidev parameter to prevent the creation of an SPI driver node for the mth chip select.

SPI0 is the same on all models of Pi and this is the one you should consider as first choice if you value compatibility.

In Chapter but not included in this extract

  • SPI with Gpio5
  • SPI Read/Write Function
  • Loopback Example Using GPIO5 
  • The MCP3008
  • Connecting to the CM5
  • Basic Configuration
  • The Protocol
  • MCP3008 in Gpio5 
  • How Fast
  • The MCP3008 Driver 
  • Problems

 Summary

  • The CM5 has six SPI controllers but not all can be used at the same time.

  • Making SPI work with any particular device has four steps:

    1. Discover how to connect the device to the SPI pins. This is a matter of identifying pinouts and what chip selects are supported.

    2. Find out how to configure the Pi's SPI bus to work with the device. This is mostly a matter of clock speed and mode.

    3. Identify the commands that you need to send to the device to get it to do something and what data it sends back as a response.

    4. Find, or work out, the relationship between the raw reading, the voltage, and the quantity the voltage represents.

  • The Linux SPI driver can be used to interface to any SPI device as long as you know what commands to send and what the data sent back means.

  • The SPI driver is supported by the SPIdev header which provides the basic tools to work with the ioctl interface.

  • The SPI driver uses general GPIO lines as chip select lines and not the built-in hardware.

  • The hardware SPI controllers are based on Synopsys DW_apb_ssi and this is well documented.

  • It is easy to extend Gpio5 to work with SPI with many advantages.

  • Using the other SPI interfaces on the CM5 is just a matter of selecting the appropriate driver.

  • The MCP3000 range of A-to-D converters is very easy to use via SPI. It can be used directly from the SPI bus by sending commands and reading the data generated.

  • There is also a specific MCP3008 driver which allows you to work with the device without having to know anything about SPI or the commands that have to be sent to read the data.

  • The MCP3008 driver is an example of an IIO device.

 

Raspberry Pi Compute Module 5
IoT In C
Using Linux
Drivers and Gpio5

By Harry Fairhead

CIoTCM5360
Buy from Amazon.

Contents

  1. The CM5 For The IoT
  2. Setting Up the CM5
  3. C and Visual Studio Code
  4. Drivers: A First Program
  5. The GPIO Character Drive
  6. GPIO Using I/O Control
  7. GPIO Events
  8. GPIO Hardware With Gpio5 
          Extract:  GPIO Registers 
  9. Some Electronics
  10. The Device Tree
  11. Pulse Width Modulation
        
    Extract: PWM Using GPIO5
  12. SPI Devices
         Extract: Getting Started With SPI ***NEW!!!
  13. I2C Driver and Gpio5
  14. Sensor Drivers – Linux IIO & hwmon
  15. 1-Wire Bus
  16. The PIO
        
    Extract: Getting Started With PIO
  17. Going Further With Drivers
  18. Almost Real-Time Linux
  19. Appendix I Gpio5

 <ASIN:1871962951> 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Facebook or Linkedin.

Banner


Vite+ - A New Toolset
01/12/2025

There's a  drop-in upgrade to Vite with additional features. The developers say Vite+ is a command-line developer tool you can install from npm, just like Vite itself.



Codacy Releases AI Risk Reduction Tool
04/12/2025

Codacy has launched two new products to help control genAI coding.  AI Risk Hub and AI Reviewer form a code compliance suite that organizations can use for governance of AI-generated code and sma [ ... ]


More News

pico book

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Wednesday, 31 December 2025 )