Controlling GPIOs on a PIC64GX Curiosity Board From Linux® Userspace
Introduction
General Purpose Input/Output (GPIO) pins are essential for interacting with hardware components like LEDs and Dual In-line Package (DIP) switches on embedded systems, In a Linux® environment, you can control these GPIOs to turn LEDs on and off or read the state of DIP switches.
This guide will walk you through the basics of using GPIOs on a PIC64GX using the PIC64GX Curiosity Board as hardware. We will use libgpiod for standard GPIO operations to control the on-board LEDs and read DIP switch states.
Prerequisites
This application is developed for the Curiosity PIC64GX1000 Kit ES development platform:
Yocto Project® Configurations
With the default configuration of the Yocto Project® image builder for the PIC64GX Curiosity Board Board Support Package (BSP), it will include the libgpiod library on the Linux system, which can be used from the userspace.
We can check configurations in the Linux Kernel, build a bootable image and Flash it onto an SD card for the PIC64GX Curiosity Board.
Follow the steps in the GitHub PIC64GX Yocto Project BSP Repo README to setup the Bitbake environment and build a core-image-minimal-dev Linux image with the default configuration:
Once the initial Linux image has been built without error, we can start configuring the Linux kernel to include the libgpiod.
Set up the Bitbake environment:
View/edit the kernel menuconfig:
After the menuconfig interactive configuration tool opens, enable the GPIO Support by navigating to:
Check if the Software Packages libgpiod and libgpiod-tools are included in your build image by navigating to your image's core recipe:
yocto-dev/meta-pic64gx-yocto-bsp/meta-pic64gx-bsp/recipes-core/images/core-image-minimal-dev.bbappend
Deploy the Linux Image on PIC64GX Curiosity Board
Steps to deploy the Yocto Project release image:
- Download the core-image-minimal-pic64gx-curiosity-kit Yocto Project image from GitHub Release Assets and unzip the wic.gz.
- Follow the instructions on GitHub to deploy the image to the SD card.
Hardware
For this application, we will control the GPIOs connected to the on-board LEDs and DIP switches of the Curiosity Board.
We can check the pins that are connected to the LEDs and DIP switches from the PIC64GX1000 Curiosity kit schematics.
Components | Connections | Components | Connections | |
---|---|---|---|---|
LED1 | GPIO1-2 | DIP1 | GPIO2-8 | |
LED2 | GPIO1-3 | DIP2 | GPIO2-9 | |
LED3 | GPIO1-4 | DIP3 | GPIO2-11 | |
LED4 | GPIO1-5 | DIP4 | GPIO2-24 | |
LED5 | GPIO1-6 | PUSH-BUTTON 1 | GPIO_2_28 | |
LED6 | GPIO1-7 | PUSH-BUTTON 2 | GPIO_2_6 | |
LED7 | GPIO1-8 | |||
LED8 | GPIO1-9 |
Software Tools and Utilities
libgpiod – C Library and Tools
libgpiod (GPIO device library) is a C library and tools for interacting with the Linux GPIO character device. This library encapsulates the ioctl() calls and data structures using a straightforward API.
For more information see the C library and tools for interacting with the Linux GPIO character device.
APIs of libgpiod
libgpiod provides a simple API to access the GPIO driver. When Yocto Project completes its build, the C header file for these APIs are located at /build/tmp-glibc/work/riscv64-oe-linux/libgpiod/1.6.3-r0/libgpiod-1.6.3/include/gpiod.h.
The libgpiod tools are located in the following folder. These provide demonstration source code that shows you how to work with the libgpiod API.
From the Yocto Project directory:
$ ls *.c
gpiodetect.c gpiofind.c gpioget.c gpioinfo.c gpiomon.c gpioset.c tools-common.c
Tools of libgpiod
There are some simple tools provided by libgpiod for accessing the GPIO driver from the shell.
In the past, GPIO was accessed by the shell from the sysfs interface. As of Linux version 4.8, this method has been deprecated. The libgpiod was developed as a more effective way to access the GPIO driver.
There are six commands in libgpiod tools:
- gpiodetect: list all gpiochips present on the system, their names, labels, and number of GPIO lines
- gpioinfo: list all lines of specified gpiochips, their names, consumers, direction, active state, and additional flags
- gpioget: read values of specified GPIO lines
- gpioset: set values of specified GPIO lines, potentially keep the lines exported and wait until timeout, user input or signal
- gpiofind: find the gpiochip name and line offset given the line name
- gpiomon: wait for events on GPIO lines, specify which events to watch, how many events to process before exiting or if the events should be reported to the console
Using libgpiod Tools on PIC64GX Curiosity Board
Detect GPIOs on the target processor:
gpiochip0 [20120000.gpio] (14 lines)
gpiochip1 [20121000.gpio] (24 lines)
gpiochip2 [20122000.gpio] (32 lines)
Print all lines of information:
[...]
gpiochip1 - 24 lines:
line 0: unnamed unused output active-high
line 1: unnamed unused output active-high
line 2: "LED1" unused output active-high
line 3: "LED2" unused output active-high
line 4: "LED3" unused output active-high
line 5: "LED4" unused output active-high
line 6: "LED5" unused output active-high
line 7: "LED6" unused output active-high
line 8: "LED7" unused output active-high
line 9: "LED8" unused output active-high
[...]
Find the GPIO chip name and offset of LED1:
gpiochip1 2
Set LED1 output high (turning on the LED1):
Set LED2 output low (turning off the LED1):
Monitor SW1 pin status:
event: FALLING EDGE offset: 28 timestamp: [1325983345.255958082]
event: RISING EDGE offset: 28 timestamp: [1325983345.256686960]
event: FALLING EDGE offset: 28 timestamp: [1325983348.205010375]
event: RISING EDGE offset: 28 timestamp: [1325983348.577229302]
Reading DIP1 Input state:
Application Programming in C Language
We can write a C program that runs from Userspace and uses the libgpiod library. The following example is a C code that will flash the LED3 five times.
Boot Linux on your Curiosity board, and navigate to /media and create gpio.c using vim editor.
Copy and paste the following C code to gpio.c:
#include <stdio.h>
#include <unistd.h>
#define CONSUMER "LED_Flasher"
#define LED_PIN 4 // Change this to the GPIO pin number connected to your LED
int main(void) {
struct gpiod_chip *chip;
struct gpiod_line *line;
int ret;
chip = gpiod_chip_open_by_name("gpiochip1"); // Change "gpiochip1" if necessary
if (!chip) {
perror("Open chip failed");
return 1;
}
line = gpiod_chip_get_line(chip, LED_PIN);
if (!line) {
perror("Get line failed");
gpiod_chip_close(chip);
return 1;
}
ret = gpiod_line_request_output(line, CONSUMER, 0);
if (ret != 0) {
perror("Request line as output failed");
gpiod_chip_close(chip);
return 1;
}
for (int i = 0; i < 5; i++) { // Flash 5 times
gpiod_line_set_value(line, 1); // LED on
sleep(1); // 1 second delay
gpiod_line_set_value(line, 0); // LED off
sleep(1); // 1 second delay
}
gpiod_line_release(line);
gpiod_chip_close(chip);
return 0;
}
After saving the modification, compile the C code:
Run the gpio executable:
Summary
We used Yocto Project to build an image with the libgpiod library and tools. We also wrote an application in C and interacted via the shell to read and write to the GPIO pins of a PIC64GX MPU.