@@ -19,13 +19,6 @@ then run the ldconfig command. | |||
sudo ldconfig | |||
If you want to install a static library, you may need to do this manually: | |||
cd wiringPi | |||
make static | |||
sudo make install-static | |||
To un-install wiringPi: | |||
./build uninstall | |||
@@ -1 +1 @@ | |||
2.44 | |||
2.46 |
@@ -64,6 +64,9 @@ if [ x$1 = "xclean" ]; then | |||
echo -n "PiGlow: " ; make clean | |||
cd ../scrollPhat | |||
echo -n "scrollPhat: " ; make clean | |||
cd ../.. | |||
echo -n "Deb: " ; rm -f debian-template/wiringpi*.deb | |||
echo | |||
exit | |||
fi | |||
@@ -1,5 +1,5 @@ | |||
Package: wiringpi | |||
Version: 2.44 | |||
Version: 2.46 | |||
Section: libraries | |||
Priority: optional | |||
Architecture: armhf | |||
@@ -1,7 +1,9 @@ | |||
/* | |||
* pins.c: | |||
* Just display a handy Pi pinnout diagram. | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
* blink-thread.c: | |||
* Standard "blink" program in wiringPi. Blinks an LED connected | |||
* to the first GPIO pin. | |||
* | |||
* Copyright (c) 2012-2013 Gordon Henderson. <projects@drogon.net> | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -21,13 +23,39 @@ | |||
*********************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include <wiringPi.h> | |||
// LED Pin - wiringPi pin 0 is BCM_GPIO 17. | |||
void doPins (void) | |||
#define LED 0 | |||
PI_THREAD (blinky) | |||
{ | |||
printf ("The pins command has been deprecated - sorry. Please use the\n") ; | |||
printf (" gpio readall\n") ; | |||
printf ("command to get a list of the pinnouts for your Pi.\n") ; | |||
for (;;) | |||
{ | |||
digitalWrite (LED, HIGH) ; // On | |||
delay (500) ; // mS | |||
digitalWrite (LED, LOW) ; // Off | |||
delay (500) ; | |||
} | |||
} | |||
int main (void) | |||
{ | |||
printf ("Raspberry Pi blink\n") ; | |||
wiringPiSetup () ; | |||
pinMode (LED, OUTPUT) ; | |||
piThreadCreate (blinky) ; | |||
for (;;) | |||
{ | |||
printf ("Hello, world\n") ; | |||
delay (600) ; | |||
} | |||
return 0 ; | |||
} |
@@ -25,7 +25,6 @@ | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <wiringPi.h> | |||
#include <sys/time.h> | |||
@@ -34,17 +33,13 @@ | |||
int main() | |||
{ | |||
int x ; | |||
struct timeval t1, t2 ; | |||
struct timeval t1, t2, t3 ; | |||
int t ; | |||
int max, min ; | |||
int del ; | |||
int underRuns, overRuns, exactRuns, total ; | |||
int underRuns, overRuns, exactRuns, bogusRuns, total ; | |||
int descheds ; | |||
if (wiringPiSetup () == -1) | |||
return 1 ; | |||
piHiPri (10) ; sleep (1) ; | |||
// Baseline test | |||
@@ -58,21 +53,22 @@ int main() | |||
{ | |||
underRuns = overRuns = exactRuns = total = 0 ; | |||
descheds = 0 ; | |||
max = del ; | |||
min = del ; | |||
max = 0 ; | |||
min = 999 ; | |||
for (x = 0 ; x < CYCLES ; ++x) | |||
{ | |||
for (;;) // Repeat this if we get a delay over 999uS | |||
{ // -> High probability Linux has deschedulled us | |||
gettimeofday (&t1, NULL) ; | |||
delayMicroseconds (del) ; | |||
usleep (del) ; | |||
// delayMicroseconds (del) ; | |||
gettimeofday (&t2, NULL) ; | |||
if (t2.tv_usec < t1.tv_usec) // Counter wrapped | |||
t = (1000000 + t2.tv_usec) - t1.tv_usec; | |||
else | |||
t = t2.tv_usec - t1.tv_usec ; | |||
timersub (&t2, &t1, &t3) ; | |||
t = t3.tv_usec ; | |||
if (t > 999) | |||
{ | |||
++descheds ; | |||
@@ -82,25 +78,24 @@ int main() | |||
break ; | |||
} | |||
if (t == del) | |||
++exactRuns ; | |||
else if (t < del) | |||
++underRuns ; | |||
else if (t > del) | |||
++overRuns ; | |||
if (t > max) | |||
{ | |||
max = t ; | |||
++overRuns ; | |||
} | |||
else if (t < min) | |||
{ | |||
min = t ; | |||
++underRuns ; | |||
} | |||
else | |||
++exactRuns ; | |||
total += t ; | |||
} | |||
printf ("Delay: %3d. Min: %3d, Max: %3d, Unders: %3d, Overs: %3d, Exacts: %3d, Average: %3d, Descheds: %2d\n", | |||
del, min, max, underRuns, overRuns, exactRuns, total / CYCLES, descheds) ; | |||
fflush (stdout) ; | |||
delay (1) ; | |||
usleep (1000) ; | |||
} | |||
return 0 ; | |||
@@ -42,7 +42,7 @@ LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt | |||
# May not need to alter anything below this line | |||
############################################################################### | |||
SRC = gpio.c readall.c pins.c | |||
SRC = gpio.c readall.c | |||
OBJ = $(SRC:.c=.o) | |||
@@ -77,22 +77,22 @@ ifneq ($(WIRINGPI_SUID),0) | |||
$Q chown root.root $(DESTDIR)$(PREFIX)/bin/gpio | |||
$Q chmod 4755 $(DESTDIR)$(PREFIX)/bin/gpio | |||
endif | |||
$Q mkdir -p $(DESTDIR)$(PREFIX)/man/man1 | |||
$Q cp gpio.1 $(DESTDIR)$(PREFIX)/man/man1 | |||
$Q mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1 | |||
$Q cp gpio.1 $(DESTDIR)$(PREFIX)/share/man/man1 | |||
.PHONY: install-deb | |||
install-deb: gpio | |||
$Q echo "[Install: deb]" | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/bin | |||
$Q install -m 0755 gpio ~/wiringPi/debian-template/wiringPi/usr/bin | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/man/man1 | |||
$Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/man/man1 | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/share/man/man1 | |||
$Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/usr/share/man/man1 | |||
.PHONY: uninstall | |||
uninstall: | |||
$Q echo "[UnInstall]" | |||
$Q rm -f $(DESTDIR)$(PREFIX)/bin/gpio | |||
$Q rm -f $(DESTDIR)$(PREFIX)/man/man1/gpio.1 | |||
$Q rm -f $(DESTDIR)$(PREFIX)/share/man/man1/gpio.1 | |||
.PHONY: depend | |||
depend: | |||
@@ -1,4 +1,4 @@ | |||
.TH GPIO 1 "September 2015" wiringPi "Command-Line access to Raspberry Pi's GPIO" | |||
.TH GPIO 1 "March 2018" wiringPi "Command-Line access to Raspberry Pi's GPIO" | |||
.SH NAME | |||
gpio \- Command-line access to Raspberry Pi's GPIO | |||
@@ -9,7 +9,7 @@ gpio \- Command-line access to Raspberry Pi's GPIO | |||
.PP | |||
.B gpio | |||
.B [ \-g | \-1 ] | |||
.B mode/read/write/aread/awrite/wb/pwm/clock/toggle/blink ... | |||
.B mode/read/write/aread/awrite/wb/pwm/pwnTone/clock/toggle/blink ... | |||
.PP | |||
.B gpio | |||
.B [ \-x extension:params ] | |||
@@ -21,6 +21,11 @@ gpio \- Command-line access to Raspberry Pi's GPIO | |||
.B ... | |||
.PP | |||
.B gpio | |||
.B [ \-p ] | |||
.B pwnTone pin frequency | |||
.B ... | |||
.PP | |||
.B gpio | |||
.B readall | |||
.PP | |||
.B gpio | |||
@@ -257,30 +262,6 @@ Change the PWM mode to balanced (the default) or mark:space ratio (traditional) | |||
Change the PWM range register. The default is 1024. | |||
.TP | |||
.B load i2c [baudrate] | |||
This loads the i2c or drivers into the kernel and changes the permissions | |||
on the associated /dev/ entries so that the current user has access to | |||
them. Optionally it will set the I2C baudrate to that supplied in Kb/sec | |||
(or as close as the Pi can manage) The default speed is 100Kb/sec. | |||
Note: On recent kernels with the device tree enabled you should use the | |||
raspi-config program to load/unload the I2C device at boot time. | |||
.TP | |||
.B load spi | |||
This loads the spi drivers into the kernel and changes the permissions | |||
on the associated /dev/ entries so that the current user has access to | |||
them. It used to have the ability to change the buffer size from the | |||
default of 4096 bytes to an arbitrary value, however for some time the | |||
Pi Foundation have compiled the SPI device driver into the kernel and | |||
this has fixed the buffer size. The way to change it now is to edit | |||
the /boot/cmdline.txt file and add on spdev.bufsiz=8192 to set it to | |||
e.g. 8192 bytes then reboot. | |||
Note: On recent kernels with the device tree enabled you should use the | |||
raspi-config program to load/unload the SPI device at boot time. | |||
.TP | |||
.B gbr | |||
channel | |||
@@ -360,7 +341,7 @@ Please report bugs to <projects@drogon.net> | |||
.SH COPYRIGHT | |||
Copyright (c) 2012-2015 Gordon Henderson | |||
Copyright (c) 2012-2018 Gordon Henderson | |||
This is free software; see the source for copying conditions. There is NO | |||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |||
@@ -2,7 +2,7 @@ | |||
* gpio.c: | |||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | |||
* Pi's GPIO. | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
* Copyright (c) 2012-2018 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -48,7 +48,7 @@ extern int wiringPiDebug ; | |||
extern void doReadall (void) ; | |||
extern void doAllReadall (void) ; | |||
extern void doPins (void) ; | |||
extern void doQmode (int argc, char *argv []) ; | |||
#ifndef TRUE | |||
# define TRUE (1==1) | |||
@@ -56,9 +56,9 @@ extern void doPins (void) ; | |||
#endif | |||
#define PI_USB_POWER_CONTROL 38 | |||
#define I2CDETECT "/usr/sbin/i2cdetect" | |||
#define MODPROBE "/sbin/modprobe" | |||
#define RMMOD "/sbin/rmmod" | |||
#define I2CDETECT "i2cdetect" | |||
#define MODPROBE "modprobe" | |||
#define RMMOD "rmmod" | |||
int wpMode ; | |||
@@ -68,9 +68,9 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio [-d] ...\n" | |||
" [-x extension:params] [[ -x ...]] ...\n" | |||
" gpio [-p] <read/write/wb> ...\n" | |||
" gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | |||
" gpio <mode/read/write/aread/awritewb/pwm/pwmTone/clock> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall/reset\n" | |||
" gpio readall\n" | |||
" gpio unexportall/exports\n" | |||
" gpio export/edge/unexport ...\n" | |||
" gpio wfi <pin> <mode>\n" | |||
@@ -221,9 +221,7 @@ static void checkDevTree (char *argv []) | |||
fprintf (stderr, | |||
"%s: Unable to load/unload modules as this Pi has the device tree enabled.\n" | |||
" You need to run the raspi-config program (as root) and select the\n" | |||
" modules (SPI or I2C) that you wish to load/unload there and reboot.\n" | |||
" There is more information here:\n" | |||
" https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314\n", argv [0]) ; | |||
" modules (SPI or I2C) that you wish to load/unload there and reboot.\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
} | |||
@@ -1270,7 +1268,7 @@ static void doVersion (char *argv []) | |||
wiringPiVersion (&vMaj, &vMin) ; | |||
printf ("gpio version: %d.%d\n", vMaj, vMin) ; | |||
printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ; | |||
printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; | |||
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; | |||
printf ("For details type: %s -warranty\n", argv [0]) ; | |||
printf ("\n") ; | |||
@@ -1320,8 +1318,11 @@ int main (int argc, char *argv []) | |||
if (argc == 1) | |||
{ | |||
fprintf (stderr, "%s\n", usage) ; | |||
return 1 ; | |||
fprintf (stderr, | |||
"%s: At your service!\n" | |||
" Type: gpio -h for full details and\n" | |||
" gpio readall for a quick printout of your connector details\n", argv [0]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Help | |||
@@ -1329,7 +1330,7 @@ int main (int argc, char *argv []) | |||
if (strcasecmp (argv [1], "-h") == 0) | |||
{ | |||
printf ("%s: %s\n", argv [0], usage) ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
// Version & Warranty | |||
@@ -1338,7 +1339,7 @@ int main (int argc, char *argv []) | |||
if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | |||
{ | |||
printf ("%d\n", piGpioLayout ()) ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
// Version and information | |||
@@ -1346,13 +1347,13 @@ int main (int argc, char *argv []) | |||
if (strcmp (argv [1], "-v") == 0) | |||
{ | |||
doVersion (argv) ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
if (strcasecmp (argv [1], "-warranty") == 0) | |||
{ | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ; | |||
printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; | |||
printf ("\n") ; | |||
printf (" This program is free software; you can redistribute it and/or modify\n") ; | |||
printf (" it under the terms of the GNU Leser General Public License as published\n") ; | |||
@@ -1367,13 +1368,13 @@ int main (int argc, char *argv []) | |||
printf (" You should have received a copy of the GNU Lesser General Public License\n") ; | |||
printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ; | |||
printf ("\n") ; | |||
return 0 ; | |||
exit (EXIT_SUCCESS) ; | |||
} | |||
if (geteuid () != 0) | |||
{ | |||
fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ; | |||
return 1 ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Initial test for /sys/class/gpio operations: | |||
@@ -1517,7 +1518,8 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; | |||
else if (strcasecmp (argv [1], "readall" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "nreadall" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "pins" ) == 0) doPins () ; | |||
else if (strcasecmp (argv [1], "pins" ) == 0) doReadall () ; | |||
else if (strcasecmp (argv [1], "qmode" ) == 0) doQmode (argc, argv) ; | |||
else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | |||
@@ -1531,5 +1533,6 @@ int main (int argc, char *argv []) | |||
fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
return 0 ; | |||
} |
@@ -1,7 +1,7 @@ | |||
/* | |||
* readall.c: | |||
* The readall functions - getting a bit big, so split them out. | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
* Copyright (c) 2012-2018 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -287,16 +287,16 @@ void abReadall (int model, int rev) | |||
/* | |||
* piPlusReadall: | |||
* Read all the pins on the model A+ or the B+ | |||
* Read all the pins on the model A+ or the B+ or actually, all 40-pin Pi's | |||
********************************************************************************* | |||
*/ | |||
static void plus2header (int model) | |||
{ | |||
/**/ if (model == PI_MODEL_AP) | |||
printf (" +-----+-----+---------+------+---+--A Plus--+---+------+---------+-----+-----+\n") ; | |||
printf (" +-----+-----+---------+------+---+---Pi A+--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_BP) | |||
printf (" +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+\n") ; | |||
printf (" +-----+-----+---------+------+---+---Pi B+--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_ZERO) | |||
printf (" +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_ZERO_W) | |||
@@ -305,6 +305,8 @@ static void plus2header (int model) | |||
printf (" +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_3) | |||
printf (" +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+\n") ; | |||
else if (model == PI_MODEL_3P) | |||
printf (" +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+\n") ; | |||
else | |||
printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; | |||
} | |||
@@ -348,7 +350,10 @@ void doReadall (void) | |||
/**/ if ((model == PI_MODEL_A) || (model == PI_MODEL_B)) | |||
abReadall (model, rev) ; | |||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) | |||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || | |||
(model == PI_MODEL_2) || | |||
(model == PI_MODEL_3) || (model == PI_MODEL_3P) || | |||
(model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W)) | |||
piPlusReadall (model) ; | |||
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||
allReadall () ; | |||
@@ -356,6 +361,7 @@ void doReadall (void) | |||
printf ("Oops - unable to determine board type... model: %d\n", model) ; | |||
} | |||
/* | |||
* doAllReadall: | |||
* Force reading of all pins regardless of Pi model | |||
@@ -366,3 +372,24 @@ void doAllReadall (void) | |||
{ | |||
allReadall () ; | |||
} | |||
/* | |||
* doQmode: | |||
* Query mode on a pin | |||
********************************************************************************* | |||
*/ | |||
void doQmode (int argc, char *argv []) | |||
{ | |||
int pin ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s qmode pin\n", argv [0]) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
pin = atoi (argv [2]) ; | |||
printf ("%s\n", alts [getAlt (pin)]) ; | |||
} |
@@ -1,3 +1,3 @@ | |||
#define VERSION "2.44" | |||
#define VERSION "2.46" | |||
#define VERSION_MAJOR 2 | |||
#define VERSION_MINOR 44 | |||
#define VERSION_MINOR 46 |
@@ -40,6 +40,7 @@ CC = gcc | |||
INCLUDE = -I. | |||
DEFS = -D_GNU_SOURCE | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC | |||
#CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Wconversion -Winline $(INCLUDE) -pipe -fPIC | |||
LIBS = -lm -lpthread -lrt -lcrypt | |||
@@ -68,13 +69,9 @@ OBJ = $(SRC:.c=.o) | |||
all: $(DYNAMIC) | |||
static: $(STATIC) | |||
$(STATIC): $(OBJ) | |||
$Q echo "[Link (Static)]" | |||
$Q ar rcs $(STATIC) $(OBJ) | |||
$Q ranlib $(STATIC) | |||
# @size $(STATIC) | |||
.PHONY: static | |||
static: | |||
$Q cat noMoreStatic | |||
$(DYNAMIC): $(OBJ) | |||
$Q echo "[Link (Dynamic)]" | |||
@@ -107,15 +104,6 @@ install: $(DYNAMIC) | |||
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so | |||
$Q $(LDCONFIG) | |||
.PHONY: install-static | |||
install-static: $(STATIC) | |||
$Q echo "[Install Headers]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/include | |||
$Q install -m 0644 $(HEADERS) $(DESTDIR)$(PREFIX)/include | |||
$Q echo "[Install Static Lib]" | |||
$Q install -m 0755 -d $(DESTDIR)$(PREFIX)/lib | |||
$Q install -m 0755 libwiringPi.a $(DESTDIR)$(PREFIX)/lib | |||
.PHONY: install-deb | |||
install-deb: $(DYNAMIC) | |||
$Q echo "[Install Headers: deb]" | |||
@@ -0,0 +1,20 @@ | |||
wiringPi is no-longer shipped with the ability to statically link it. | |||
Many reasons but the biggest issue is people who have statically linked | |||
wiringPi into their product - for example a Pi UPS device or a Tetris-like | |||
game and not subsequently shipped their modified sources. These people are | |||
no better than common thieves with complete disregard to the conditions | |||
of the LGPL that wiringPi ships with. | |||
Additionally, many think it's a good idea to statically link wiringPi | |||
into their favourite language - like Node, and Java and other itsy bitsy | |||
little things. These people have a complete and utter disregard to what | |||
happens underneath when e.g. the Linux kernel changes on the Pi then | |||
wiringPi stops as it depends on some Pi kernel features, then the poor | |||
user get in-touch with me and I've had over 10,000 emails so-far and | |||
it's now beyond a joke. | |||
DO NOT STATICALLY LINK WIRINGPI. | |||
Gordon Henderson, March 2018. |
@@ -139,6 +139,9 @@ static volatile unsigned int GPIO_PWM ; | |||
#define PAGE_SIZE (4*1024) | |||
#define BLOCK_SIZE (4*1024) | |||
static unsigned int usingGpioMem = FALSE ; | |||
static int wiringPiSetuped = FALSE ; | |||
// PWM | |||
// Word offsets into the PWM control region | |||
@@ -185,15 +188,22 @@ static volatile unsigned int GPIO_PWM ; | |||
// Locals to hold pointers to the hardware | |||
static volatile uint32_t *gpio ; | |||
static volatile uint32_t *pwm ; | |||
static volatile uint32_t *clk ; | |||
static volatile uint32_t *pads ; | |||
static volatile unsigned int *gpio ; | |||
static volatile unsigned int *pwm ; | |||
static volatile unsigned int *clk ; | |||
static volatile unsigned int *pads ; | |||
static volatile unsigned int *timer ; | |||
static volatile unsigned int *timerIrqRaw ; | |||
// Export variables for the hardware pointers | |||
volatile unsigned int *_wiringPiGpio ; | |||
volatile unsigned int *_wiringPiPwm ; | |||
volatile unsigned int *_wiringPiClk ; | |||
volatile unsigned int *_wiringPiPads ; | |||
volatile unsigned int *_wiringPiTimer ; | |||
volatile unsigned int *_wiringPiTimerIrqRaw ; | |||
#ifdef USE_TIMER | |||
static volatile uint32_t *timer ; | |||
static volatile uint32_t *timerIrqRaw ; | |||
#endif | |||
// Data for use with the boardId functions. | |||
// The order of entries here to correspond with the PI_MODEL_X | |||
@@ -223,7 +233,7 @@ const char *piModelNames [16] = | |||
"CM3", // 10 | |||
"Unknown11", // 11 | |||
"Pi Zero-W", // 12 | |||
"Unknown13", // 13 | |||
"Pi 3+", // 13 | |||
"Unknown14", // 14 | |||
"Unknown15", // 15 | |||
} ; | |||
@@ -652,6 +662,41 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
/* | |||
* setupCheck | |||
* Another sanity check because some users forget to call the setup | |||
* function. Mosty because they need feeding C drip by drip )-: | |||
********************************************************************************* | |||
*/ | |||
static void setupCheck (const char *fName) | |||
{ | |||
if (!wiringPiSetuped) | |||
{ | |||
fprintf (stderr, "%s: You have not called one of the wiringPiSetup\n" | |||
" functions, so I'm aborting your program before it crashes anyway.\n", fName) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
} | |||
/* | |||
* gpioMemCheck: | |||
* See if we're using the /dev/gpiomem interface, if-so then some operations | |||
* can't be done and will crash the Pi. | |||
********************************************************************************* | |||
*/ | |||
static void usingGpioMemCheck (const char *what) | |||
{ | |||
if (usingGpioMem) | |||
{ | |||
fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
} | |||
/* | |||
* piGpioLayout: | |||
* Return a number representing the hardware revision of the board. | |||
* This is not strictly the board revision but is used to check the | |||
@@ -720,6 +765,7 @@ int piGpioLayout (void) | |||
// I do not support so don't email me your bleating whinges about anything | |||
// other than a genuine Raspberry Pi. | |||
#ifdef DONT_CARE_ANYMORE | |||
if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835"))) | |||
{ | |||
fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ; | |||
@@ -730,12 +776,27 @@ int piGpioLayout (void) | |||
fprintf (stderr, "Raspberry Pi ONLY.\n") ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
#endif | |||
// Actually... That has caused me more than 10,000 emails so-far. Mosty by | |||
// people who think they know better by creating a statically linked | |||
// version that will not run with a new 4.9 kernel. I utterly hate and | |||
// despise those people. | |||
// | |||
// I also get bleats from people running other than Raspbian with another | |||
// distros compiled kernel rather than a foundation compiled kernel, so | |||
// this might actually help them. It might not - I only have the capacity | |||
// to support Raspbian. | |||
// | |||
// However, I've decided to leave this check out and rely purely on the | |||
// Revision: line for now. It will not work on a non-pi hardware or weird | |||
// kernels that don't give you a suitable revision line. | |||
// Right - we're Probably on a Raspberry Pi. Check the revision field for the real | |||
// So - we're Probably on a Raspberry Pi. Check the revision field for the real | |||
// hardware type | |||
// In-future, I ought to use the device tree as there are now Pi entries in | |||
// /proc/device-tree/ ... | |||
// but I'll leave that for the next revision. | |||
// but I'll leave that for the next revision. Or the next. | |||
// Isolate the Revision line | |||
@@ -938,7 +999,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
if ((revision & (1 << 23)) != 0) // New way | |||
{ | |||
if (wiringPiDebug) | |||
printf ("piBoardId: New Way: revision is: 0x%08X\n", revision) ; | |||
printf ("piBoardId: New Way: revision is: %08X\n", revision) ; | |||
bRev = (revision & (0x0F << 0)) >> 0 ; | |||
bType = (revision & (0xFF << 4)) >> 4 ; | |||
@@ -1183,7 +1244,7 @@ void pwmSetClock (int divisor) | |||
/* | |||
* gpioClockSet: | |||
* Set the freuency on a GPIO clock pin | |||
* Set the frequency on a GPIO clock pin | |||
********************************************************************************* | |||
*/ | |||
@@ -1322,6 +1383,8 @@ void pinModeAlt (int pin, int mode) | |||
{ | |||
int fSel, shift ; | |||
setupCheck ("pinModeAlt") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-board pin | |||
{ | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
@@ -1351,6 +1414,8 @@ void pinMode (int pin, int mode) | |||
struct wiringPiNodeStruct *node = wiringPiNodes ; | |||
int origPin = pin ; | |||
setupCheck ("pinMode") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-board pin | |||
{ | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
@@ -1384,6 +1449,8 @@ void pinMode (int pin, int mode) | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
return ; | |||
usingGpioMemCheck ("pinMode PWM") ; | |||
// Set pin to PWM mode | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; | |||
@@ -1398,6 +1465,8 @@ void pinMode (int pin, int mode) | |||
if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin | |||
return ; | |||
usingGpioMemCheck ("pinMode CLOCK") ; | |||
// Set pin to GPIO_CLOCK mode and set the clock frequency to 100KHz | |||
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ; | |||
@@ -1416,10 +1485,7 @@ void pinMode (int pin, int mode) | |||
/* | |||
* pullUpDownCtrl: | |||
* Control the internal pull-up/down resistors on a GPIO pin | |||
* The Arduino only has pull-ups and these are enabled by writing 1 | |||
* to a port when in input mode - this paradigm doesn't quite apply | |||
* here though. | |||
* Control the internal pull-up/down resistors on a GPIO pin. | |||
********************************************************************************* | |||
*/ | |||
@@ -1427,6 +1493,8 @@ void pullUpDnControl (int pin, int pud) | |||
{ | |||
struct wiringPiNodeStruct *node = wiringPiNodes ; | |||
setupCheck ("pullUpDnControl") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | |||
{ | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
@@ -1588,6 +1656,8 @@ void pwmWrite (int pin, int value) | |||
{ | |||
struct wiringPiNodeStruct *node = wiringPiNodes ; | |||
setupCheck ("pwmWrite") ; | |||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | |||
{ | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
@@ -1597,6 +1667,7 @@ void pwmWrite (int pin, int value) | |||
else if (wiringPiMode != WPI_MODE_GPIO) | |||
return ; | |||
usingGpioMemCheck ("pwmWrite") ; | |||
*(pwm + gpioToPwmPort [pin]) = value ; | |||
} | |||
else | |||
@@ -1656,6 +1727,8 @@ void pwmToneWrite (int pin, int freq) | |||
{ | |||
int range ; | |||
setupCheck ("pwmToneWrite") ; | |||
if (freq == 0) | |||
pwmWrite (pin, 0) ; // Off | |||
else | |||
@@ -2139,16 +2212,15 @@ int wiringPiSetup (void) | |||
{ | |||
int fd ; | |||
int model, rev, mem, maker, overVolted ; | |||
static int alreadyDoneThis = FALSE ; | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
if (alreadyDoneThis) | |||
if (wiringPiSetuped) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
wiringPiSetuped = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -2204,11 +2276,18 @@ int wiringPiSetup (void) | |||
// Try /dev/mem. If that fails, then | |||
// try /dev/gpiomem. If that fails then game over. | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0) | |||
{ | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n Try running with sudo?\n", strerror (errno)) ; | |||
piGpioBase = 0 ; | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem | |||
{ | |||
piGpioBase = 0 ; | |||
usingGpioMem = TRUE ; | |||
} | |||
else | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n" | |||
" Aborting your program because if it can not access the GPIO\n" | |||
" hardware then it most certianly won't work\n" | |||
" Try running with sudo?\n", strerror (errno)) ; | |||
} | |||
// Set the offsets into the memory interface. | |||
@@ -2245,7 +2324,6 @@ int wiringPiSetup (void) | |||
if (pads == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; | |||
#ifdef USE_TIMER | |||
// The system timer | |||
timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; | |||
@@ -2259,7 +2337,14 @@ int wiringPiSetup (void) | |||
*(timer + TIMER_CONTROL) = 0x0000280 ; | |||
*(timer + TIMER_PRE_DIV) = 0x00000F9 ; | |||
timerIrqRaw = timer + TIMER_IRQ_RAW ; | |||
#endif | |||
// Export the base addresses for any external software that might need them | |||
_wiringPiGpio = gpio ; | |||
_wiringPiPwm = pwm ; | |||
_wiringPiClk = clk ; | |||
_wiringPiPads = pads ; | |||
_wiringPiTimer = timer ; | |||
initialiseEpoch () ; | |||
@@ -2325,16 +2410,10 @@ int wiringPiSetupSys (void) | |||
int pin ; | |||
char fName [128] ; | |||
static int alreadyDoneThis = FALSE ; | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
if (alreadyDoneThis) | |||
if (wiringPiSetuped) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
wiringPiSetuped = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -99,6 +99,7 @@ | |||
#define PI_MODEL_ZERO 9 | |||
#define PI_MODEL_CM3 10 | |||
#define PI_MODEL_ZERO_W 12 | |||
#define PI_MODEL_3P 13 | |||
#define PI_VERSION_1 0 | |||
#define PI_VERSION_1_1 1 | |||
@@ -162,6 +163,15 @@ struct wiringPiNodeStruct | |||
extern struct wiringPiNodeStruct *wiringPiNodes ; | |||
// Export variables for the hardware pointers | |||
extern volatile unsigned int *_wiringPiGpio ; | |||
extern volatile unsigned int *_wiringPiPwm ; | |||
extern volatile unsigned int *_wiringPiClk ; | |||
extern volatile unsigned int *_wiringPiPads ; | |||
extern volatile unsigned int *_wiringPiTimer ; | |||
extern volatile unsigned int *_wiringPiTimerIrqRaw ; | |||
// Function prototypes | |||
// c++ wrappers thanks to a comment by Nick Lott | |||
@@ -871,7 +871,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors) | |||
char *p ; | |||
char *extension = extensionData ; | |||
struct extensionFunctionStruct *extensionFn ; | |||
unsigned pinBase = 0 ; | |||
int pinBase = 0 ; | |||
verbose = printErrors ; | |||