GPIO With Interrupts

Hi,

I’m currently trying to create a GPIO library for the TX1 akin to RPi.GPIO, but am having a lot of trouble trying to implement functions like add_event_detect, which allows for the usage of a threaded interrupt handler with a callback to execute when an interrupt is detected. I’ve tested my implementations of the simpler functionalities (setup, cleanup, output, simple input reads), but I’m completely stuck on the interrupt handling.

My first thought was to try and emulate the RPi.GPIO codebase, but it started to get very complicated and frankly all I really need is a way to check for interrupts/signal changes on a single GPIO pin without using up a lot of system resources, as I will need to handle GPIO inputs alongside some resource-intensive vision processing. If anyone has implemented a similar solution or could point me in the right direction that would be hugely appreciated!

Thanks,
Harris

hello harrisjj4l1,

here’s documentation for your reference.
you could download it via [Release 28.1 Development Guide]-> [PDF Documents]-> [Tegra Linux Driver Package TX1 Adaptation Guide]

also, you’re able to enable the gpio manually following below.

- Location of the GPIOs
# cd /sys/class/gpio
- Generate gpio220 for example.
# echo 220 > export
- Enable the gpio
# echo out > direction && echo 1 > value

Jerry,

Thanks for the quick reply, but my question was more about handling IO interrupts and handling inputs.

-Harris

We are now able to monitor interrupts on gpio38, however it seems as though interrupts are constantly being received from this pin. The value changes properly based on the input signal, however our script does not generate an interrupt only on manually triggered edges. Instead we are getting an endless stream of interrupts. Before running this test script, we are executing the following commands:

- From within the /sys/class/gpio folder, export pin 38 to user space
# sudo sh -c "echo 38 > export"
- Change into that directory and set up edge detection on the pin
# cd gpio38 && sudo sh -c "echo both > edge"

Then we run the following script to monitor (adapted from here: https://www.linux.com/learn/beaglebone-black-how-get-interrupts-through-linux-gpio:

#include <glib.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "jetsonGPIO.h"

static gboolean
onButtonEvent (GIOChannel *channel,
               GIOCondition condition,
               gpointer user_data )
{
    gchar buf[100];
    gsize buf_sz = 100;

    std::cerr << "onButtonEvent" << std::endl;
    GError *error = 0;
    gsize bytes_read = 0;
    g_io_channel_seek_position (channel, 0, G_SEEK_SET, 0);
    GIOStatus rc = g_io_channel_read_chars (channel,
                                            buf, buf_sz - 1,
                                            &bytes_read,
                                            &error);
    std::cerr << "rc:" << rc << " data:" << buf << std::endl;

    // call again!
    return 1;
}

int main (int argc, char **argv)
{
    // Spawn an event loop
    GMainLoop* loop = g_main_loop_new (0, 0);
    
    // Open the pin's value file for non-blocking read and keep track of the file descriptor
    int fd = open ("/sys/class/gpio/gpio38/value", O_RDONLY | O_NONBLOCK);
    
    // Create a glib iochannel using the newly obtained file descriptor and set the interrupt 
    // condition
    GIOChannel* channel = g_io_channel_unix_new (fd);
    GIOCondition cond = GIOCondition (G_IO_PRI);

    // Add a task to the event loop to watch for interrupts and call the onButtonEvent 
    // function when one is detected
    guint id = g_io_add_watch (channel, cond, onButtonEvent, 0);

    // Run the main loop
    g_main_loop_run (loop);
}

Our output looks like this:

onButtonEvent
rc:1 data:1
B
onButtonEvent
rc:1 data:1
B
onButtonEvent
rc:1 data:1
B
onButtonEvent
rc:1 data:1
B
onButtonEvent
rc:1 data:1
B
...

I’m not entirely sure where the B is coming from, nor why interrupts are being sent without a change to the value of the pin.