Browse Source

Added wiringPiISRmulti, which generates an interrupt if any GPIO in a list changes state based on mode.

pull/158/head
Jim Parziale 2 years ago
parent
commit
bfb3a8b4a0
5 changed files with 302 additions and 59 deletions
  1. +3
    -6
      devLib/Makefile
  2. +1
    -1
      examples/Makefile
  3. +57
    -4
      gpio/gpio.c
  4. +216
    -43
      wiringPi/wiringPi.c
  5. +25
    -5
      wiringPi/wiringPi.h

+ 3
- 6
devLib/Makefile View File

@@ -43,15 +43,12 @@ LIBS =


############################################################################### ###############################################################################


SRC = ds1302.c maxdetect.c \
piNes.c piFace.c \
lcd128x64.c lcd.c \
scrollPhat.c \
piGlow.c
SRC = ds1302.c maxdetect.c piNes.c \
lcd128x64.c lcd.c


OBJ = $(SRC:.c=.o) OBJ = $(SRC:.c=.o)


HEADERS = ds1302.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h scrollPhat.h
HEADERS = ds1302.h lcd128x64.h lcd.h maxdetect.h piNes.h


################################################################################# #################################################################################




+ 1
- 1
examples/Makefile View File

@@ -40,7 +40,7 @@ LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt


SRC = \ SRC = \
blink12.c blink12drcs.c blink6drcs.c blink8.c blink8-drcn.c blink.c blink-thread.c \ blink12.c blink12drcs.c blink6drcs.c blink8.c blink8-drcn.c blink.c blink-thread.c \
buttons2.c buttons.c \
buttons.c buttons2.c buttons3.c \
clock.c \ clock.c \
delayTest.c \ delayTest.c \
ds1302.c \ ds1302.c \


+ 57
- 4
gpio/gpio.c View File

@@ -72,6 +72,7 @@ char *usage = "Usage: gpio -v Show version info\n"
" gpio unexportall/exports\n" " gpio unexportall/exports\n"
" gpio export/edge/unexport ...\n" " gpio export/edge/unexport ...\n"
" gpio wfi <pin> <mode>\n" " gpio wfi <pin> <mode>\n"
" gpio mwfi <pin>[,<pin>...] <mode>\n"
" gpio drive <group> <value>\n" " gpio drive <group> <value>\n"
" gpio pwm-bal/pwm-ms \n" " gpio pwm-bal/pwm-ms \n"
" gpio pwmr <range> \n" " gpio pwmr <range> \n"
@@ -499,9 +500,12 @@ void doExport (int argc, char *argv[])
* to exit the program. Crude but effective. * to exit the program. Crude but effective.
********************************************************************************* *********************************************************************************
*/ */
static void wfi (UNUSED int pin)
static int nInts = 0;
static void wfi (int pin)
{ {
exit (EXIT_SUCCESS);
nInts++;
printf ("wfi: Interrupt on pin %d; nInts=%d\n", pin, nInts);
//exit (EXIT_SUCCESS);
} }


void doWfi (int argc, char *argv[]) void doWfi (int argc, char *argv[])
@@ -531,8 +535,56 @@ void doWfi (int argc, char *argv[])
exit (1); exit (1);
} }


for (;;)
delayMs(9999);
nInts = 0;
printf("%s: Wait for one interrupt...\n", __FUNCTION__);
while (nInts < 1)
{
delayMs(100);
}
}

void doMWfi (int argc, char *argv[])
{
int pinList[MAX_ONBOARD_PINS];
int n_pins = 0;
int mode;

if (argc != 4)
{
fprintf (stderr, "Usage: %s mwfi pin[,pin...] mode\n", argv[0]);
exit (1);
}

// Get list of pins from comma-separated list in argv[2]
char *pt;
pt = strtok (argv[2],",");
while (pt != NULL)
{
pinList[n_pins++] = atoi(pt);
pt = strtok (NULL, ",");
}

if (strcasecmp (argv[3], "rising") == 0) mode = INT_EDGE_RISING;
else if (strcasecmp (argv[3], "falling") == 0) mode = INT_EDGE_FALLING;
else if (strcasecmp (argv[3], "both") == 0) mode = INT_EDGE_BOTH;
else
{
fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv[1], argv[3]);
exit (1);
}

if (wiringPiISRmulti (pinList, n_pins, mode, &wfi) < 0)
{
fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv[1], strerror (errno));
exit (1);
}

