Browse Source

#204

pull/205/head
mstroh76 7 months ago
parent
commit
c1a86f41f2
5 changed files with 230 additions and 107 deletions
  1. +1
    -1
      VERSION
  2. +32
    -7
      gpio/gpio.c
  3. +2
    -2
      version.h
  4. +192
    -96
      wiringPi/wiringPi.c
  5. +3
    -1
      wiringPi/wiringPi.h

+ 1
- 1
VERSION View File

@@ -1 +1 @@
3.1
3.2

+ 32
- 7
gpio/gpio.c View File

@@ -556,16 +556,30 @@ void doExport (int argc, char *argv [])
*********************************************************************************
*/

static void wfi (void)
{ exit (0) ; }
static volatile int iterations ;
static volatile int globalCounter ;

static void wfi (void) {
globalCounter++;
//printf("irq count %d/%d\n", globalCounter , iterations);
if(globalCounter>=iterations) {
printf("finished\n");
exit (0) ;
} else {
printf("I"); fflush(stdout);
}
}

void doWfi (int argc, char *argv [])
{
int pin, mode ;
int pin, mode;
int timeoutSec = 2147483647;

if (argc != 4)
iterations = 1;
globalCounter = 0;
if (argc != 4 && argc != 5 && argc != 6)
{
fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
fprintf (stderr, "Usage: %s wfi pin mode [interations] [timeout sec.]\n", argv [0]) ;
exit (1) ;
}

@@ -579,6 +593,12 @@ void doWfi (int argc, char *argv [])
fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
exit (1) ;
}
if (argc>=5) {
iterations = atoi(argv [4]);
}
if (argc>=6) {
timeoutSec = atoi(argv [5]);
}

if (wiringPiISR (pin, mode, &wfi) < 0)
{
@@ -586,8 +606,13 @@ void doWfi (int argc, char *argv [])
exit (1) ;
}

for (;;)
delay (9999) ;
printf("wait for interrupt function call \n");
for (int Sec=0; Sec<timeoutSec; ++Sec) {
printf("."); fflush(stdout);
delay (999);
}
printf("\nstopping wait for interrupt\n");
wiringPiISRStop (pin);
}




+ 2
- 2
version.h View File

@@ -1,3 +1,3 @@
#define VERSION "3.1"
#define VERSION "3.2"
#define VERSION_MAJOR 3
#define VERSION_MINOR 1
#define VERSION_MINOR 2

+ 192
- 96
wiringPi/wiringPi.c View File

@@ -72,6 +72,7 @@
#include <asm/ioctl.h>
#include <byteswap.h>
#include <sys/utsname.h>
#include <linux/gpio.h>

#include "softPwm.h"
#include "softTone.h"
@@ -406,9 +407,10 @@ static int sysFds [64] =
} ;

// ISR Data
static int chipFd = -1;
static void (*isrFunctions [64])(void) ;

static pthread_t isrThreads[64];
static int isrMode[64];

// Doing it the Arduino way with lookup tables...
// Yes, it's probably more innefficient than all the bit-twidling, but it
@@ -2112,7 +2114,7 @@ unsigned int digitalReadByte2 (void)
* waitForInterrupt:
* Pi Specific.
* Wait for Interrupt on a GPIO pin.
* This is actually done via the /sys/class/gpio interface regardless of
* This is actually done via the /dev/gpiochip interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency.
*********************************************************************************
@@ -2120,11 +2122,12 @@ unsigned int digitalReadByte2 (void)

int waitForInterrupt (int pin, int mS)
{
int fd, x ;
uint8_t c ;
int fd, ret;
struct pollfd polls ;
struct gpioevent_data evdata;
//struct gpio_v2_line_request req2;

/**/ if (wiringPiMode == WPI_MODE_PINS)
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
@@ -2132,28 +2135,146 @@ int waitForInterrupt (int pin, int mS)
if ((fd = sysFds [pin]) == -1)
return -2 ;

// Setup poll structure
// Setup poll structure
polls.fd = fd;
polls.events = POLLIN | POLLERR ;
polls.revents = 0;

// Wait for it ...
ret = poll(&polls, 1, mS);
if (ret <= 0) {
fprintf(stderr, "wiringPi: ERROR: poll returned=%d\n", ret);
} else {
//if (polls.revents & POLLIN)
if (wiringPiDebug) {
printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, sysFds [pin]) ;
}
/* read event data */
int readret = read(sysFds [pin], &evdata, sizeof(evdata));
if (readret == sizeof(evdata)) {
if (wiringPiDebug) {
printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ;
}
ret = evdata.id;
} else {
ret = 0;
}
}
return ret;
}

