Linux Kernel Driver for Pi-Plates

This was the first project of my first internship. I wrote a Linux kernel driver so a Raspberry Pi could drive Pi-Plates expansion boards.

When
2020
Status
Completed
Role
Engineering Intern, Harsch Systems
  • C
  • Linux kernel
  • SPI
  • GPIO
A Raspberry Pi surrounded by three green Pi-Plates expansion boards, laid out on a white countertop
A Raspberry Pi (center) with three Pi-Plates expansion boards, including a DAQCplate (top right). The plates stack on the Pi's 40-pin header.

The problem

I worked under Mike Harsch at Harsch Systems for an internship that spanned most of the COVID era. He built industrial control systems that relied on Pi-Plates add-on boards for the Raspberry Pi. Communication with these happened over the standard Python RPi.GPIO library. That normally works, but under heavier loads the library would force frequent, expensive context switches, which would sometimes cause it to miss strict timing requirements. My task was to move all of the I/O and the Pi-Plate protocol into the kernel, where the timing could be controlled.

I had never worked in kernel space, so this was a big learning experience for me. I relied heavily on the book Linux Device Drivers to learn how these things worked.

The finished module (pi-plate-module) talks to the plates over SPI, manages acknowledge and interrupt GPIO lines, detects timing violations, exposes a device in the standard /dev folder, and was far more reliable than the previous implementation. It supports all the Pi-Plate devices, including newer ones that used slightly different timings and protocols.

The C library

On top of the driver I wrote pi-plate-io, a user-space C library that wraps these kernel-space commands to the Pi-Plates. These can read inputs and temperatures, drive relays and stepper motors, generate waveforms, and capture oscilloscope-style traces.