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
CFLAGS=-O2 -std=c89 -W -Werror -Wall -Wextra -pedantic -I.
LFLAGS=-lm
CFILES=$(wildcard ./*.c)
all:
$(CC) $(CFLAGS) main.c i2c.c lis3dh.c -o lis3dh $(LFLAGS)
$(CC) $(CFLAGS) $(CFILES) -o lis3dh $(LFLAGS)
clean:
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

46
main.c
View File

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