polls.fd = fd ;
polls.events = POLLPRI | POLLERR ;
const char DEV_GPIO_PI[] ="/dev/gpiochip0";
const char DEV_GPIO_PI5[]="/dev/gpiochip4";

// Wait for it ...
int waitForInterruptInit (int pin, int mode)
{
const char* strmode = "";

x = poll (&polls, 1, mS) ;
if (wiringPiMode == WPI_MODE_PINS) {
pin = pinToGpio [pin] ;
} else if (wiringPiMode == WPI_MODE_PHYS) {
pin = physToGpio [pin] ;
}

// If no error, do a dummy read to clear the interrupt
// A one character read appars to be enough.
/* open gpio */
sleep(1);
const char* gpiochip = PI_MODEL_5 == RaspberryPiModel ? DEV_GPIO_PI5 : DEV_GPIO_PI;
if (chipFd < 0) {
chipFd = open(gpiochip, O_RDWR);
if (chipFd < 0) {
fprintf(stderr, "wiringPi: ERROR: %s open ret=%d\n", gpiochip, chipFd);
return -1;
}
}
if (wiringPiDebug) {
printf ("wiringPi: Open chip %s succeded, fd=%d\n", gpiochip, chipFd) ;
}

if (x > 0)
{
lseek (fd, 0, SEEK_SET) ; // Rewind
(void)read (fd, &c, 1) ; // Read & clear
struct gpioevent_request req;
req.lineoffset = pin;
req.handleflags = GPIOHANDLE_REQUEST_INPUT;
switch(mode) {
default:
case INT_EDGE_SETUP:
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptMode mode INT_EDGE_SETUP - exiting\n") ;
}
return -1;
case INT_EDGE_FALLING:
req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE;
strmode = "falling";
break;
case INT_EDGE_RISING:
req.eventflags = GPIOEVENT_REQUEST_RISING_EDGE;
strmode = "rising";
break;
case INT_EDGE_BOTH:
req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
strmode = "both";
break;
}
strncpy(req.consumer_label, "wiringpi_gpio_irq", sizeof(req.consumer_label) - 1);

return x ;
//later implement GPIO_V2_GET_LINE_IOCTL req2
int ret = ioctl(chipFd, GPIO_GET_LINEEVENT_IOCTL, &req);
if (ret) {
fprintf(stderr, "wiringPi: ERROR: %s ioctl get line %d %s returned %d\n", gpiochip, pin, strmode, ret);
return -1;
}
if (wiringPiDebug) {
printf ("wiringPi: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ;
}

/* set event fd nonbloack read */
int fd_line = req.fd;
sysFds [pin] = fd_line;
int flags = fcntl(fd_line, F_GETFL);
flags |= O_NONBLOCK;
ret = fcntl(fd_line, F_SETFL, flags);
if (ret) {
fprintf(stderr, "wiringPi: ERROR: %s fcntl set nonblock read=%d\n", gpiochip, chipFd);
return -1;
}

return 0;
}


int waitForInterruptClose (int pin) {
if (sysFds[pin]>0) {
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ;
}
if (pthread_cancel(isrThreads[pin]) == 0) {
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ;
}
} else {
if (wiringPiDebug) {
fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n");
}
}
close(sysFds [pin]);
}
sysFds [pin] = -1;

/* -not closing so far - other isr may be using it - only close if no other is using - will code later
if (chipFd>0) {
close(chipFd);
}
chipFd = -1;
*/
if (wiringPiDebug) {
printf ("wiringPi: waitForInterruptClose finished\n") ;
}
return 0;
}


int wiringPiISRStop (int pin) {
return waitForInterruptClose (pin);
}

/*
* interruptHandler:
* This is a thread and gets started to wait for the interrupt we're
@@ -2164,17 +2285,30 @@ int waitForInterrupt (int pin, int mS)

static void *interruptHandler (UNU void *arg)
{
int myPin ;
int pin ;

(void)piHiPri (55) ; // Only effective if we run as root

myPin = pinPass ;
pin = pinPass ;
pinPass = -1 ;

for (;;)
if (waitForInterrupt (myPin, -1) > 0)
isrFunctions [myPin] () ;
for (;;) {
int ret = waitForInterrupt(pin, -1);
if ( ret> 0) {
if (wiringPiDebug) {
printf ("wiringPi: call function\n") ;
}
isrFunctions [pin] () ;
// wait again - in the past forever - now can be stopped by waitForInterruptClose
} else if( ret< 0) {
break; // stop thread!
}
}

waitForInterruptClose (pin);
if (wiringPiDebug) {
printf ("wiringPi: interruptHandler finished\n") ;
}
return NULL ;
}

@@ -2189,93 +2323,55 @@ static void *interruptHandler (UNU void *arg)

int wiringPiISR (int pin, int mode, void (*function)(void))
{
pthread_t threadId ;
const char *modeS ;
char fName [64] ;
char pinS [8] ;
pid_t pid ;
int count, i ;
char c ;
int bcmGpioPin ;
const int maxpin = GetMaxPin();

if (pin < 0 || pin > maxpin)
return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-%d (%d)\n", maxpin, pin) ;

/**/ if (wiringPiMode == WPI_MODE_UNINITIALISED)
if (wiringPiMode == WPI_MODE_UNINITIALISED)
return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
else if (wiringPiMode == WPI_MODE_PINS)
bcmGpioPin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
bcmGpioPin = physToGpio [pin] ;
else
bcmGpioPin = pin ;

