run program on pin change - how.

I have an application that I would rather not have tied up in a loop pooling for when something needs done. This application however needs to begin running when a pin changes level. What would be the best way to do this on the beagle bone?

Eric

I have an application that I would rather not have tied up in a loop pooling
for when something needs done. This application however needs to begin
running when a pin changes level. What would be the best way to do this on
the beagle bone?

You could let the operating system poll for you on the GPIO SYSFS
entry[1], avoiding any usage of the CPU doing silly things like
spinning in loops. I found the RidgeRun example[2] to be particularly
useful.

Better yet, with devicetree, you could simply make an instance of the
gpio-keys driver. This would turn the GPIO change into a keypress
event where you can use any common mechanism for monitoring
events/keypresses to trigger your application to continue.

[1] https://www.kernel.org/doc/Documentation/gpio.txt
[2] https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals#Using_poll.28.29_to_monitor_for_GPIO_0_change

You could run menuconfig, add built-in support to the kernel for ‘*’ for Device Drivers—>Input device support—>Keyboards–>GPIO Button

GPIO buttons enable GPOI pins to act like buttons that generate key up and key down events. Then you read the /dev/input/event0 like a file. These are blocking reads rather than polling. I wrote a program that looked for brightness up and brightness down key presses to control the LCD backlight intensity. Then I installed this a service and configured to automatically start after boot.

Read this posting discussing how I got it working on a TI DM8168:
http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/p/248588/872795.aspx#872795

I pasted the important code parts below:

/// Opens the GPIO Buttons /dev/input/event*
/// \param[in] devicePath the input device path, example, /dev/input/event0
/// \return -1 if fails
int lcdBackLightOpen(char * devicePath) {

char name[256] = “Device Unknown”;

//Setup check
if (NULL == devicePath){
printf(“Device path is empty.”);
return -1;
}

strcpy(m_devicePath, devicePath);

if ((getuid ()) != 0){
printf ("*** Error Must be root to open and input device event queue\n");
return -1;
}

if(-1 < m_fileDescriptor) {
printf ("*** Warning %s is already open\n", m_devicePath);
return m_fileDescriptor;
}

//Open Device
m_fileDescriptor = open (devicePath, O_RDONLY);
if (-1 == m_fileDescriptor) {
printf ("*** Error %s is not a valid device.\n", devicePath);
return -1;
}

//Print Device Name
ioctl (m_fileDescriptor, EVIOCGNAME (sizeof (name)), name);
printf (“Reading From : %s (%s)\n”, m_devicePath, name);

printf("\nKey Map:\n");
printf(" KEY_BRIGHTNESS_INC 0x%02x (%d)\n", KEY_BRIGHTNESS_INC);
printf(" KEY_BRIGHTNESS_DEC 0x%02x (%d)\n", KEY_BRIGHTNESS_DEC);

return m_fileDescriptor;
}

/// Closes the file decriptor
void lcdBackLightClose(void) {

if(-1 < m_fileDescriptor)
{
printf (“closing %s…\n”, m_devicePath);
close(m_fileDescriptor);
m_fileDescriptor = -1;
}
}

/// The LCD back light control loop.
/// Monitors for GPIO Button events KEY_BRIGHTNESSUP and KEY_BRIGHTNESSUP
/// \remarks Has no exit path. Relys on a SIGINT to exit
void lcdBackLightControl(void)
{
struct input_event eventList[64];
int bytesReadCount = 0;
int eventCount = 0;
int eventIndex = 0;

while (1){

bytesReadCount = read (m_fileDescriptor, eventList, sizeof(eventList));
if( (int)sizeof(struct input_event) > bytesReadCount ){
//perror_exit (“read()”);
continue;
}
eventCount = bytesReadCount / (int)sizeof(struct input_event);
//printf("\nbytesReadCount %d, events %d\n", bytesReadCount, eventCount);

for( eventIndex = 0; eventIndex < eventCount; eventIndex++)
{
//lcdBackLightPrintEvent(&eventList[eventIndex]);

// Only read the key press (0x01) or key repeat (0x02) events
// Not sure where input_event value constants are defined if anywhere.
if ((EV_KEY == eventList[eventIndex].value || EV_REL == eventList[eventIndex].value ) &&
(EV_KEY == eventList[eventIndex].type)){

//lcdBackLightPrintEvent(&eventList[eventIndex]);

if( KEY_BRIGHTNESS_INC == eventList[eventIndex].code){
lcdBackLightUp();
}
else if( KEY_BRIGHTNESS_DEC == eventList[eventIndex].code){
lcdBackLightDown();
}
}
}
}
}