Переглянути джерело

Merge pull request #205 from WiringPi/isr

Implement ISR for all Raspberry Pi Boards - new driver interface
pull/209/head
Manfred Wallner 8 місяці тому
committed by GitHub
джерело
коміт
28050cc41d
Не вдалося знайти GPG ключ що відповідає даному підпису Ідентифікатор GPG ключа: B5690EEEBB952194
9 змінених файлів з 581 додано та 219 видалено
  1. +2
    -0
      README.md
  2. +1
    -1
      VERSION
  3. +169
    -0
      examples/isr3.c
  4. +51
    -7
      gpio/gpio.c
  5. +39
    -6
      reinstall
  6. +2
    -2
      version.h
  7. +250
    -201
      wiringPi/wiringPi.c
  8. +3
    -1
      wiringPi/wiringPi.h
  9. +64
    -1
      wiringPi/wiringPiLegacy.c

+ 2
- 0
README.md Переглянути файл

@@ -135,6 +135,8 @@ wiringPi has been wrapped for multiple languages:

Please use the [issue system](https://github.com/WiringPi/WiringPi/issues) of GitHub.

If you're not sure whether to create an issue or not, please engage in [discussions](https://github.com/WiringPi/WiringPi/discussions)!

Please do not email Gordon or @Gadgetoid.

Please don't email GC2 for reporting issues, you might [contact us](mailto:wiringpi@gc2.at) for anything that's not meant for the public.


+ 1
- 1
VERSION Переглянути файл

@@ -1 +1 @@
3.1
3.2

+ 169
- 0
examples/isr3.c Переглянути файл

@@ -0,0 +1,169 @@
/*
* isr3.c:
* Wait for Interrupt test program WiringPi >=3.2 - ISR method
*
*
*/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wpiExtensions.h>
#include <unistd.h>
#include <sys/time.h>

// globalCounter:
// Global variable to count interrupts
// Should be declared volatile to make sure the compiler doesn't cache it.

static volatile int globalCounter;
volatile long long gStartTime, gEndTime;

/*
* myInterrupt:
*********************************************************************************
*/

static void wfi (void) {
struct timeval now;

gettimeofday(&now, 0);
if (0==gStartTime) {
gStartTime = now.tv_sec*1000000LL + now.tv_usec;
} else {
gEndTime = now.tv_sec*1000000LL + now.tv_usec;
}
globalCounter++;
}

/*
*********************************************************************************
* main
*********************************************************************************
*/

double StartSequence (int Enge, int OUTpin) {
int expected;
double timeExpected;

gStartTime = 0;
gEndTime = 0;
globalCounter = 0;
printf("Start\n");
digitalWrite(OUTpin, HIGH);
delay(200);
digitalWrite(OUTpin, LOW);
delay(100);
digitalWrite(OUTpin, HIGH);
delay(200);
digitalWrite(OUTpin, LOW);
delay(100);
printf("Stop\n");
int globalCounterCopy = globalCounter;

if (INT_EDGE_BOTH == Enge) {
expected = 4;
timeExpected = 500;
} else {
expected = 2;
timeExpected = 300;
}

if(globalCounter==expected) {
double fTime = (gEndTime - gStartTime) / 1000000.0;
printf("IRQ worked %g sec (~%gs expected)\n\n", fTime, timeExpected/1000.0);
return fTime;
} else {
printf("IRQ not worked got %d iterations (%d exprected)\n\n", globalCounterCopy, expected);
return 0;
}
}


double DurationTime(int Enge, int OUTpin, int IRQpin) {
struct timeval now;
double fTime = 0.0;

gStartTime = 0;
gEndTime = 0;
globalCounter = 0;
printf("Start\n");

if (INT_EDGE_RISING == Enge) {
digitalWrite(OUTpin, LOW);
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ;
sleep(1);
gettimeofday(&now, 0);
gStartTime = now.tv_sec*1000000LL + now.tv_usec;
digitalWrite(OUTpin, HIGH);
delay(20);
digitalWrite(OUTpin, LOW);
} else if (INT_EDGE_FALLING == Enge) {
digitalWrite(OUTpin, HIGH);
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ;
sleep(1);
gettimeofday(&now, 0);
gStartTime = now.tv_sec*1000000LL + now.tv_usec;
digitalWrite(OUTpin, LOW);
}

sleep(1);
fTime = (gEndTime - gStartTime);
printf("IRQ detect time %g usec\n\n", fTime);
wiringPiISRStop (IRQpin) ;

return fTime;
}

int main (void)
{
const int IRQpin = 22 ;
const int OUTpin = 25 ;
int major, minor;

wiringPiVersion(&major, &minor);

printf("\nISR test (WiringPi %d.%d)\n", major, minor);

wiringPiSetupGpio() ;

pinMode(IRQpin, INPUT);
pinMode(OUTpin, OUTPUT);
digitalWrite (OUTpin, LOW) ;


printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin);
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ;
sleep(1);
StartSequence (INT_EDGE_RISING, OUTpin);
printf("Testing close\n");
wiringPiISRStop (IRQpin) ;

printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin);
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ;
sleep(1);
StartSequence (INT_EDGE_FALLING, OUTpin);
printf("Testing close\n");
wiringPiISRStop (IRQpin) ;

printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin);
wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi) ;
sleep(1);
StartSequence (INT_EDGE_BOTH, OUTpin);
printf("Testing close\n");
wiringPiISRStop (IRQpin) ;

for (int count=0; count<2; count++) {
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin);
DurationTime(INT_EDGE_RISING, OUTpin, IRQpin);

printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin);
DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin);
}
pinMode(OUTpin, INPUT);

return 0 ;
}

+ 51
- 7
gpio/gpio.c Переглянути файл

@@ -43,6 +43,7 @@
#include "../version.h"

extern int wiringPiDebug ;
int gpioDebug ;

// External functions I can't be bothered creating a separate .h file for:

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

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

void printgpioflush(const char* text) {
if (gpioDebug) {
printf(text);
fflush(stdout);
}
}

void printgpio(const char* text) {
if (gpioDebug) {
printf(text);
fflush(stdout);
}
}

static void wfi (void) {
globalCounter++;
if(globalCounter>=iterations) {
printgpio("finished\n");
exit (0) ;
} else {
printgpioflush("I");
}
}

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 +607,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 +620,13 @@ void doWfi (int argc, char *argv [])
exit (1) ;
}

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


@@ -1360,6 +1399,11 @@ int main (int argc, char *argv [])
printf ("gpio: wiringPi debug mode enabled\n") ;
wiringPiDebug = TRUE ;
}
if (getenv ("GPIO_DEBUG") != NULL)
{
printf ("gpio: gpio debug mode enabled\n") ;
gpioDebug = TRUE ;
}

if (argc == 1)
{


+ 39
- 6
reinstall Переглянути файл

@@ -1,11 +1,44 @@
#!/bin/sh
vMaj=`cut -d. -f1 VERSION`
vMin=`cut -d. -f2 VERSION`
DEBVERSION=$vMaj.$vMin
sudo apt -y remove wiringpi
./build clean
./build debian
mv debian-template/wiringpi_${DEBVERSION}_armhf.deb .
sudo apt install ./wiringpi_${DEBVERSION}_armhf.deb
WPIVERSION=$vMaj.$vMin
ARCH=$(dpkg-architecture -qDEB_HOST_ARCH)

if [ -f /etc/os-release ]; then
# load vars from /etc/os-release
. /etc/os-release
if [ "$ID" = "raspbian" ] || [ "$ID" = "debian" ] || [ "$ID" = "linuxmint" ]; then
if [ "$ID" = "raspbian" ]; then
echo OS: Raspberry Pi OS
else
echo OS: Debian
fi
echo using all in one deb-package
echo ============================
echo

sudo apt -y remove wiringpi
./build clean
./build debian
mv debian-template/wiringpi_${WPIVERSION}_${ARCH}.deb .
sudo apt install ./wiringpi_${WPIVERSION}_${ARCH}.deb

elif [ "$ID" = "debian" ] || [ "$ID" = "linuxmint" ]; then
echo OS: Ubuntu/Mint
echo using 3 deb-package
echo ===================
echo

sudo apt -y remove libwiringpi2
sudo apt -y remove libwiringpi3
sudo apt -y remove wiringpi libwiringpi-dev
./build clean
./build ubuntu
#mv debian-template/wiringpi_${WPIVERSION}_armhf.deb .
#sudo apt install ./wiringpi_${WPIVERSION}_armhf.deb
fi

else
echo OS unknown, exit
exit
fi

+ 2
- 2
version.h Переглянути файл

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

+ 250
- 201
wiringPi/wiringPi.c Переглянути файл

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

#include "softPwm.h"
#include "softTone.h"
@@ -405,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
@@ -851,6 +854,36 @@ static void usingGpioMemCheck (const char *what)
}