nInts = 0;
printf("%s: Wait for %d interrupts...\n", __FUNCTION__, n_pins);
while (nInts < n_pins)
{
delayMs(100);
}
} }




@@ -1429,6 +1481,7 @@ int main (int argc, char *argv[])
else if (strcasecmp (argv[1], "rbd" ) == 0) doReadByte (argc, argv, FALSE); else if (strcasecmp (argv[1], "rbd" ) == 0) doReadByte (argc, argv, FALSE);
else if (strcasecmp (argv[1], "clock" ) == 0) doClock (argc, argv); else if (strcasecmp (argv[1], "clock" ) == 0) doClock (argc, argv);
else if (strcasecmp (argv[1], "wfi" ) == 0) doWfi (argc, argv); else if (strcasecmp (argv[1], "wfi" ) == 0) doWfi (argc, argv);
else if (strcasecmp (argv[1], "mwfi" ) == 0) doMWfi (argc, argv);
else else
{ {
fprintf (stderr, "[FATAL] %s: Unknown command: %s.\n", basename(argv[0]), argv[1]); fprintf (stderr, "[FATAL] %s: Unknown command: %s.\n", basename(argv[0]), argv[1]);


+ 216
- 43
wiringPi/wiringPi.c View File

@@ -293,7 +293,6 @@ static uint64_t epochMilli, epochMicro;


// Misc // Misc
static int wiringPiMode = WPI_MODE_UNINITIALISED; static int wiringPiMode = WPI_MODE_UNINITIALISED;
static volatile int pinPass = -1;
static pthread_mutex_t pinMutex; static pthread_mutex_t pinMutex;


// Debugging & Return codes // Debugging & Return codes
@@ -306,7 +305,7 @@ int wiringPiTryGpioMem = FALSE;


// sysFds: // sysFds:
// Map a file descriptor from the /sys/class/gpio/gpioX/value // Map a file descriptor from the /sys/class/gpio/gpioX/value
static int sysFds[64] =
static int sysFds[MAX_ONBOARD_PINS] =
{ {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -315,7 +314,7 @@ static int sysFds[64] =
}; };


// ISR Data // ISR Data
static void (*isrFunctions[64])(int pin);
static void (*isrFunctions[MAX_ONBOARD_PINS])(int pin);




// Doing it the Arduino way with lookup tables... // Doing it the Arduino way with lookup tables...
@@ -330,7 +329,7 @@ static int *pinToGpio;
// Index: WiringPi pin # // Index: WiringPi pin #
// Value @ index: BCM GPIO # // Value @ index: BCM GPIO #
// Revision 1, 1.1: // Revision 1, 1.1:
static int pinToGpioR1[64] =
static int pinToGpioR1[MAX_ONBOARD_PINS] =
{ {
// From the Original Wiki // From the Original Wiki
17, 18, 21, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7 17, 18, 21, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7
@@ -347,7 +346,7 @@ static int pinToGpioR1[64] =
// Index: WiringPi pin # // Index: WiringPi pin #
// Value @ index: BCM GPIO # // Value @ index: BCM GPIO #
// Revisions 2...: // Revisions 2...:
static int pinToGpioR2[64] =
static int pinToGpioR2[MAX_ONBOARD_PINS] =
{ {
// From the Original Wiki // From the Original Wiki
17, 18, 27, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7 17, 18, 27, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7
@@ -372,7 +371,7 @@ static int pinToGpioR2[64] =
static int *physToGpio; static int *physToGpio;
// Index: Physical pin # // Index: Physical pin #
// Value @ index: BCM GPIO # // Value @ index: BCM GPIO #
static int physToGpioR1[64] =
static int physToGpioR1[MAX_ONBOARD_PINS] =
{ {
-1, // 0 -1, // 0
-1, -1, // 1, 2 -1, -1, // 1, 2
@@ -396,7 +395,7 @@ static int physToGpioR1[64] =


// Index: Physical pin # // Index: Physical pin #
// Value @ index: BCM GPIO # // Value @ index: BCM GPIO #
static int physToGpioR2[64] =
static int physToGpioR2[MAX_ONBOARD_PINS] =
{ {
-1, // 0 -1, // 0
-1, -1, // 1, 2 -1, -1, // 1, 2
@@ -1272,9 +1271,11 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
int pin; int pin;
struct wiringPiNodeStruct *node; struct wiringPiNodeStruct *node;


// Minimum pin base is 64
if (pinBase < 64)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase);
// Minimum pin base is MAX_ONBOARD_PINS
if (pinBase < MAX_ONBOARD_PINS)
{
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is not < %d\n", pinBase, MAX_ONBOARD_PINS);
}


// Check all pins in-case there is overlap: // Check all pins in-case there is overlap:
for (pin = pinBase; pin < (pinBase + numPins); ++pin) for (pin = pinBase; pin < (pinBase + numPins); ++pin)
@@ -1322,7 +1323,7 @@ void pinModeAlt (int pin, int mode)


setupCheck ("pinModeAlt"); setupCheck ("pinModeAlt");


if ((pin & PI_GPIO_MASK) == 0) // On-board pin
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
{ {
if (wiringPiMode == WPI_MODE_PINS) if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin]; pin = pinToGpio[pin];
@@ -1352,7 +1353,7 @@ void pinMode (int pin, int mode)


setupCheck ("pinMode"); setupCheck ("pinMode");


if ((pin & PI_GPIO_MASK) == 0) // On-board pin
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
{ {
if (wiringPiMode == WPI_MODE_PINS) if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin]; pin = pinToGpio[pin];
@@ -1428,7 +1429,7 @@ void pullUpDnControl (int pin, int pud)


setupCheck ("pullUpDnControl"); setupCheck ("pullUpDnControl");


if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{ {
if (wiringPiMode == WPI_MODE_PINS) if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin]; pin = pinToGpio[pin];
@@ -1486,9 +1487,9 @@ int digitalRead (int pin)
{ {
char c; char c;
struct wiringPiNodeStruct *node = wiringPiNodes; struct wiringPiNodeStruct *node = wiringPiNodes;
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{ {
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
{ {
if (sysFds[pin] == -1) if (sysFds[pin] == -1)
return LOW; return LOW;
@@ -1542,9 +1543,9 @@ void digitalWrite (int pin, int value)
{ {
struct wiringPiNodeStruct *node = wiringPiNodes; struct wiringPiNodeStruct *node = wiringPiNodes;


if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{ {
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
{ {
if (sysFds[pin] != -1) if (sysFds[pin] != -1)
{ {
@@ -1586,7 +1587,7 @@ void pwmWrite (int pin, int value)


setupCheck ("pwmWrite"); setupCheck ("pwmWrite");


if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{ {
if (wiringPiMode == WPI_MODE_PINS) if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin]; pin = pinToGpio[pin];
@@ -1841,15 +1842,12 @@ int waitForInterrupt (int pin, int mS)
* fires. * fires.
********************************************************************************* *********************************************************************************
*/ */
static void *interruptHandler (UNUSED void *arg)
static void *interruptHandler (void *arg)
{ {
int myPin;
int myPin = (int)arg;


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


myPin = pinPass;
pinPass = -1;

for (;;) for (;;)
{ {
if (waitForInterrupt (myPin, -1) > 0) if (waitForInterrupt (myPin, -1) > 0)
@@ -1865,8 +1863,8 @@ static void *interruptHandler (UNUSED void *arg)
/* /*
* wiringPiISR: * wiringPiISR:
* Pi Specific. * Pi Specific.
* Take the details and create an interrupt handler that will do a call-
* back to the user supplied function.
* Take the details and create an interrupt handler that will do a callback
* to the user-supplied function.
* Returns 0 on success, -1 on failure (or program exits if !wiringPiReturnCodes) * Returns 0 on success, -1 on failure (or program exits if !wiringPiReturnCodes)
********************************************************************************* *********************************************************************************
*/ */
@@ -1877,21 +1875,31 @@ int wiringPiISR (int pin, int mode, void (*function)(int))
char fName[64]; char fName[64];
char pinS[8]; char pinS[8];
pid_t pid; pid_t pid;
int count, i;
int count;
char c; char c;
int bcmGpioPin; int bcmGpioPin;


if ((pin < 0) || (pin > 63)) if ((pin < 0) || (pin > 63))
{
return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin); return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", 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"); return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n");
}
else if (wiringPiMode == WPI_MODE_PINS) else if (wiringPiMode == WPI_MODE_PINS)
{
bcmGpioPin = pinToGpio[pin]; bcmGpioPin = pinToGpio[pin];
}
else if (wiringPiMode == WPI_MODE_PHYS) else if (wiringPiMode == WPI_MODE_PHYS)
{
bcmGpioPin = physToGpio[pin]; bcmGpioPin = physToGpio[pin];
}
else else
{
bcmGpioPin = pin; bcmGpioPin = pin;
}


// Now export the pin and set the right edge // Now export the pin and set the right edge
// We're going to use the gpio program to do this, so it assumes // We're going to use the gpio program to do this, so it assumes
@@ -1901,16 +1909,24 @@ int wiringPiISR (int pin, int mode, void (*function)(int))
if (mode != INT_EDGE_SETUP) if (mode != INT_EDGE_SETUP)
{ {
if (mode == INT_EDGE_FALLING) if (mode == INT_EDGE_FALLING)
{
modeS = "falling"; modeS = "falling";
}
else if (mode == INT_EDGE_RISING) else if (mode == INT_EDGE_RISING)
{
modeS = "rising"; modeS = "rising";
}
else else
{
modeS = "both"; modeS = "both";
}


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


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


if (pid == 0) // Child, execl (doesn't return if successful) if (pid == 0) // Child, execl (doesn't return if successful)
{ {
@@ -1928,7 +1944,9 @@ int wiringPiISR (int pin, int mode, void (*function)(int))
return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n"); return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n");
} }
else // Parent, wait for child's execl call to finish else // Parent, wait for child's execl call to finish
{
waitpid (pid, NULL, 0); waitpid (pid, NULL, 0);
}
} }
// Parent continues... // Parent continues...


@@ -1943,24 +1961,158 @@ int wiringPiISR (int pin, int mode, void (*function)(int))


// Clear any initial pending interrupt // Clear any initial pending interrupt
ioctl (sysFds[bcmGpioPin], FIONREAD, &count); ioctl (sysFds[bcmGpioPin], FIONREAD, &count);
for (i = 0; i < count; ++i)
for (int i = 0; i < count; ++i)
{
read (sysFds[bcmGpioPin], &c, 1); read (sysFds[bcmGpioPin], &c, 1);
}


// Save caller's callback function // Save caller's callback function
isrFunctions[pin] = function;
isrFunctions[bcmGpioPin] = function;


pthread_mutex_lock (&pinMutex); pthread_mutex_lock (&pinMutex);
pinPass = pin;
pthread_create (&threadId, NULL, interruptHandler, NULL);
while (pinPass != -1)
{
delayMs(1);
}
pthread_create (&threadId, NULL, interruptHandler, (void *)bcmGpioPin);
pthread_mutex_unlock (&pinMutex); pthread_mutex_unlock (&pinMutex);


return 0; return 0;
} }


/*
* wiringPiISRmulti:
* Pi Specific.
* Create an interrupt handler that will do a callback to the user-supplied function
* when any of the specified pins changes according to mode.
* Returns 0 on success, -1 on failure (or program exits if !wiringPiReturnCodes)
*********************************************************************************
*/
int wiringPiISRmulti (int pins[], int n_pins, int mode, void (*function)(int))
{
pthread_t threadId;
const char *modeS;
char fName[64];
char pinS[8];
pid_t pid;
int count;
char c;
int bcmGpioPins[MAX_ONBOARD_PINS];

if (n_pins < 1)
{
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: Must specify at least one pin.\n");
}

// Translate pin list to list of BCM GPIO pins
for (int i=0; i < n_pins; ++i)
{
int pin = pins[i];

if ((pin < 0) || (pin > 63))
{
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: pin must be 0-63 (%d)\n", pin);
}

if (wiringPiMode == WPI_MODE_UNINITIALISED)
{
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: wiringPi has not been initialised. Unable to continue.\n");
}
else if (wiringPiMode == WPI_MODE_PINS)
{
bcmGpioPins[i] = pinToGpio[pin];
}
else if (wiringPiMode == WPI_MODE_PHYS)
{
bcmGpioPins[i] = physToGpio[pin];
}
else
{
bcmGpioPins[i] = pin;
}
}

// Now export the pins and set the appropriate 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";
}

// Export each pin in the list
for (int i=0; i < n_pins; ++i)
{
sprintf (pinS, "%d", bcmGpioPins[i]);

if ((pid = fork ()) < 0) // Fail
{
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: fork failed: %s\n", strerror (errno));
}
if (pid == 0) // Child, execl (doesn't return if successful)
{
if (access ("/usr/local/bin/gpio", X_OK) == 0)
{
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL);
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: 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, "wiringPiISRmulti: execl failed: %s\n", strerror (errno));
}
else
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: Can't find gpio program\n");
}
else // Parent, wait for child's execl call to finish
{
waitpid (pid, NULL, 0);
}
} // end for(pin#)
} // end if (mode != INT_EDGE_SETUP)

// Parent continues...

for (int i=0; i < n_pins; ++i)
{
int bcmGpioPin = bcmGpioPins[i];

// Now pre-open the /sys/class node - but it may already be open if
// we are in Sys mode...
if (sysFds[bcmGpioPin] == -1)
{
sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin);
if ((sysFds[bcmGpioPin] = open (fName, O_RDWR)) < 0)
return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: unable to open %s: %s\n", fName, strerror (errno));
}

// Clear any initial pending interrupt
ioctl (sysFds[bcmGpioPin], FIONREAD, &count);
for (int i = 0; i < count; ++i)
{
read (sysFds[bcmGpioPin], &c, 1);
}

// Save caller's callback function
isrFunctions[bcmGpioPin] = function;

// Create a separate
pthread_mutex_lock (&pinMutex);
pthread_create (&threadId, NULL, interruptHandler, (void *)bcmGpioPin);
pthread_mutex_unlock (&pinMutex);
} // end for(pin#)

return 0;
}


/* /*
* initialiseEpoch: * initialiseEpoch:
@@ -2127,6 +2279,8 @@ int wiringPiSetup (void)


wiringPiSetuped = TRUE; wiringPiSetuped = TRUE;


// ------------------------------------------------------

if (getenv (ENV_DEBUG) != NULL) if (getenv (ENV_DEBUG) != NULL)
{ {
wiringPiDebug = TRUE; wiringPiDebug = TRUE;
@@ -2142,6 +2296,7 @@ int wiringPiSetup (void)
printf ("wiringPi: wiringPiSetup called\n"); printf ("wiringPi: wiringPiSetup called\n");
} }


// ------------------------------------------------------
// Get the board ID information. We're not really using the information here, // Get the board ID information. We're not really using the information here,
// but it will give us information like the GPIO layout scheme (2 variants // but it will give us information like the GPIO layout scheme (2 variants
// on the older 26-pin Pi's) and the GPIO peripheral base address. // on the older 26-pin Pi's) and the GPIO peripheral base address.
@@ -2153,9 +2308,15 @@ int wiringPiSetup (void)
if ((model == PI_MODEL_CM1) || if ((model == PI_MODEL_CM1) ||
(model == PI_MODEL_CM3) || (model == PI_MODEL_CM3) ||
(model == PI_MODEL_CM3P)) (model == PI_MODEL_CM3P))
wiringPiMode = WPI_MODE_GPIO; // Virtual pin numbers 0 through 16
{
// Compute modules don't use WiringPi pin mode (virtual pins)
wiringPiMode = WPI_MODE_GPIO; // Broadcom GPIO pin numbers
}
else else
wiringPiMode = WPI_MODE_PINS; // Broadcom GPIO pin numbers
{
// WiringPi pin mode
wiringPiMode = WPI_MODE_PINS; // Virtual pin numbers 0 through 16
}


if (piGpioLayout() == 1) // A, B, Rev 1, 1.1 (Oldest boards) if (piGpioLayout() == 1) // A, B, Rev 1, 1.1 (Oldest boards)
{ {
@@ -2168,14 +2329,19 @@ int wiringPiSetup (void)
physToGpio = physToGpioR2; physToGpio = physToGpioR2;
} }


// ...

// BCM2835: Raspberry Pi 1 Models A, A+, B, B+, the Raspberry Pi Zero, the Raspberry Pi Zero W, and the Raspberry Pi Compute Module 1
// BCM2836: Raspberry Pi 2 Model B (essentially identical to BCM2835)
// BCM2837: Raspberry Pi 3 Model B, later models of the Raspberry Pi 2 Model B, and the Raspberry Pi Compute Module 3
// (essentially identical to BCM2836)
// BCM2837B0: Raspberry Pi 3 Models A+, B+, and the Raspberry Pi Compute Module 3+ (essentially identical to BCM2837)
// RP3A0 (BCM2710A1): Raspberry Pi Zero 2 W
// BCM2710A1 = silicon die packaged inside the Broadcom BCM2837 chip which is used on the Raspberry Pi 3
switch (model) switch (model)
{ {
case PI_MODEL_A: case PI_MODEL_B:
case PI_MODEL_AP: case PI_MODEL_BP:
case PI_ALPHA: case PI_MODEL_CM1:
case PI_MODEL_A: case PI_MODEL_AP:
case PI_MODEL_B: case PI_MODEL_BP:
case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: case PI_MODEL_ZERO: case PI_MODEL_ZERO_W:
case PI_MODEL_CM1: case PI_ALPHA:
piGpioBase = GPIO_PERI_BASE_OLD; piGpioBase = GPIO_PERI_BASE_OLD;
piGpioPupOffset = GPPUD; piGpioPupOffset = GPPUD;
break; break;
@@ -2183,16 +2349,19 @@ int wiringPiSetup (void)
case PI_MODEL_4B: case PI_MODEL_4B:
case PI_MODEL_400: case PI_MODEL_400:
case PI_MODEL_CM4: case PI_MODEL_CM4:
// BCM2711: Raspberry Pi 4 Model B, the Raspberry Pi 400, and the Raspberry Pi Compute Module 4
piGpioBase = GPIO_PERI_BASE_2711; piGpioBase = GPIO_PERI_BASE_2711;
piGpioPupOffset = GPPUPPDN0; piGpioPupOffset = GPPUPPDN0;
break; break;


default: default:
// PI_MODEL_2B PI_MODEL_3AP PI_MODEL_3B PI_MODEL_3BP PI_MODEL_CM3P PI_MODEL_CM3
piGpioBase = GPIO_PERI_BASE_2835; piGpioBase = GPIO_PERI_BASE_2835;
piGpioPupOffset = GPPUD; piGpioPupOffset = GPPUD;
break; break;
} }


// ------------------------------------------------------
// Open the master /dev/ memory control device // Open the master /dev/ memory control device
// Device strategy: December 2016: // Device strategy: December 2016:
// Try /dev/mem. If that fails, then // Try /dev/mem. If that fails, then
@@ -2246,6 +2415,7 @@ int wiringPiSetup (void)
if (timer == MAP_FAILED) if (timer == MAP_FAILED)
return wiringPiFailure (WPI_NON_FATAL, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)); return wiringPiFailure (WPI_NON_FATAL, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno));


// ------------------------------------------------------
// Set the timer to free-running, 1MHz. // Set the timer to free-running, 1MHz.
// 0xF9 is 249, the timer divide is base clock / (divide+1) // 0xF9 is 249, the timer divide is base clock / (divide+1)
// so base clock is 250MHz / 250 = 1MHz. // so base clock is 250MHz / 250 = 1MHz.
@@ -2253,6 +2423,7 @@ int wiringPiSetup (void)
*(timer + TIMER_PRE_DIV) = 0x00000F9; *(timer + TIMER_PRE_DIV) = 0x00000F9;
timerIrqRaw = timer + TIMER_IRQ_RAW; timerIrqRaw = timer + TIMER_IRQ_RAW;


// ------------------------------------------------------
// Export the base addresses for any external software that might need them // Export the base addresses for any external software that might need them
_wiringPiGpio = gpio; _wiringPiGpio = gpio;
_wiringPiPwm = pwm; _wiringPiPwm = pwm;
@@ -2260,6 +2431,8 @@ int wiringPiSetup (void)
_wiringPiPads = pads; _wiringPiPads = pads;
_wiringPiTimer = timer; _wiringPiTimer = timer;


// ------------------------------------------------------

initialiseEpoch (); initialiseEpoch ();


return 0; return 0;
@@ -2349,7 +2522,7 @@ int wiringPiSetupSys (void)


// Open and scan the directory, looking for exported GPIOs, and pre-open // Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later // the 'value' interface to speed things up for later
for (pin = 0; pin < 64; ++pin)
for (pin = 0; pin < MAX_ONBOARD_PINS; ++pin)
{ {
sprintf (fName, "/sys/class/gpio/gpio%d/value", pin); sprintf (fName, "/sys/class/gpio/gpio%d/value", pin);
sysFds[pin] = open (fName, O_RDWR); sysFds[pin] = open (fName, O_RDWR);


+ 25
- 5
wiringPi/wiringPi.h View File

@@ -37,9 +37,10 @@
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))


// Mask for the bottom 64 pins which belong to the Raspberry Pi // Mask for the bottom 64 pins which belong to the Raspberry Pi
// The others are available for the other devices
// The others are available for the other devices
// @TODO Replace these checks with a check for (pin < 64) // @TODO Replace these checks with a check for (pin < 64)
#define PI_GPIO_MASK (0xFFFFFFC0) #define PI_GPIO_MASK (0xFFFFFFC0)
#define MAX_ONBOARD_PINS 64




// wiringPi modes // wiringPi modes
@@ -194,6 +195,7 @@ extern volatile unsigned int *_wiringPiPads;
extern volatile unsigned int *_wiringPiTimer; extern volatile unsigned int *_wiringPiTimer;
extern volatile unsigned int *_wiringPiTimerIrqRaw; extern volatile unsigned int *_wiringPiTimerIrqRaw;


// ----------------------------------------------------------------------------


// Function prototypes // Function prototypes
// c++ wrappers thanks to a comment by Nick Lott // c++ wrappers thanks to a comment by Nick Lott
@@ -202,11 +204,13 @@ extern volatile unsigned int *_wiringPiTimerIrqRaw;
extern "C" { extern "C" {
#endif #endif


// Data
// ----------------------------------------------------------------------------


// Internal // Internal
extern int wiringPiFailure (int fatal, const char *message, ...); extern int wiringPiFailure (int fatal, const char *message, ...);


// ----------------------------------------------------------------------------

// Core wiringPi functions // Core wiringPi functions
extern struct wiringPiNodeStruct *wiringPiFindNode (int pin); extern struct wiringPiNodeStruct *wiringPiFindNode (int pin);
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins); extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins);
@@ -233,7 +237,7 @@ extern int digitalRead (int pin);
extern void digitalWrite (int pin, int value); extern void digitalWrite (int pin, int value);


// Analog read/write is only for an external hardware module, // Analog read/write is only for an external hardware module,
// therefore pin must be >= 64
// therefore pin must be >= MAX_ONBOARD_PINS
extern int analogRead (int pin); extern int analogRead (int pin);
extern void analogWrite (int pin, int value); extern void analogWrite (int pin, int value);


@@ -268,10 +272,24 @@ extern unsigned int digitalReadByte2(void);
extern void digitalWriteByte (int value); extern void digitalWriteByte (int value);
extern void digitalWriteByte2 (int value); extern void digitalWriteByte2 (int value);


// ----------------------------------------------------------------------------
// Interrupts (Also Pi hardware specific) // Interrupts (Also Pi hardware specific)
extern int waitForInterrupt (int pin, int mS); // Must be in SYS mode (wiringPiSetupSys was called for setup)
extern int wiringPiISR (int pin, int mode, void (*function)(int)); // Uses SYS mode, and also waitForInterrupt


// Set up for a callback to be called when the specified pin changes according to mode.
// mode = INT_EDGE_SETUP, INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH
// Uses SYS mode, and also waitForInterrupt
extern int wiringPiISR (int pin, int mode, void (*function)(int));

// Same as wiringPiISR above, but takes a list of pins to wait for.
// Note that the mode applies to all the specified pins.
extern int wiringPiISRmulti (int pins[], int n_pins, int mode, void (*function)(int));

// Internal-only (unless you know how to set up /sys/class/gpio)
// Wait for "interrupt" on a GPIO pin.
// Must be in SYS mode (wiringPiSetupSys was called for setup)
extern int waitForInterrupt (int pin, int mS);

// ----------------------------------------------------------------------------
// Threads // Threads
extern int piThreadCreate (void *(*fn)(void *)); extern int piThreadCreate (void *(*fn)(void *));
extern void piLock (int key); extern void piLock (int key);
@@ -280,6 +298,8 @@ extern void piUnlock (int key);
// Scheduling priority // Scheduling priority
extern int piHiPri (const int pri); extern int piHiPri (const int pri);


// ----------------------------------------------------------------------------

extern void delay (unsigned int milliseconds); extern void delay (unsigned int milliseconds);
extern void delayMicroseconds (unsigned int microseconds); extern void delayMicroseconds (unsigned int microseconds);
// Please use these for code that's easier to comprehend: // Please use these for code that's easier to comprehend:


Loading…
Cancel
Save