Applications - GPIO Based IRQ

Introduction

This topic shows how the General Purpose Input/Output (GPIO) Interrupt Request (IRQ) functionality of the SAMA5D2 Series ARM® Cortex®-A5 Microprocessor Unit (MPU) is enabled in the Linux® kernel and how to access the GPIO IRQ in User Space.

In general, the GPIO IRQ functionality has been introduced into the Linux kernel and can be accessed via the standard kernel API request_irq().

Since the IRQ of SAMA5D2 is also shared by the Peripheral Input/Output (PIO) controller, each and every GPIO pin can be used as an external interrupt. In this kind of application, the GPIO pins can be configured to be monitored. When there is input change on a specific GPIO pin, the IRQ interrupt will be asserted by the PIO controller.

The GPIO based IRQ uses a lower IRQ handle level than external IRQs, so the response time is slower. However, the GPIO based IRQ may be good enough in most cases for your application. In this topic, we show you how to request and handle a GPIO IRQ in User Space via the /dev/gpiochip0 device node.


Prerequisites

This application is developed for the ATSAMA5D27-SOM1-EK1 development platform:

This application is developed using the Buildroot build system:


Hardware

For this application, you will be controlling the GPIO IRQ pin of the mikroBUS™ 1 expansion socket of the ATSAMA5D27-SOM1-EK1. The figure below shows the expansion capability of the SOM1-EK1.

ATSAMA5D27_SOM1_EK1_expansion_01.png

mikroBUS

You will monitor and control the INT_mBUS1 pin on the mikroBUS 1 connector. It is connected to the ATSAMA5D27-SOM1 pin PB0 which is assigned the IRQ number 83. The IRQ number was assigned by the software when registering the interrupt. We’ll show you how it was done below.

mikroBUS 1 pin Schematic Name IRQ Number Package Pin
J25 pin 2 INT_mBUS1 83 PB0

For more details of the Package and Pinout of the SAMA5D2, refer to “Table 6-2. Pinouts” in SAMA5D2 Series Datasheet.

mikroBUS 1

mikrobus1_R1.png

Buildroot Configuration

Objective: Using Buildroot, build a bootable image and FLASH onto an SD Memory Card for the ATSAMA5D27-SOM1-EK1 development board.

Follow the steps for building the image in the topic Create Project with Default Configuration. In the topic, you will use the default configuration file: atmel_sama5d27_som1_ek_mmc_dev_defconfig.


Device Tree

Objective: Observe how the GPIO IRQ functionality was configured in the device tree. No changes are required.

Once Buildroot has completed its build, the IRQ definitions for the ATSAMA5D27-SOM1-EK1 were configured by a Device Tree. The Device Tree Source (DTS) include files (*.dtsi and *.dts) are located in the Buildroot output directory: /output/build/linux-linux4sam_6.0/arch/arm/boot/dts/.

1

Examine the sama5d2.dtsi file and observe the GPIO IRQ functionality assignments:

667   pioA_clk: pioA_clk {
668      #clock-cells = <0>;
669      reg = <18>;
670      atmel,clk-output-range = <0 83000000>;
671   };
.
.
1493  pioA: pinctrl@fc038000 {
1494     compatible = "atmel,sama5d2-pinctrl";
1495     reg = <0xfc038000 0x600>;
1496     interrupts = <18 IRQ_TYPE_LEVEL_HIGH 7>,
1497              <68 IRQ_TYPE_LEVEL_HIGH 7>,
1498              <69 IRQ_TYPE_LEVEL_HIGH 7>,
1499              <70 IRQ_TYPE_LEVEL_HIGH 7>;
1500     interrupt-controller;
1501     #interrupt-cells = <2>;
1502     gpio-controller;
1503     #gpio-cells = <2>;
1504     clocks = <&pioA_clk>;
1505  };

Line 669 shows the PID of pioA is 18. This definition of the offset will be used to enable the pioA clock in the PMC.

Line 670 shows the pioA input clock, the maximum frequency is 83 MHz.

Line 1494 specifies which driver will be used for the pioA device.

Line 1495 shows the pioA address is 0xfc038000, size is 0x600.

Line 1496 to 1499 show that there are 128 GPIO pins divided into four banks, each GPIO bank has its own IRQ line.

Line 1497 shows each GPIO bank has its own IRQ line.

The definitions of IRQ_TYPE are available in the file: buildroot/output/build/linux-linux4sam_6.0/include/dt-bindings/interrupt-controller/irq.h

