#include <string.h>
#include <time.h>
#include <fcntl.h>
+#include <pthread.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include "wiringPi.h"
void (*pinMode) (int pin, int mode) ;
void (*pullUpDnControl) (int pin, int pud) ;
void (*digitalWrite) (int pin, int value) ;
+void (*digitalWriteByte) (int value) ;
void (*pwmWrite) (int pin, int value) ;
void (*setPadDrive) (int group, int value) ;
int (*digitalRead) (int pin) ;
static volatile uint32_t *clk ;
static volatile uint32_t *pads ;
static volatile uint32_t *timer ;
-
static volatile uint32_t *timerIrqRaw ;
-// Raspberry Pi board revision
+// Time for easy calculations
+
+static unsigned long long epoch ;
+
+// Misc
-static int boardRevision = -1 ;
+static int wiringPiMode = WPI_MODE_UNINITIALISED ;
// Debugging
-static int wiringPiDebug = FALSE ;
+int wiringPiDebug = FALSE ;
// The BCM2835 has 54 GPIO pins.
// BCM2835 data sheet, Page 90 onwards.
static int sysFds [64] ;
+// ISR Data
+
+static void (*isrFunctions [64])(void) ;
+
+
// Doing it the Arduino way with lookup tables...
// Yes, it's probably more innefficient than all the bit-twidling, but it
// does tend to make it all a bit clearer. At least to me!
static int pinToGpioR2 [64] =
{
- 17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7
- 2, 3, // I2C - SDA0, SCL0
- 8, 7, // SPI - CE1, CE0
- 10, 9, 11, // SPI - MOSI, MISO, SCLK
- 14, 15, // UART - Tx, Rx
- 28, 29, 30, 31, // New GPIOs 8 though 11
+ 17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
+ 2, 3, // I2C - SDA0, SCL0 wpi 8 - 9
+ 8, 7, // SPI - CE1, CE0 wpi 10 - 11
+ 10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14
+ 14, 15, // UART - Tx, Rx wpi 15 - 16
+ 28, 29, 30, 31, // New GPIOs 8 though 11 wpi 17 - 20
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
} ;
+
// gpioToGPFSEL:
// Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5)
5,5,5,5,5,5,5,5,5,5,
} ;
+
// gpioToShift
// Define the shift up for the 3 bits per pin in each GPFSEL port
0,3,6,9,12,15,18,21,24,27,
} ;
+
// gpioToGPSET:
// (Word) offset to the GPIO Set registers for each GPIO pin
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
} ;
+
// gpioToGPCLR:
// (Word) offset to the GPIO Clear registers for each GPIO pin
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
} ;
+
// gpioToGPLEV:
// (Word) offset to the GPIO Input level registers for each GPIO pin
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
} ;
+
#ifdef notYetReady
// gpioToEDS
// (Word) offset to the Event Detect Status
} ;
#endif
+
// gpioToPUDCLK
// (Word) offset to the Pull Up Down Clock regsiter
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
} ;
+
// gpioToPwmALT
// the ALT value to put a GPIO pin into PWM mode
} ;
-// Time for easy calculations
+/*
+ * Functions
+ *********************************************************************************
+ */
-static unsigned long long epoch ;
-//////////////////////////////////////////////////////////////////////////////////
+/*
+ * wpiPinToGpio:
+ * Translate a wiringPi Pin number to native GPIO pin number.
+ * (We don't use this here, prefering to just do the lookup directly,
+ * but it's been requested!)
+ *********************************************************************************
+ */
+
+int wpiPinToGpio (int wpiPin)
+{
+ return pinToGpio [wpiPin & 63] ;
+}
+
+
+/*
+ * piBoardRev:
+ * Return a number representing the hardware revision of the board.
+ * Revision is currently 1 or 2. -1 is returned on error.
+ *
+ * Much confusion here )-:
+ * Seems there are some boards with 0000 in them (mistake in manufacture)
+ * and some board with 0005 in them (another mistake in manufacture?)
+ * So the distinction between boards that I can see is:
+ * 0000 - Error
+ * 0001 - Not used
+ * 0002 - Rev 1
+ * 0003 - Rev 1
+ * 0004 - Rev 2
+ * 0005 - Rev 2 (but error)
+ * 0006 - Rev 2
+ * 000f - Rev 2 + 512MB
+ *
+ * A small thorn is the olde style overvolting - that will add in
+ * 1000000
+ *
+ *********************************************************************************
+ */
+
+static void piBoardRevOops (char *why)
+{
+ fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
+ fprintf (stderr, " -> %s\n", why) ;
+ fprintf (stderr, " -> You may want to check:\n") ;
+ fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
+ exit (EXIT_FAILURE) ;
+}
+
+int piBoardRev (void)
+{
+ FILE *cpuFd ;
+ char line [120] ;
+ char *c, lastChar ;
+ static int boardRev = -1 ;
+
+// No point checking twice...
+
+ if (boardRev != -1)
+ return boardRev ;
+
+ if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
+ return -1 ;
+
+ while (fgets (line, 120, cpuFd) != NULL)
+ if (strncmp (line, "Revision", 8) == 0)
+ break ;
+
+ fclose (cpuFd) ;
+
+ if (line == NULL)
+ piBoardRevOops ("No \"Revision\" line") ;
+
+ line [strlen (line) - 1] = 0 ; // Chomp LF
+
+ if (wiringPiDebug)
+ printf ("piboardRev: Revision string: %s\n", line) ;
+
+ for (c = line ; *c ; ++c)
+ if (isdigit (*c))
+ break ;
+
+ if (!isdigit (*c))
+ piBoardRevOops ("No numeric revision string") ;
+
+// If you have overvolted the Pi, then it appears that the revision
+// has 100000 added to it!
+
+ if (wiringPiDebug)
+ if (strlen (c) != 4)
+ printf ("piboardRev: This Pi has/is overvolted!\n") ;
+
+ lastChar = line [strlen (line) - 1] ;
+
+ if (wiringPiDebug)
+ printf ("piboardRev: lastChar is: '%c' (%d, 0x%02X)\n", lastChar, lastChar, lastChar) ;
+
+ /**/ if ((lastChar == '2') || (lastChar == '3'))
+ boardRev = 1 ;
+ else
+ boardRev = 2 ;
+
+ if (wiringPiDebug)
+ printf ("piBoardRev: Returning revision: %d\n", boardRev) ;
+
+ return boardRev ;
+}
+
/*
void pinModeGpio (int pin, int mode)
{
+// register int barrier ;
+
int fSel, shift, alt ;
pin &= 63 ;
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
+ delayMicroseconds (110) ; // See comments in pwmSetClockWPi
+ *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
+
// Page 107 of the BCM Peripherals manual talks about the GPIO clocks,
// but I'm assuming (hoping!) that this applies to other clocks too.
*(pwm + PWM_CONTROL) = 0 ; // Stop PWM
+
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock
- delayMicroseconds (110) ; // See comments in pwmSetClockWPi
+ delayMicroseconds (110) ; // See comments in pwmSetClockWPi
- (void)*(pwm + PWM_CONTROL) ;
- while ((*(pwm + PWM_CONTROL) & 0x80) != 0) // Wait for clock to be !BUSY
+ while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY
delayMicroseconds (1) ;
*(clk + PWMCLK_DIV) = BCM_PASSWORD | (32 << 12) ; // set pwm div to 32 (19.2/32 = 600KHz)
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // enable clk
-// Default range regsiter of 1024
+ delayMicroseconds (110) ; // See comments in pwmSetClockWPi
+
+// Default range register of 1024
- *(pwm + PWM0_DATA) = 0 ; *(pwm + PWM0_RANGE) = 1024 ;
- *(pwm + PWM1_DATA) = 0 ; *(pwm + PWM1_RANGE) = 1024 ;
+ *(pwm + PWM0_RANGE) = 1024 ; delayMicroseconds (10) ;
+ *(pwm + PWM1_RANGE) = 1024 ; delayMicroseconds (10) ;
+ *(pwm + PWM0_DATA) = 0 ; delayMicroseconds (10) ;
+ *(pwm + PWM1_DATA) = 0 ; delayMicroseconds (10) ;
// Enable PWMs in balanced mode (default)
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;
+
+ delay (100) ;
}
+
// When we change mode of any pin, we remove the pull up/downs
// Or we used to... Hm. Commented out now because for some wieird reason,
// it seems to block subsequent attempts to set the pull up/downs and I've
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock
delayMicroseconds (110) ; // prevents clock going sloooow
- while ((*(pwm + PWM_CONTROL) & 0x80) != 0) // Wait for clock to be !BUSY
+ while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY
delayMicroseconds (1) ;
*(clk + PWMCLK_DIV) = BCM_PASSWORD | (divisor << 12) ;
}
-
-
#ifdef notYetReady
/*
* pinED01:
/*
- * pwnWrite:
+ * digitalWriteByte:
+ * Write an 8-bit byte to the first 8 GPIO pins - try to do it as
+ * fast as possible.
+ * However it still needs 2 operations to set the bits, so any external
+ * hardware must not rely on seeing a change as there will be a change
+ * to set the outputs bits to zero, then another change to set the 1's
+ *********************************************************************************
+ */
+
+void digitalWriteByteGpio (int value)
+{
+ uint32_t pinSet = 0 ;
+ uint32_t pinClr = 0 ;
+ int mask = 1 ;
+ int pin ;
+
+ for (pin = 0 ; pin < 8 ; ++pin)
+ {
+ if ((value & mask) == 0)
+ pinClr |= (1 << pinToGpio [pin]) ;
+ else
+ pinSet |= (1 << pinToGpio [pin]) ;
+
+ mask <<= 1 ;
+ }
+
+ *(gpio + gpioToGPCLR [0]) = pinClr ;
+ *(gpio + gpioToGPSET [0]) = pinSet ;
+}
+
+void digitalWriteByteSys (int value)
+{
+ int mask = 1 ;
+ int pin ;
+
+ for (pin = 0 ; pin < 8 ; ++pin)
+ {
+ digitalWriteSys (pinToGpio [pin], value & mask) ;
+ mask <<= 1 ;
+ }
+}
+
+
+/*
+ * pwmWrite:
* Set an output PWM value
*********************************************************************************
*/
}
+/*
+ * interruptHandler:
+ * This is a thread and gets started to wait for the interrupt we're
+ * hoping to catch. It will call the user-function when the interrupt
+ * fires.
+ *********************************************************************************
+ */
+
+static void *interruptHandler (void *arg)
+{
+ int myPin = *(int *)arg ;
+
+ (void)piHiPri (55) ; // Only effective if we run as root
+
+ for (;;)
+ if (waitForInterruptSys (myPin, -1) > 0)
+ isrFunctions [myPin] () ;
+
+ return NULL ;
+}
+
+
+/*
+ * wiringPiISR:
+ * Take the details and create an interrupt handler that will do a call-
+ * back to the user supplied function.
+ *********************************************************************************
+ */
+
+int wiringPiISR (int pin, int mode, void (*function)(void))
+{
+ pthread_t threadId ;
+ char fName [64] ;
+ char *modeS ;
+ char pinS [8] ;
+ pid_t pid ;
+
+ pin &= 63 ;
+
+ if (wiringPiMode == WPI_MODE_UNINITIALISED)
+ {
+ fprintf (stderr, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
+ exit (EXIT_FAILURE) ;
+ }
+ else if (wiringPiMode == WPI_MODE_PINS)
+ pin = pinToGpio [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", pin) ;
+
+ if ((pid = fork ()) < 0) // Fail
+ return pid ;
+
+ if (pid == 0) // Child, exec
+ {
+ execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
+ return -1 ; // Failure ...
+ }
+ else // Parent, wait
+ wait (NULL) ;
+ }
+
+// Now pre-open the /sys/class node - it may already be open if
+// we had set it up earlier, but this will do no harm.
+
+ sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
+ if ((sysFds [pin] = open (fName, O_RDWR)) < 0)
+ return -1 ;
+
+ isrFunctions [pin] = function ;
+
+ pthread_create (&threadId, NULL, interruptHandler, &pin) ;
+
+ delay (1) ;
+
+ return 0 ;
+}
/*
* somewhat sub-optimal in that it uses 100% CPU, something not an issue
* in a microcontroller, but under a multi-tasking, multi-user OS, it's
* wastefull, however we've no real choice )-:
+ *
+ * Plan B: It seems all might not be well with that plan, so changing it
+ * to use gettimeofday () and poll on that instead...
*********************************************************************************
*/
void delayMicrosecondsHard (unsigned int howLong)
{
+#ifdef HARD_TIMER
+ volatile unsigned int dummy ;
+
*(timer + TIMER_LOAD) = howLong ;
*(timer + TIMER_IRQ_CLR) = 0 ;
- while (*timerIrqRaw == 0)
- ;
+ dummy = *timerIrqRaw ;
+ while (dummy == 0)
+ dummy = *timerIrqRaw ;
+#else
+ struct timeval tNow, tLong, tEnd ;
+
+ gettimeofday (&tNow, NULL) ;
+ tLong.tv_sec = howLong / 1000000 ;
+ tLong.tv_usec = howLong % 1000000 ;
+ timeradd (&tNow, &tLong, &tEnd) ;
+
+ while (timercmp (&tNow, &tEnd, <))
+ gettimeofday (&tNow, NULL) ;
+#endif
}
void delayMicrosecondsWPi (unsigned int howLong)
{
- struct timespec sleeper, dummy ;
+ struct timespec sleeper ;
/**/ if (howLong == 0)
return ;
{
sleeper.tv_sec = 0 ;
sleeper.tv_nsec = (long)(howLong * 1000) ;
- nanosleep (&sleeper, &dummy) ;
+ nanosleep (&sleeper, NULL) ;
}
}
int wiringPiSetup (void)
{
int fd ;
- FILE *cpuFd ;
- char line [80] ;
- char *c ;
- int revision = -1 ;
- uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ;
+ int boardRev ;
+ //uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ;
struct timeval tv ;
+ if (geteuid () != 0)
+ {
+ fprintf (stderr, "wiringPi:\n Must be root to call wiringPiSetup().\n (Did you forget sudo?)\n") ;
+ exit (EXIT_FAILURE) ;
+ }
+
if (getenv ("WIRINGPI_DEBUG") != NULL)
+ {
+ printf ("wiringPi: Debug mode enabled\n") ;
wiringPiDebug = TRUE ;
+ }
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetup called\n") ;
pinMode = pinModeWPi ;
pullUpDnControl = pullUpDnControlWPi ;
digitalWrite = digitalWriteWPi ;
+ digitalWriteByte = digitalWriteByteGpio ; // Same code
pwmWrite = pwmWriteWPi ;
setPadDrive = setPadDriveWPi ;
digitalRead = digitalReadWPi ;
pwmSetRange = pwmSetRangeWPi ;
pwmSetClock = pwmSetClockWPi ;
-// Find board revision
-
- if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
- {
- fprintf (stderr, "wiringPiSetup: Unable to open /proc/cpuinfo: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
- while (fgets (line, 80, cpuFd) != NULL)
- if (strncmp (line, "Revision", 8) == 0)
- for (c = line ; *c ; ++c)
- {
- if (!isdigit (*c))
- continue ;
- revision = atoi (c) ;
- break ;
- }
-
- fclose (cpuFd) ;
- if (revision == -1)
- {
- fprintf (stderr, "wiringPiSetup: Unable to determine board revision\n") ;
- errno = 0 ;
- return -1 ;
- }
-
-// If you have overvolted the Pi, then it appears that the revision
-// has 100000 added to it!
-
- if (wiringPiDebug)
- if (revision > 1000)
- printf ("wiringPi: This Pi has/is overvolted!\n") ;
-
- revision %= 100 ;
+ boardRev = piBoardRev () ;
- /**/ if ((revision == 2) || (revision == 3))
- boardRevision = 1 ;
- else if ((revision == 4) || (revision == 5) || (revision == 6))
- boardRevision = 2 ;
- else
- {
- fprintf (stderr, "wiringPiSetup: Unable to determine board revision: %d\n", revision) ;
- errno = 0 ;
- return -1 ;
- }
-
-
- if (boardRevision == 1)
+ if (boardRev == 1)
pinToGpio = pinToGpioR1 ;
else
pinToGpio = pinToGpioR2 ;
- if (wiringPiDebug)
- printf ("wiringPi: Revision: %d, board revision: %d\n", revision, boardRevision) ;
-
// Open the master /dev/memory device
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
{
- fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
// GPIO:
-// Allocate 2 pages - 1 ...
-
- if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
+ gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;
+ if ((int32_t)gpio == -1)
{
- fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
-// ... presumably to make sure we can round it up to a whole page size
-
- if (((uint32_t)gpioMem % PAGE_SIZE) != 0)
- gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ;
-
- gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ;
-
- if ((int32_t)gpio < 0)
- {
- fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
// PWM
- if ((pwmMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
- {
- fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
- if (((uint32_t)pwmMem % PAGE_SIZE) != 0)
- pwmMem += PAGE_SIZE - ((uint32_t)pwmMem % PAGE_SIZE) ;
-
- pwm = (uint32_t *)mmap(pwmMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PWM) ;
-
- if ((int32_t)pwm < 0)
+ pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ;
+ if ((int32_t)pwm == -1)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
// Clock control (needed for PWM)
- if ((clkMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
+ clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, CLOCK_BASE) ;
+ if ((int32_t)clk == -1)
{
- fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
- if (((uint32_t)clkMem % PAGE_SIZE) != 0)
- clkMem += PAGE_SIZE - ((uint32_t)clkMem % PAGE_SIZE) ;
-
- clk = (uint32_t *)mmap(clkMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, CLOCK_BASE) ;
-
- if ((int32_t)clk < 0)
- {
- fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
// The drive pads
- if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
+ pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ;
+ if ((int32_t)pads == -1)
{
- fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
- if (((uint32_t)padsMem % PAGE_SIZE) != 0)
- padsMem += PAGE_SIZE - ((uint32_t)padsMem % PAGE_SIZE) ;
-
- pads = (uint32_t *)mmap(padsMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PADS) ;
-
- if ((int32_t)pads < 0)
- {
- fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
// The system timer
- if ((timerMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
- {
- fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ;
- return -1 ;
- }
-
- if (((uint32_t)timerMem % PAGE_SIZE) != 0)
- timerMem += PAGE_SIZE - ((uint32_t)timerMem % PAGE_SIZE) ;
-
- timer = (uint32_t *)mmap(timerMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_TIMER) ;
-
- if ((int32_t)timer < 0)
+ timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ;
+ if ((int32_t)timer == -1)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ {
+ int serr = errno ;
+ fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
+ errno = serr ;
+ }
return -1 ;
}
gettimeofday (&tv, NULL) ;
epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
+ wiringPiMode = WPI_MODE_PINS ;
+
return 0 ;
}
{
int x ;
- if (wiringPiDebug)
- printf ("wiringPi: wiringPiSetupGpio called\n") ;
+ if (geteuid () != 0)
+ {
+ fprintf (stderr, "Must be root to call wiringPiSetupGpio(). (Did you forget sudo?)\n") ;
+ exit (EXIT_FAILURE) ;
+ }
if ((x = wiringPiSetup ()) < 0)
return x ;
+ if (wiringPiDebug)
+ printf ("wiringPi: wiringPiSetupGpio called\n") ;
+
pinMode = pinModeGpio ;
pullUpDnControl = pullUpDnControlGpio ;
digitalWrite = digitalWriteGpio ;
+ digitalWriteByte = digitalWriteByteGpio ;
pwmWrite = pwmWriteGpio ;
setPadDrive = setPadDriveGpio ;
digitalRead = digitalReadGpio ;
pwmSetRange = pwmSetRangeWPi ;
pwmSetClock = pwmSetClockWPi ;
+ wiringPiMode = WPI_MODE_GPIO ;
+
return 0 ;
}
int wiringPiSetupSys (void)
{
+ int boardRev ;
int pin ;
struct timeval tv ;
char fName [128] ;
+ if (getenv ("WIRINGPI_DEBUG") != NULL)
+ wiringPiDebug = TRUE ;
+
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupSys called\n") ;
pinMode = pinModeSys ;
pullUpDnControl = pullUpDnControlSys ;
digitalWrite = digitalWriteSys ;
+ digitalWriteByte = digitalWriteByteSys ;
pwmWrite = pwmWriteSys ;
setPadDrive = setPadDriveSys ;
digitalRead = digitalReadSys ;
pwmSetRange = pwmSetRangeSys ;
pwmSetClock = pwmSetClockSys ;
+ boardRev = piBoardRev () ;
+
+ if (boardRev == 1)
+ pinToGpio = pinToGpioR1 ;
+ else
+ pinToGpio = pinToGpioR2 ;
// Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later
gettimeofday (&tv, NULL) ;
epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
+ wiringPiMode = WPI_MODE_GPIO_SYS ;
+
return 0 ;
}