void PrintSystemStdErr () {
struct utsname sys_info;
if (uname(&sys_info) == 0) {
fprintf (stderr, " wiringpi = %d.%d\n", VERSION_MAJOR, VERSION_MINOR);
fprintf (stderr, " system name = %s\n", sys_info.sysname);
//fprintf (stderr, " node name = %s\n", sys_info.nodename);
fprintf (stderr, " release = %s\n", sys_info.release);
fprintf (stderr, " version = %s\n", sys_info.version);
fprintf (stderr, " machine = %s\n", sys_info.machine);
if (strstr(sys_info.machine, "arm") == NULL && strstr(sys_info.machine, "aarch")==NULL) {
fprintf (stderr, " -> This is not an ARM architecture; it cannot be a Raspberry Pi.\n") ;
}
}
}


void piFunctionOops (const char *function, const char* suggestion, const char* url)
{
fprintf (stderr, "Oops: Function %s is not supported\n", function) ;
PrintSystemStdErr();
if (suggestion) {
fprintf (stderr, " -> Please %s\n", suggestion) ;
}
if (url) {
fprintf (stderr, " -> See info at %s\n", url) ;
}
fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ;
exit (EXIT_FAILURE) ;
}


/*
* piGpioLayout:
@@ -876,12 +909,15 @@ static void usingGpioMemCheck (const char *what)
*
*********************************************************************************
*/
const char* revfile = "/proc/device-tree/system/linux,revision";

void piGpioLayoutOops (const char *why)
{
fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ;
fprintf (stderr, "Oops: Unable to determine Raspberry Pi board revision from %s and from /proc/cpuinfo\n", revfile) ;
PrintSystemStdErr();
fprintf (stderr, " -> %s\n", why) ;
fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n") ;
fprintf (stderr, " -> WiringPi is designed for Raspberry Pi and can only be used with a Raspberry Pi.\n\n") ;
fprintf (stderr, " -> Check at https://github.com/wiringpi/wiringpi/issues.\n\n") ;
exit (EXIT_FAILURE) ;
}

@@ -905,10 +941,6 @@ int piBoardRev (void)
return piGpioLayout () ;
}


const char* revfile = "/proc/device-tree/system/linux,revision";


const char* GetPiRevision(char* line, int linelength, unsigned int* revision) {

const char* c = NULL;
@@ -1012,6 +1044,8 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
unsigned int revision = 0x00 ;
int bRev, bType, bProc, bMfg, bMem, bWarranty ;

//piGpioLayoutOops ("this is only a test case");

c = GetPiRevision(line, maxlength, &revision); // device tree
if (NULL==c) {
c = GetPiRevisionLegacy(line, maxlength, &revision); // proc/cpuinfo
@@ -1729,19 +1763,12 @@ void pullUpDnControl (int pin, int pud)

int digitalRead (int pin)
{
char c ;
struct wiringPiNodeStruct *node = wiringPiNodes ;

if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
{
if (sysFds [pin] == -1)
return LOW ;

lseek (sysFds [pin], 0L, SEEK_SET) ;
read (sysFds [pin], &c, 1) ;
return (c == '0') ? LOW : HIGH ;
}
if (wiringPiMode == WPI_MODE_GPIO_SYS)
return LOW ;
else if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
@@ -1804,17 +1831,8 @@ void digitalWrite (int pin, int value)

if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
{
if (sysFds [pin] != -1)
{
if (value == LOW)
write (sysFds [pin], "0\n", 2) ;
else
write (sysFds [pin], "1\n", 2) ;
}
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
return ;
}
else if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
@@ -1985,13 +2003,8 @@ void digitalWriteByte (const int value)

FailOnModel5();

/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 0 ; pin < 8 ; ++pin)
{
digitalWrite (pinToGpio [pin], value & mask) ;
mask <<= 1 ;
}
return ;
}
else
@@ -2019,13 +2032,9 @@ unsigned int digitalReadByte (void)

FailOnModel5();

/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 0 ; pin < 8 ; ++pin)
{
x = digitalRead (pinToGpio [pin]) ;
data = (data << 1) | x ;
}
return 0;
}
else
{
@@ -2052,19 +2061,10 @@ unsigned int digitalReadByte (void)

void digitalWriteByte2 (const int value)
{
register int mask = 1 ;
register int pin ;

FailOnModel5();

/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 20 ; pin < 28 ; ++pin)
{
digitalWrite (pin, value & mask) ;
mask <<= 1 ;
}
return ;
}
else
{
@@ -2075,18 +2075,12 @@ void digitalWriteByte2 (const int value)

unsigned int digitalReadByte2 (void)
{
int pin, x ;
uint32_t data = 0 ;

FailOnModel5();

/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 20 ; pin < 28 ; ++pin)
{
x = digitalRead (pin) ;
data = (data << 1) | x ;
}
}
else
data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins
@@ -2099,7 +2093,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.
*********************************************************************************
@@ -2107,11 +2101,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] ;
@@ -2119,28 +2114,147 @@ 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;
isrFunctions [pin] = NULL;

