Embedded Linux C++ Interrupt Polling epoll

Embedded Linux C++ Interrupt Polling epoll


The following Qt C++ code snippet demonstrates how to poll a file descriptor representing an interrupt line in Embedded Linux.

#include "interrupthandler.h"

/// Define the IRQ Path exposed for the HDMI chip

#define NXP_IRQ_PATH ("/sys/class/gpio/gpio62/value")

/// Define the number of file descriptors to be monitored by epoll

#define EPOLL_QUEUE_LEN 1

/**

* @brief InterruptHandler::InterruptHandler Constructor

*/

InterruptHandler::InterruptHandler() {

// Print a status message

qDebug() << "COMPANY NXP HANDLER: Beginning to monitor NXP HDMI Chip ( TDA19988 )...";

// Initially always start polling

m_FinishedPolling = false;

// Create a sender object for dbus nmformation

m_DbusSender = new SendDbusHdmiData("com.company.proj.camera.command", "/receive_mode_change", QDBusConnection::sessionBus(), 0);

/// We will monitor for interrupts by allowing Linux to notify us of one on sysfs by means of epoll

/// An epoll instance is created by epoll_create(2) or epoll_create1(2) (they take different arguments),

/// which return an epoll instance. epoll_ctl(2) is used to add/remove descriptors to be watched on the epoll instance.

/// To wait for events on the watched set, epoll_wait(2) is used, which blocks until events are available.

/// Please see their manpages for more info.

/* The epoll event structure that you pass to epoll_ctl(2) is shown below. With every descriptor being watched, you can associate an integer or a pointer as user data.

typedef union epoll_data

{

void *ptr;

int fd;

__uint32_t u32;

__uint64_t u64;

} epoll_data_t;

struct epoll_event

{

__uint32_t events; <-- Epoll events

epoll_data_t data; <-- User data variable

};

*/

// Open the gpio file descriptor for the interrupt

int nxpIrqFd = open(NXP_IRQ_PATH,O_RDONLY);

// Create an epoll set for use with this file descriptor

// EPOLL_QUEUE_LEN is the number of file descriptors to be monitored

int pollFd = epoll_create(EPOLL_QUEUE_LEN);

// Check that we could open the IRQ file and also create the epoll set

if ( nxpIrqFd >= 0 && pollFd != -1 ) {

// epoll event structure for monitoring irq file descriptor

struct epoll_event ev;

struct epoll_event evs;

// Set up what epoll watches for and the file descriptor we care about

ev.events = EPOLLPRI | EPOLLERR | EPOLLET;

ev.data.fd = nxpIrqFd;

// Add the gpio file descriptor to the epoll set

// When nxpIrqFd descriptor will be closed, it will be automatically deleted from epoll descriptor.

if( 0 == epoll_ctl(pollFd, EPOLL_CTL_ADD, nxpIrqFd, &ev) ) {

// As long as we are supposed to poll - do so

while(!m_FinishedPolling) {

// Wait a while, then see if there is a pending interrupt

usleep(10);

// Wait for something to do

/*

The epoll_wait() system call waits for events on the epoll(7)

instance referred to by the file descriptor epfd. The memory area

pointed to by events will contain the events that will be available

for the caller. Up to maxevents are returned by epoll_wait(). The

maxevents argument must be greater than zero.

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

while specifying a timeout equal to zero cause epoll_wait() to return

immediately, even if no events are available.

*/

int status = epoll_wait( pollFd,&evs,1,0 ); // Returns the number of file descriptors ready for the requested io

if ( status ) {

// If we received events in evs, read data

if ( evs.events & EPOLLPRI ){

// Get the file descriptor of the data that is ready, seek to the beginning

// and read the data

char c;

int fd = evs.data.fd;

lseek(fd,0,SEEK_SET);

read(fd, &c, 1);

}

}

}

}

else {

// Error using epoll to monitor irq file descriptor

qDebug() << "COMPANY NXP HANDLER: Error! Could not use epoll to watch file descriptor for: " << NXP_IRQ_PATH;

}

}





ClassyBits 2016