Pi IoT In C Using Linux Drivers - The SPI Driver
Written by Harry Fairhead   
Monday, 31 May 2021
Article Index
Pi IoT In C Using Linux Drivers - The SPI Driver
A Loopback Example
Pi SPI Interfaces

SPI is a very popular way of connecting devices to the Raspberry Pi and the good news is that it is well supported by Linux drivers - once you know how.

This content comes from my newly published book:

Raspberry Pi IoT In C Using Linux Drivers

By Harry Fairhead

Cdrivers360

Buy from Amazon.

Contents

  1.  Choosing A Pi For IoT

  2. C and Visual Studio Code

  3.  Drivers: A First Program

  4.  The GPIO Character Driver
         Extract: GPIO Character Driver

  5. GPIO Using I/O Control

  6.  GPIO Events

  7.  The Device Tree
        Extract: The DHT22

  8.  Some Electronics

  9.  Pulse Width Modulation
    Extract:  The PWM Driver 

  10. SPI Devices
    Extract: The SPI Driver 

  11. I2C Basics

  12. The I2C Linux Driver ***NEW!

     

  13. Advanced I2C

  14. Sensor Drivers – Linux IIO & Hwmon
      Extract: Hwmon  

  15. 1-Wire Bus
      Extract: 1-Wire And The DS18B20 

  16. Going Further With Drivers

  17. Appendix I

 <ASIN:1871962641>

<ASIN:B08W9V7TP9>

In chapter but not in book:

  • SPI Devices
  • SPI Bus Basics
  • Pi SPI Interfaces
  • SPI Protocol

SPI Driver

Before you can use the SPI bus you have to load its driver. You can do this by adding:

dtparam=spi=on

to the /boot/config.txt file. This loads a driver for SPI0 using two chip select lines. To find out how to activate other SPI channels see later. For the rest of this section we will be using SPI0.

Alternatively you can activate the driver dynamically:

FILE *doCommand(char *cmd)
{
    FILE *fp = popen(cmd, "r");
    if (fp == NULL)
    {
        printf("Failed to run command %s \n\r", cmd);
        exit(1);
    }
    return fp;
}
void checkSPI0()
{
    FILE *fd = doCommand("sudo  dtparam -l");
    char output[1024];
    int txfound = 0;
    char indicator[] = "spi=on";
    char command[] = "sudo dtparam spi=on";
    while (fgets(output, sizeof(output), fd) != NULL)
    {
        printf("%s\n\r", output);
        fflush(stdout);
        if (strstr(output, indicator) != NULL)
        {
            txfound = 1;
        }
    }
    if (txfound == 0)
    {
        fd = doCommand(command);
        sleep(2);
    }
    pclose(fd);
}

This works by first using the dtparam -l command to list the loaded overlays. If the spi overlay is already loaded nothing is done. If it isn’t then it runs the command:

dtparam spi=on

SPIDev

The interface to the SPI driver is generally referred to as SPIdev and there is an spidev.h header file which provides all of the definitions you need to make use of it. When you load the SPI driver to install SPI Channel n a number of character devices are created in /dev of the general form spidevn.m where n is the channel number and m is the chip select line used to control the device.

For example, the basic SPI driver uses channel 0, i.e. SPI0 with two chip select lines, and thus you will find spidev0.0 and spidev0.1 which control the SPI device connected to SPI0 on chip select 0 and 1 respectively. By default, spidev0.0 uses GPIO8 pin 26 and spidev0.1 uses GPIO7 pin 28 for chip selects.

To work with an SPI device all you have to do is use ioctl to send requests to the relevant file. If you want to know more about ioctl see Chapter 4.

There are a range of configuration requests:

  • SPI_IOC_WR_MODE    	
    sets mode
  • SPI_IOC_WR_LSB_FIRST  	
    sets LSB first or last
  • SPI_IOC_WR_BITS_PER_WORD 	
    sets number of bits per word
  • SPI_IOC_WR_MAX_SPEED_HZ 
    sets SPI clock if possible

Note: SPI_IOC_WR_LSB_FIRST isn’t supported on Pi OS.

There are also requests with WR replaced by RD which read, rather than write, the configuration.

<ASIN:187196265X>

<ASIN:B01HGCSGXM>



Last Updated ( Monday, 31 May 2021 )