Line 1504 shows the definition for pioA clock source.


Kernel

Objective: Observe how GPIO IRQ functionality was configured in the Linux kernel. No changes are required.

The GPIO IRQ functionality is made available in User Space by the GPIO chip driver. Thus, you can develop IRQ functionality applications in User Space.

1

From the buildroot directory, run the Linux kernel menuconfig:

$ make linux-menuconfig

The top-level menu will be displayed:

linux-config-top-level.png

Device Driver

2

Select Device Drivers —->.

linux-config-device-drivers.png

3

Select Pin controllers —->.

4

Observe that -*- AT91 PIO4 pinctrl driver is selected.

With this setting, pinctrl and gpio drivers will be built into the kernel. Then, you can access the GPIO driver via the device node in rootfs: /dev/gpiochip0.

at91_pio4_pinctrl_driver.png

Rootfs

User Space:
As discussed in the Device Tree section above, the GPIO IRQ functionality is registered as gpiochip0. Enabling the kernel feature (default) you can access GPIO driver via /dev/gpiochip0 device node.


Application

The following is a C-Language demonstration program (gpio_irq.c) for demonstrating the GPIO based IRQ in User Space:

To compile:

$ buildroot/output/host/bin/arm-buildroot-linux-uclibcgnueabihf-gcc gpio_irq.c -o irq_test

Be sure to type in the location of the cross-compiler on your host computer.

Source code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <string.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>

#define DEV_GPIO  "/dev/gpiochip0"

#define POLL_TIMEOUT -1 /* No timeout */

int main(int argc, char *argv[])
{
    int fd, fd_in;
    int ret;
    int flags;

    struct gpioevent_request req;
    struct gpioevent_data evdata;
    struct pollfd fdset;

    /* open gpio */
    fd = open(DEV_GPIO, O_RDWR);
    if (fd < 0) {
        printf("ERROR: open %s ret=%d\n", DEV_GPIO, fd);
        return -1;
    }

    /* Request gpio_pb0 interrupt */
    // 128 gpio in gpiochip0
    // 0  ~ 31    PA0 -> PA31
    // 32 ~ 63  PB0 -> PB31
    // 33 ~ 95  PC0 -> PC31
    // 96 ~ 127 PD0 -> PD31
    req.lineoffset = 32;
    req.handleflags = GPIOHANDLE_REQUEST_INPUT;
    req.eventflags  = GPIOEVENT_REQUEST_BOTH_EDGES;
    strncpy(req.consumer_label, "gpio_irq", sizeof(req.consumer_label) - 1);

    /* requrest line event handle */
    ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req);
    if (ret) {
        printf("ERROR: ioctl get line event ret=%d\n", ret);
        return -1;
    }

    /* set event fd nonbloack read */
    fd_in = req.fd;
    flags = fcntl(fd_in, F_GETFL);
    flags |= O_NONBLOCK;
    ret = fcntl(fd_in, F_SETFL, flags);
    if (ret) {
        printf("ERROR: fcntl set nonblock read\n");
    }

    for (;;) {
        fdset.fd      = fd_in;
        fdset.events  = POLLIN;
        fdset.revents = 0;

        /* poll gpio line event */
        ret = poll(&fdset, 1, POLL_TIMEOUT);
        if (ret <= 0)
            continue;

        if (fdset.revents & POLLIN) {
            printf("irq received.\n");
            /* read event data */
            ret = read(fd_in, &evdata, sizeof(evdata));
            if (ret == sizeof(evdata))
                printf("id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp);
        }
    }

    /* close gpio */
    close(fd);

    return 0;
}

Hands On

Copy the irq_test program to the target and execute.

Trigger the INT_mBUS1 pin with a falling edge or rising edge signal.

  1. chmod +x irq_test
  2. ./irq_test

irq received.
id: 2, timestamp: 1326702743513717054
irq received.
id: 1, timestamp: 1326702744536525542
irq received.
id: 2, timestamp: 1326702745118564762
irq received.
id: 1, timestamp: 1326702745694055688


Summary

In this topic, you used Buildroot to build an image with GPIO IRQ functionality for the ATSAMA5D2 Series MPU. You accessed the GPIO IRQ via User Space by the /dev/gpiochip0 device node. You also accessed the GPIO IRQ driver using a C-Language program. You walked through the device tree and kernel to observe how the embedded Linux system configures the source code for building.

© 2020 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.