interrupt generation

This commit is contained in:
William Clark 2023-12-28 18:10:34 +00:00
parent e1f2040e6c
commit 7ec153d397
4 changed files with 162 additions and 17 deletions

View File

@ -1,8 +1,9 @@
CC=gcc CC=gcc
CFLAGS=-O2 -std=c89 -W -Werror -Wall -Wextra -pedantic -I. CFLAGS=-O2 -std=c89 -W -Werror -Wall -Wextra -pedantic -I.
LFLAGS=-lm LFLAGS=-lm
CFILES=$(wildcard ./*.c)
all: all:
$(CC) $(CFLAGS) main.c i2c.c lis3dh.c -o lis3dh $(LFLAGS) $(CC) $(CFLAGS) $(CFILES) -o lis3dh $(LFLAGS)
clean: clean:
rm -rf lis3dh rm -rf lis3dh

119
interrupt.c Normal file
View File

@ -0,0 +1,119 @@
/*
SYSFS gpio interrupt example for Raspberry Pi
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include "interrupt.h"
static int write_file(const char *path, const char *str) {
int fd = 0;
if ((fd = open(path, O_WRONLY)) == 0) {
fprintf(stderr, "unable to open %s\n", path);
return 1;
}
if (write(fd, str, strlen(str)) < 1) {
fprintf(stderr, "unable to write to %s\n", path);
close(fd);
return 1;
}
close(fd);
return 0;
}
/* Register a sysfs GPIO pin to be interruptable
similar to:
$ echo 12 > /sys/class/gpio/export
$ echo both > /sys/class/gpio12/edge
$ echo in > /sys/class/gpio12/direction
*/
int int_register(int pin) {
char path[1024];
char buffer[64];
/* begin by unregistering supplied pin, just in case */
(void) int_unregister(pin);
memset(buffer, 0, 64);
sprintf(buffer, "%d", pin);
if (write_file("/sys/class/gpio/export", buffer) != 0) {
return 1;
}
/* sleep 500 ms to let linux set up the dir .. */
usleep(500000);
memset(path, 0, 1024);
sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "edge");
if (write_file(path, "both") != 0) {
return 1;
}
memset(path, 0, 1024);
sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "direction");
if (write_file(path, "in") != 0) {
return 1;
}
return 0;
}
/* unregister an interrupt gpio config
similar to:
$ echo 12 > /sys/class/gpio/unexport
*/
int int_unregister(int pin) {
char buffer[64];
memset(buffer, 0, 64);
sprintf(buffer, "%d", pin);
if (write_file("/sys/class/gpio/unexport", buffer) != 0) {
return 1;
}
return 0;
}
/* poll a gpio pin for interrupt event
blocking
*/
int int_poll(int pin) {
int fd;
struct pollfd pfd;
char path[1024];
char buf[16];
memset(path, 0, 1024);
sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "value");
if ((fd = open(path, O_RDONLY)) == 0) {
fprintf(stderr, "unable to open %s\n", path);
return 1;
}
pfd.fd = fd;
pfd.events = POLLPRI | POLLERR;
lseek(fd, 0, SEEK_SET);
read(fd, buf, sizeof buf);
poll(&pfd, 1, -1);
lseek(fd, 0, SEEK_SET);
read(fd, buf, sizeof buf);
return 0;
}

11
interrupt.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef INTERRUPT_H
#define INTERRUPT_H
/*
Note: `pin' is GPIO No.
*/
int int_register(int pin);
int int_unregister(int pin);
int int_poll(int pin);
#endif

26
main.c
View File

@ -4,8 +4,11 @@
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <math.h>
#include "lis3dh.h" #include "lis3dh.h"
#include "interrupt.h"
#include "i2c.h" #include "i2c.h"
#define GPIO_INTERRUPT_PIN 12
/* calc magnitude of accel [x y z] vector */ /* calc magnitude of accel [x y z] vector */
float mag(float x, float y, float z) { float mag(float x, float y, float z) {
return sqrt( powf(x, 2) + powf(y, 2) + powf(z, 2) ); return sqrt( powf(x, 2) + powf(y, 2) + powf(z, 2) );
@ -14,6 +17,7 @@ float mag(float x, float y, float z) {
/* print message then exit */ /* print message then exit */
void quit(const char *msg, lis3dh_t *lis) { void quit(const char *msg, lis3dh_t *lis) {
lis->dev.deinit(); lis->dev.deinit();
int_unregister(GPIO_INTERRUPT_PIN);
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
exit(1); exit(1);
} }
@ -22,7 +26,7 @@ int main() {
lis3dh_t lis; lis3dh_t lis;
struct lis3dh_fifo_data fifo; struct lis3dh_fifo_data fifo;
int i, k; int k;
/* set fn ptrs to rw on bus (i2c or SPI) */ /* set fn ptrs to rw on bus (i2c or SPI) */
lis.dev.init = i2c_init; lis.dev.init = i2c_init;
@ -37,22 +41,28 @@ int main() {
quit("init()", &lis); quit("init()", &lis);
} }
/* register interrupt */
if (int_register(GPIO_INTERRUPT_PIN)) {
quit("int_register()", &lis);
}
/* set up config */ /* set up config */
lis.cfg.mode = LIS3DH_MODE_NORMAL; lis.cfg.mode = LIS3DH_MODE_NORMAL;
lis.cfg.range = LIS3DH_FS_2G; lis.cfg.range = LIS3DH_FS_2G;
lis.cfg.rate = LIS3DH_ODR_100_HZ; lis.cfg.rate = LIS3DH_ODR_100_HZ;
lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM; lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM;
lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1;
lis.cfg.pin1.overrun = 1;
/* write device config */ /* write device config */
if (lis3dh_configure(&lis)) { if (lis3dh_configure(&lis)) {
quit("configure()", &lis); quit("configure()", &lis);
} }
for (i=0; i<100; i++) { /* wait for interrupt from LIS3DH */
if (int_poll(GPIO_INTERRUPT_PIN)) {
/* poll fifo reg */ quit("int_poll()", &lis);
if (lis3dh_poll_fifo(&lis)) {
quit("poll_fifo()", &lis);
} }
/* read stored fifo data into `fifo' struct */ /* read stored fifo data into `fifo' struct */
@ -65,6 +75,10 @@ int main() {
fifo.x[k], fifo.y[k], fifo.z[k], fifo.x[k], fifo.y[k], fifo.z[k],
mag(fifo.x[k], fifo.y[k], fifo.z[k])); mag(fifo.x[k], fifo.y[k], fifo.z[k]));
} }
/* unregister interrupt */
if (int_unregister(GPIO_INTERRUPT_PIN)) {
quit("int_unregister()", &lis);
} }
/* deinitalise struct */ /* deinitalise struct */