/* -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
@@ -2151,17 +2265,32 @@ 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") ;
}
if(isrFunctions [pin]) {
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 ;
}

@@ -2176,93 +2305,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 ;
}

@@ -2712,60 +2803,18 @@ int wiringPiSetupPhys (void)

/*
* wiringPiSetupSys:
* Must be called once at the start of your program execution.
*
* Initialisation (again), however this time we are using the /sys/class/gpio
* interface to the GPIO systems - slightly slower, but always usable as
* a non-root user, assuming the devices are already exported and setup correctly.
* GPIO Sysfs Interface for Userspace is deprecated
* https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html
* The last Raspberry Pi Kernel with Sysfs was 6.1.
* If needed, please use WiringPi 3.1.
*
*/

int wiringPiSetupSys (void)
{
char fName [128] ;

if (wiringPiSetuped)
return 0 ;

wiringPiSetuped = TRUE ;

if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ;

if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ;

if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupSys called\n") ;

int model, rev, mem, maker, overVolted ;
piBoardId (&model, &rev, &mem, &maker, &overVolted) ;

if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1)
{
pinToGpio = pinToGpioR1 ;
physToGpio = physToGpioR1 ;
}
else
{
pinToGpio = pinToGpioR2 ;
physToGpio = physToGpioR2 ;
}

// Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later

for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin)
{
int pinFS = GPIOToSysFS(pin);
if (pinFS>=0) {
sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ;
sysFds [pin] = open (fName, O_RDWR) ;
}
}

initialiseEpoch () ;

wiringPiMode = WPI_MODE_GPIO_SYS ;
piFunctionOops("wiringPiSetupSys",
"use wringpi 3.1 (last version with GPIO Sysfs interface)",
"https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html");

return 0 ;
}

+ 3
- 1
wiringPi/wiringPi.h Переглянути файл

@@ -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



+ 64
- 1
wiringPi/wiringPiLegacy.c Переглянути файл

@@ -185,4 +185,67 @@ int piGpioLayoutLegacy (void)
printf ("piGpioLayout: Returning revision: %d\n", gpioLayout) ;

return gpioLayout ;
}
}


/*
* wiringPiSetupSys:
* Must be called once at the start of your program execution.
*
* Initialisation (again), however this time we are using the /sys/class/gpio
* interface to the GPIO systems - slightly slower, but always usable as
* a non-root user, assuming the devices are already exported and setup correctly.
*/

/*
int wiringPiSetupSys (void)
{
char fName [128] ;

if (wiringPiSetuped)
return 0 ;

wiringPiSetuped = TRUE ;

if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ;

if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ;

if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupSys called\n") ;

int model, rev, mem, maker, overVolted ;
piBoardId (&model, &rev, &mem, &maker, &overVolted) ;

if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1)
{
pinToGpio = pinToGpioR1 ;
physToGpio = physToGpioR1 ;
}
else
{
pinToGpio = pinToGpioR2 ;
physToGpio = physToGpioR2 ;
}

// Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later

for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin)
{
int pinFS = GPIOToSysFS(pin);
if (pinFS>=0) {
sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ;
sysFds [pin] = open (fName, O_RDWR) ;
}
}

initialiseEpoch () ;

wiringPiMode = WPI_MODE_GPIO_SYS ;

return 0 ;
}
*/

Завантаження…
Відмінити
Зберегти