// Now export the pin and set the right edge
// We're going to use the gpio program to do this, so it assumes
// a full installation of wiringPi. It's a bit 'clunky', but it
// is a way that will work when we're running in "Sys" mode, as
// a non-root user. (without sudo)

if (mode != INT_EDGE_SETUP)
{
/**/ if (mode == INT_EDGE_FALLING)
modeS = "falling" ;
else if (mode == INT_EDGE_RISING)
modeS = "rising" ;
else
modeS = "both" ;

sprintf (pinS, "%d", bcmGpioPin) ;

if ((pid = fork ()) < 0) // Fail
return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ;

if (pid == 0) // Child, exec
{
/**/ if (access ("/usr/local/bin/gpio", X_OK) == 0)
{
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
}
else if (access ("/usr/bin/gpio", X_OK) == 0)
{
execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
}
else
return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ;
}
else // Parent, wait
waitpid (pid, NULL, 0) ;
if (wiringPiDebug) {
printf ("wiringPi: wiringPiISR pin %d, mode %d\n", pin, mode) ;
}

// Now pre-open the /sys/class node - but it may already be open if
// we are in Sys mode...

if (sysFds [bcmGpioPin] == -1)
{
int pinFS = GPIOToSysFS(bcmGpioPin);
sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ;
if (pinFS>=0 && (sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0)
return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ;
if (isrFunctions [pin]) {
printf ("wiringPi: ISR function alread active, ignoring \n") ;
}

// Clear any initial pending interrupt

ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ;
for (i = 0 ; i < count ; ++i)
read (sysFds [bcmGpioPin], &c, 1) ;

isrFunctions [pin] = function ;
isrMode[pin] = mode;
if(waitForInterruptInit (pin, mode)<0) {
if (wiringPiDebug) {
fprintf (stderr, "wiringPi: waitForInterruptInit failed\n") ;
}
};

if (wiringPiDebug) {
printf ("wiringPi: mutex in\n") ;
}
pthread_mutex_lock (&pinMutex) ;
pinPass = pin ;
pthread_create (&threadId, NULL, interruptHandler, NULL) ;
while (pinPass != -1)
delay (1) ;
if (wiringPiDebug) {
printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]);
}
if (pthread_create (&isrThreads[pin], NULL, interruptHandler, NULL)==0) {
if (wiringPiDebug) {
printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]);
}
while (pinPass != -1)
delay (1) ;
} else {
if (wiringPiDebug) {
printf("wiringPi: pthread_create failed\n");
}
}

if (wiringPiDebug) {
printf ("wiringPi: mutex out\n") ;
}
pthread_mutex_unlock (&pinMutex) ;

if (wiringPiDebug) {
printf ("wiringPi: wiringPiISR finished\n") ;
}
return 0 ;
}



+ 3
- 1
wiringPi/wiringPi.h View File

@@ -239,7 +239,7 @@ extern void piBoardId (int *model, int *rev, int *mem, int *m
extern int wpiPinToGpio (int wpiPin) ;
extern int physPinToGpio (int physPin) ;
extern void setPadDrive (int group, int value) ;
extern void setPadDrivePin (int pin, int value); // Interface V2
extern void setPadDrivePin (int pin, int value); // Interface V3.0
extern int getAlt (int pin) ;
extern void pwmToneWrite (int pin, int freq) ;
extern void pwmSetMode (int mode) ;
@@ -256,6 +256,8 @@ extern void digitalWriteByte2 (int value) ;

extern int waitForInterrupt (int pin, int mS) ;
extern int wiringPiISR (int pin, int mode, void (*function)(void)) ;
extern int wiringPiISRStop (int pin) ; //V3.2
extern int waitForInterruptClose(int pin) ; //V3.2

// Threads



Loading…
Cancel
Save