diff --git a/INSTALL b/INSTALL index 3b11fa8f..f91b6484 100644 --- a/INSTALL +++ b/INSTALL @@ -26,8 +26,4 @@ To un-install wiringPi: For help and support see: * https://github.com/WiringPi/WiringPi/issues -* https://discord.gg/SM4WUVG - -wiringPi originally created by Gordon Henderson -https://projects.drogon.net/ diff --git a/People b/People index b339494e..20ddb459 100644 --- a/People +++ b/People @@ -31,3 +31,5 @@ Andre Crone Rik Teerling Pointing out some silly mistooks in the I2C code... + +And everyone else that's been working on this project! \ No newline at end of file diff --git a/README.md b/README.md index 740b65cc..e534bb44 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,127 @@ -:warning: This library was deprecated by its author in August 2019. As of 31st October 2023 nobody has shown an interest in properly maintaining it. Between this, and changes to GPIO in Rasberry Pi OS Bookworm and on the Raspberry Pi 5, this project is going nowhere. It has been archived to more clearly indicate this status. +# WiringPi -WiringPi (Unofficial Mirror/Fork) -================================= +WiringPi is a _performant_ GPIO access library written in C for Raspberry Pi boards. -This is an unofficial mirror/fork of wiringPi to support ports (Python/Ruby/etc). With the -[end of official development](https://web.archive.org/web/20220405225008/http://wiringpi.com/wiringpi-deprecated/), this repository -has become a mirror of the last "official" source release, plus a fork facilitating updates -to support newer hardware (primarily for use by the ports) and fix bugs. +:warning:️ :construction: on Pi5, PWM support is currently under development and _will not work at this point_. If you're interested in the progress, please check the [corresponding issue](https://github.com/GrazerComputerClub/WiringPi/issues/21). - * The final "official" source release can be found at the - [`final_source_2.50`](https://github.com/WiringPi/WiringPi/tree/final_official_2.50) tag. - * The default `master` branch contains code that has been written since that final source - release to provide support for newer hardware. -Ports ------ +To compile programs with wiringPi, you need to include `wiringPi.h` as well as link against `wiringPi`: + +```c +#include // Include WiringPi library! + +int main(void) +{ + // uses BCM numbering of the GPIOs and directly accesses the GPIO registers. + wiringPiSetupGpio(); + + // pin mode ..(INPUT, OUTPUT, PWM_OUTPUT, GPIO_CLOCK) + // set pin 17 to input + pinMode(17, INPUT); + + // pull up/down mode (PUD_OFF, PUD_UP, PUD_DOWN) => down + pullUpDnControl(17, PUD_DOWN); + + // get state of pin 17 + int value = digitalRead(17); + + if (HIGH == value) + { + // your code + } +} +``` + +To compile this code, link against wiringPi: + +```sh +gcc -o myapp myapp.c -l wiringPi +``` + +Be sure to check out the [examples](./examples/), build them using Make: + +```sh +cd examples +make +``` + +The tool `gpio` can be used to set single pins as well as get the state of everything at once: + +``` +pi@wiringdemo:~ $ gpio readall + +-----+-----+---------+------+---+---Pi 3B--+---+------+---------+-----+-----+ + | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | + +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ + | | | 3.3v | | | 1 || 2 | | | 5v | | | + | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5v | | | + | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | + | 4 | 7 | GPIO. 7 | IN | 0 | 7 || 8 | 0 | IN | TxD | 15 | 14 | + | | | 0v | | | 9 || 10 | 1 | IN | RxD | 16 | 15 | + | 17 | 0 | GPIO. 0 | IN | 1 | 11 || 12 | 1 | IN | GPIO. 1 | 1 | 18 | + | 27 | 2 | GPIO. 2 | IN | 1 | 13 || 14 | | | 0v | | | + | 22 | 3 | GPIO. 3 | IN | 1 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | + | | | 3.3v | | | 17 || 18 | 1 | IN | GPIO. 5 | 5 | 24 | + | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | + | 9 | 13 | MISO | IN | 0 | 21 || 22 | 1 | IN | GPIO. 6 | 6 | 25 | + | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 | + | | | 0v | | | 25 || 26 | 0 | IN | CE1 | 11 | 7 | + | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | + | 5 | 21 | GPIO.21 | IN | 0 | 29 || 30 | | | 0v | | | + | 6 | 22 | GPIO.22 | IN | 0 | 31 || 32 | 1 | IN | GPIO.26 | 26 | 12 | + | 13 | 23 | GPIO.23 | IN | 1 | 33 || 34 | | | 0v | | | + | 19 | 24 | GPIO.24 | IN | 1 | 35 || 36 | 1 | IN | GPIO.27 | 27 | 16 | + | 26 | 25 | GPIO.25 | IN | 1 | 37 || 38 | 1 | IN | GPIO.28 | 28 | 20 | + | | | 0v | | | 39 || 40 | 1 | IN | GPIO.29 | 29 | 21 | + +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ + | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | + +-----+-----+---------+------+---+---Pi 3B--+---+------+---------+-----+-----+ +``` + + +## Installing + +You can either build it yourself or use the prebuilt binaries: + +### From Source + +1. create debian-package + +```sh +# fetch the source +sudo apt install git +git clone https://github.com/WiringPi/WiringPi.git +cd WiringPi + +# build the package +./build debian +mv debian-template/wiringpi-3.0-1.deb . + +# install it +sudo apt install ./wiringpi-3.0-1.deb +``` + + +### Prebuilt Binaries + +Grab the latest release from [here](https://github.com/WiringPi/WiringPi/releases). + + +Unzip/use the portable prebuilt verison: + +```sh +# unzip the archive +tar -xfv wiringpi_3.0.tar.gz +``` + +Install the debian package: + +```sh +# install a dpkg +sudo apt install ./wiringpi-3.0-1.deb +``` + + +## Ports wiringPi has been wrapped for multiple languages: @@ -24,7 +131,26 @@ wiringPi has been wrapped for multiple languages: * Python - https://github.com/WiringPi/WiringPi-Python * Ruby - https://github.com/WiringPi/WiringPi-Ruby -Support -------- +## Support + +Please use the [issue system](https://github.com/WiringPi/WiringPi/issues) of GitHub. + +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. + +## History + +This repository is the continuation of 'Gordon's wiringPi' which has been [deprecated](https://web.archive.org/web/20220405225008/http://wiringpi.com/wiringpi-deprecated/), a while ago. + +* The last "old wiringPi" source of Gordon's release can be found at the + [`final_source_2.50`](https://github.com/WiringPi/WiringPi/tree/final_official_2.50) tag. +* The default `master` branch contains code that has been written since version 2.5 + to provide support for newer hardware as well as new features. + +:information_source:️ Since 2024, [GC2](https://github.com/GrazerComputerClub) has taken over maintenance of the project, supporting new OS versions as well as current hardware generations. We are dedicated to keeping the arguably best-performing GPIO Library for Raspberry Pi running smoothly. We strive to do our best, but please note that this is a community effort, and we cannot provide any guarantees or take responsibility for implementing specific features you may need. + +## Debug -Please do not email Gordon if you have issues, he will not be able to help. +WIRINGPI_DEBUG=1 ./my_wiringpi_program +WIRINGPI_DEBUG=1 ./gpio readall diff --git a/VERSION b/VERSION index 587cb39c..f398a206 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.70 +3.0 \ No newline at end of file diff --git a/debian-template/wiringPi/DEBIAN/control b/debian-template/wiringPi/DEBIAN/control index ee811af9..2d1ae2c3 100644 --- a/debian-template/wiringPi/DEBIAN/control +++ b/debian-template/wiringPi/DEBIAN/control @@ -1,13 +1,13 @@ Package: wiringpi -Version: 2.70 +Version: 3.0 Section: libraries Priority: optional Architecture: armhf Depends: libc6 -Maintainer: Phil Howard -Uploaders: Phil Howard +Maintainer: Grazer Computer Club - GC2 +Uploaders: Grazer Computer Club - GC2 Description: The wiringPi libraries, headers and gpio command Libraries to allow GPIO access on a Raspberry Pi from C and C++ - and BASIC programs as well as from the command-line -Homepage: https://github.com/WiringPi/WiringPi/ -Bugs: https://github.com/WiringPi/WiringPi/ + programs as well as from the command-line +Homepage: https://github.com/WiringPi/WiringPi +Bugs: https://github.com/WiringPi/WiringPi/issues diff --git a/debian-template/wiringPi/DEBIAN/postinst b/debian-template/wiringPi/DEBIAN/postinst index 4997e98d..600192f1 100755 --- a/debian-template/wiringPi/DEBIAN/postinst +++ b/debian-template/wiringPi/DEBIAN/postinst @@ -1,5 +1,5 @@ #!/bin/sh set -e -/bin/chown root.root /usr/bin/gpio +/bin/chown root:root /usr/bin/gpio /bin/chmod 4755 /usr/bin/gpio /sbin/ldconfig diff --git a/gpio/gpio.c b/gpio/gpio.c index 46b36df9..c4d698e7 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -2,7 +2,7 @@ * gpio.c: * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry * Pi's GPIO. - * Copyright (c) 2012-2018 Gordon Henderson + * Copyright (c) 2012-2024 Gordon Henderson and contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ @@ -88,6 +88,15 @@ char *usage = "Usage: gpio -v\n" " gpio gbw " ; // No trailing newline needed here. +int GPIOToSysFS_ExitonFail (const int pin, const char* name) { + int pinFS = GPIOToSysFS(pin); + if (pinFS<0) { + fprintf (stderr, "%s: invalid sysfs pin of bcm pin %d\n", name, pin) ; + exit (1) ; + } + return pinFS; +} + #ifdef NOT_FOR_NOW /* * decodePin: @@ -391,16 +400,19 @@ static void doI2Cdetect (UNU int argc, char *argv []) static void doExports (UNU int argc, UNU char *argv []) { int fd ; - int i, l, first ; + int pin, l, first ; char fName [128] ; char buf [16] ; - for (first = 0, i = 0 ; i < 64 ; ++i) // Crude, but effective + for (first = 0, pin = 0 ; pin < 64 ; ++pin) // Crude, but effective { // Try to read the direction - - sprintf (fName, "/sys/class/gpio/gpio%d/direction", i) ; + int pinFS = GPIOToSysFS(pin); + if (pinFS<0) { + continue; + } + sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; if ((fd = open (fName, O_RDONLY)) == -1) continue ; @@ -410,7 +422,11 @@ static void doExports (UNU int argc, UNU char *argv []) printf ("GPIO Pins exported:\n") ; } - printf ("%4d: ", i) ; + if(pinFS==pin) { + printf ("%4d: ", pin) ; + } else { + printf ("%4d (%4d): ", pin, pinFS) ; + } if ((l = read (fd, buf, 16)) == 0) sprintf (buf, "%s", "?") ; @@ -425,7 +441,7 @@ static void doExports (UNU int argc, UNU char *argv []) // Try to Read the value - sprintf (fName, "/sys/class/gpio/gpio%d/value", i) ; + sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; if ((fd = open (fName, O_RDONLY)) == -1) { printf ("No Value file (huh?)\n") ; @@ -443,7 +459,7 @@ static void doExports (UNU int argc, UNU char *argv []) // Read any edge trigger file - sprintf (fName, "/sys/class/gpio/gpio%d/edge", i) ; + sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; if ((fd = open (fName, O_RDONLY)) == -1) { printf ("\n") ; @@ -485,7 +501,7 @@ void doExport (int argc, char *argv []) } pin = atoi (argv [2]) ; - + int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); mode = argv [3] ; if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) @@ -494,10 +510,9 @@ void doExport (int argc, char *argv []) exit (1) ; } - fprintf (fd, "%d\n", pin) ; + fprintf (fd, "%d\n", pinFS) ; fclose (fd) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; if ((fd = fopen (fName, "w")) == NULL) { fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; @@ -522,10 +537,10 @@ void doExport (int argc, char *argv []) // Change ownership so the current user can actually use it - sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; changeOwner (argv [0], fName) ; - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; changeOwner (argv [0], fName) ; } @@ -599,6 +614,7 @@ void doEdge (int argc, char *argv []) } pin = atoi (argv [2]) ; + int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); mode = argv [3] ; // Export the pin and set direction to input @@ -609,10 +625,10 @@ void doEdge (int argc, char *argv []) exit (1) ; } - fprintf (fd, "%d\n", pin) ; + fprintf (fd, "%d\n", pinFS) ; fclose (fd) ; - sprintf (fName, "/sys/class/gpio/gpio%d/direction", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/direction", pinFS) ; if ((fd = fopen (fName, "w")) == NULL) { fprintf (stderr, "%s: Unable to open GPIO direction interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; @@ -622,7 +638,7 @@ void doEdge (int argc, char *argv []) fprintf (fd, "in\n") ; fclose (fd) ; - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; if ((fd = fopen (fName, "w")) == NULL) { fprintf (stderr, "%s: Unable to open GPIO edge interface for pin %d: %s\n", argv [0], pin, strerror (errno)) ; @@ -641,10 +657,10 @@ void doEdge (int argc, char *argv []) // Change ownership of the value and edge files, so the current user can actually use it! - sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; changeOwner (argv [0], fName) ; - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ; + sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; changeOwner (argv [0], fName) ; fclose (fd) ; @@ -670,6 +686,7 @@ void doUnexport (int argc, char *argv []) } pin = atoi (argv [2]) ; + int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) { @@ -677,7 +694,7 @@ void doUnexport (int argc, char *argv []) exit (1) ; } - fprintf (fd, "%d\n", pin) ; + fprintf (fd, "%d\n", pinFS) ; fclose (fd) ; } @@ -697,13 +714,16 @@ void doUnexportall (char *progName) for (pin = 0 ; pin < 63 ; ++pin) { - if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ; - exit (1) ; + int pinFS = GPIOToSysFS(pin); + if (pinFS>=0) { + if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) + { + fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ; + exit (1) ; + } + fprintf (fd, "%d\n", pinFS) ; + fclose (fd) ; } - fprintf (fd, "%d\n", pin) ; - fclose (fd) ; } } @@ -774,6 +794,31 @@ void doMode (int argc, char *argv []) ********************************************************************************* */ +static void doPadDrivePin (int argc, char *argv []) +{ + + if (argc != 4) { + fprintf (stderr, "Usage: %s drivepin pin value\n", argv [0]) ; + exit (1) ; + } + + int pin = atoi (argv [2]) ; + int val = atoi (argv [3]) ; + + if ((pin < 0) || (pin > 27)) { + fprintf (stderr, "%s: drive pin not 0-27: %d\n", argv [0], pin) ; + exit (1) ; + } + + if ((val < 0) || (val > 3)) { + fprintf (stderr, "%s: drive value not 0-3: %d\n", argv [0], val) ; + exit (1) ; + } + + setPadDrivePin (pin, val) ; +} + + static void doPadDrive (int argc, char *argv []) { int group, val ; @@ -787,7 +832,7 @@ static void doPadDrive (int argc, char *argv []) group = atoi (argv [2]) ; val = atoi (argv [3]) ; - if ((group < 0) || (group > 2)) + if ((group < -1) || (group > 2)) //-1 hidden feature for read and print values { fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ; exit (1) ; @@ -1268,7 +1313,7 @@ static void doVersion (char *argv []) wiringPiVersion (&vMaj, &vMin) ; printf ("gpio version: %d.%d\n", vMaj, vMin) ; - printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; + printf ("Copyright (c) 2012-2024 Gordon Henderson and contributors\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("For details type: %s -warranty\n", argv [0]) ; printf ("\n") ; @@ -1293,7 +1338,7 @@ static void doVersion (char *argv []) } } - if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO + if (wiringPiUserLevelAccess()) // User level GPIO is GO printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; else printf (" * Root or sudo required for GPIO access.\n") ; @@ -1353,7 +1398,7 @@ int main (int argc, char *argv []) if (strcasecmp (argv [1], "-warranty") == 0) { printf ("gpio version: %s\n", VERSION) ; - printf ("Copyright (c) 2012-2018 Gordon Henderson\n") ; + printf ("Copyright (c) 2012-2024 Gordon Henderson and contributors\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") ; @@ -1516,6 +1561,7 @@ int main (int argc, char *argv []) else if (strcasecmp (argv [1], "pwmc" ) == 0) doPwmClock (argc, argv) ; else if (strcasecmp (argv [1], "pwmTone" ) == 0) doPwmTone (argc, argv) ; else if (strcasecmp (argv [1], "drive" ) == 0) doPadDrive (argc, argv) ; + else if (strcasecmp (argv [1], "drivepin" ) == 0) doPadDrivePin(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) doReadall () ; diff --git a/gpio/readall.c b/gpio/readall.c index 932f8e1f..c28f7fea 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -1,7 +1,7 @@ /* * readall.c: * The readall functions - getting a bit big, so split them out. - * Copyright (c) 2012-2018 Gordon Henderson + * Copyright (c) 2012-2024 Gordon Henderson and contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ @@ -75,11 +75,23 @@ static void doReadallExternal (void) ********************************************************************************* */ -static char *alts [] = +static const char unknown_alt[] = " - "; +static const char *alts [] = { - "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" + "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3", "ALT6", "ALT7", "ALT8", "ALT9" } ; + +static const char* GetAltString(int alt) { + + if (alt>=0 && alt<=11) { + return alts[alt]; + } + + return unknown_alt; +} + + static int physToWpi [64] = { -1, // 0 @@ -177,7 +189,7 @@ static void readallPhys (int physPin) else pin = physToWpi [physPin] ; - printf (" | %4s", alts [getAlt (pin)]) ; + printf (" | %4s", GetAltString(getAlt (pin))) ; printf (" | %d", digitalRead (pin)) ; } @@ -201,7 +213,7 @@ static void readallPhys (int physPin) pin = physToWpi [physPin] ; printf (" | %d", digitalRead (pin)) ; - printf (" | %-4s", alts [getAlt (pin)]) ; + printf (" | %-4s", GetAltString(getAlt (pin))) ; } printf (" | %-5s", physNames [physPin]) ; @@ -233,11 +245,11 @@ static void allReadall (void) for (pin = 0 ; pin < 27 ; ++pin) { printf ("| %3d ", pin) ; - printf ("| %-4s ", alts [getAlt (pin)]) ; + printf ("| %-4s ", GetAltString(getAlt (pin))) ; printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; printf ("| ") ; printf ("| %3d ", pin + 27) ; - printf ("| %-4s ", alts [getAlt (pin + 27)]) ; + printf ("| %-4s ", GetAltString(getAlt (pin + 27))) ; printf ("| %s ", digitalRead (pin + 27) == HIGH ? "High" : "Low ") ; printf ("|\n") ; } @@ -315,6 +327,8 @@ static void plus2header (int model) printf (" +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+\n") ; else if (model == PI_MODEL_400) printf (" +-----+-----+---------+------+---+---Pi 400-+---+------+---------+-----+-----+\n") ; + else if (model == PI_MODEL_5) + printf (" +-----+-----+---------+------+---+---Pi 5---+---+------+---------+-----+-----+\n") ; else printf (" +-----+-----+---------+------+---+---Pi ?---+---+------+---------+-----+-----+\n") ; } @@ -363,7 +377,8 @@ void doReadall (void) (model == PI_MODEL_3AP) || (model == PI_MODEL_3B) || (model == PI_MODEL_3BP) || (model == PI_MODEL_4B) || (model == PI_MODEL_400) || (model == PI_MODEL_CM4) || - (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W) || (model == PI_MODEL_ZERO_2W)) + (model == PI_MODEL_ZERO) || (model == PI_MODEL_ZERO_W) || (model == PI_MODEL_ZERO_2W) || + (model == PI_MODEL_5) ) piPlusReadall (model) ; else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3) || (model == PI_MODEL_CM3P) ) allReadall () ; @@ -401,5 +416,5 @@ void doQmode (int argc, char *argv []) } pin = atoi (argv [2]) ; - printf ("%s\n", alts [getAlt (pin)]) ; + printf ("%s\n", GetAltString(getAlt (pin))) ; } diff --git a/newVersion b/newVersion old mode 100644 new mode 100755 index e63b9277..b8cbef16 --- a/newVersion +++ b/newVersion @@ -40,8 +40,8 @@ Section: libraries Priority: optional Architecture: armhf Depends: libc6 -Maintainer: Phil Howard -Uploaders: Phil Howard +Maintainer: Grazer Computer Club - GC2 +Uploaders: Grazer Computer Club - GC2 Description: The wiringPi libraries, headers and gpio command Libraries to allow GPIO access on a Raspberry Pi from C and C++ and BASIC programs as well as from the command-line diff --git a/update b/update deleted file mode 100755 index 0f722434..00000000 --- a/update +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -# update - update source files from master on yakko - -rsync -aHx --exclude='*.o' --exclude='*~' -v --delete gordon@yakko:rpi/git/wiringPi/ . diff --git a/version.h b/version.h index 10c398ab..5ea99743 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "2.70" -#define VERSION_MAJOR 2 -#define VERSION_MINOR 70 +#define VERSION "3.0" +#define VERSION_MAJOR 3 +#define VERSION_MINOR 0 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index d4b1e24d..bbf17133 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -1,7 +1,7 @@ /* * wiringPi: * Arduino look-a-like Wiring library for the Raspberry Pi - * Copyright (c) 2012-2017 Gordon Henderson + * Copyright (c) 2012-2024 Gordon Henderson and contributors * Additional code for pwmSetClock by Chris Hall * * Thanks to code samples from Gert Jan van Loo and the @@ -123,6 +123,50 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; #define FSEL_ALT4 0b011 #define FSEL_ALT5 0b010 +//RP1 chip (@Pi5) - 3.1.1. Function select +#define RP1_FSEL_ALT0 0x00 +#define RP1_FSEL_GPIO 0x05 //SYS_RIO +#define RP1_FSEL_NONE 0x09 +#define RP1_FSEL_NONE_HW 0x1f //default, mask + +//RP1 chip (@Pi5) RIO address +const unsigned int RP1_RIO_OUT = 0x0000; +const unsigned int RP1_RIO_OE = (0x0004/4); +const unsigned int RP1_RIO_IN = (0x0008/4); + +//RP1 chip (@Pi5) RIO offset for set/clear value +const unsigned int RP1_SET_OFFSET = (0x2000/4); +const unsigned int RP1_CLR_OFFSET = (0x3000/4); + +//RP1 chip (@Pi5) PDE/PDU pull-up/-down enable +const unsigned int RP1_PUD_UP = (1<<3); +const unsigned int RP1_PUD_DOWN = (1<<2); +const unsigned int RP1_INV_PUD_MASK = ~(RP1_PUD_UP | RP1_PUD_DOWN); //~0x0C + +//RP1 chip (@Pi5) pin level, status register +const unsigned int RP1_STATUS_LEVEL_LOW = 0x00400000; +const unsigned int RP1_STATUS_LEVEL_HIGH = 0x00800000; +const unsigned int RP1_STATUS_LEVEL_MASK = 0x00C00000; + +const unsigned int RP1_DEBOUNCE_DEFAULT_VALUE = 4; +const unsigned int RP1_DEBOUNCE_MASK = 0x7f; +const unsigned int RP1_DEBOUNCE_DEFAULT = (RP1_DEBOUNCE_DEFAULT_VALUE << 5); + +const unsigned int RP1_PAD_DEFAULT_0TO8 = (0x0B | 0x70); //Slewfast, Schmitt, PullUp, | 12mA, Input enable +const unsigned int RP1_PAD_DEFAULT_FROM9 = (0x07 | 0x70); //Slewfast, Schmitt, PullDown, | 12mA, Input enable + +const unsigned int RP1_PAD_DRIVE_MASK = 0x00000030; +const unsigned int RP1_INV_PAD_DRIVE_MASK = ~(RP1_PAD_DRIVE_MASK); + +//RP1 chip (@Pi5) address +const unsigned long long RP1_64_BASE_Addr = 0x1f000d0000; +const unsigned int RP1_BASE_Addr = 0x40000000; +const unsigned int RP1_PWM0_Addr = 0x40098000; // Adress is not mapped to gpiomem device! +const unsigned int RP1_IO0_Addr = 0x400d0000; +const unsigned int RP1_SYS_RIO0_Addr = 0x400e0000; +const unsigned int RP1_PADS0_Addr = 0x400f0000; + + // Access from ARM Running Linux // Taken from Gert/Doms code. Some of this is not in the manual // that I can find )-: @@ -130,11 +174,24 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; // Updates in September 2015 - all now static variables (and apologies for the caps) // due to the Pi v2, v3, etc. and the new /dev/gpiomem interface +const char* gpiomem_global = "/dev/mem"; +const char* gpiomem_BCM = "/dev/gpiomem"; +const char* gpiomem_RP1 = "/dev/gpiomem0"; +const int gpiomem_RP1_Size = 0x00030000; +// PCIe Memory access, static define - maybe needed to detect in future +//dmesg: rp1 0000:01:00.0: bar1 len 0x400000, start 0x1f00000000, end 0x1f003fffff, flags, 0x40200 +const char* pciemem_RP1_path = "/sys/bus/pci/devices/0000:01:00.0"; +const char* pciemem_RP1 = "/sys/bus/pci/devices/0000:01:00.0/resource1"; +const int pciemem_RP1_Size = 0x00400000; +const unsigned short pciemem_RP1_Ventor= 0x1de4; +const unsigned short pciemem_RP1_Device= 0x0001; + static volatile unsigned int GPIO_PADS ; static volatile unsigned int GPIO_CLOCK_BASE ; static volatile unsigned int GPIO_BASE ; static volatile unsigned int GPIO_TIMER ; static volatile unsigned int GPIO_PWM ; +static volatile unsigned int GPIO_RIO ; #define PAGE_SIZE (4*1024) #define BLOCK_SIZE (4*1024) @@ -188,22 +245,25 @@ static int wiringPiSetuped = FALSE ; // Locals to hold pointers to the hardware +static volatile unsigned int *base ; 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 ; +static volatile unsigned int *rio ; // Export variables for the hardware pointers +volatile unsigned int *_wiringPiBase ; volatile unsigned int *_wiringPiGpio ; volatile unsigned int *_wiringPiPwm ; volatile unsigned int *_wiringPiClk ; volatile unsigned int *_wiringPiPads ; volatile unsigned int *_wiringPiTimer ; volatile unsigned int *_wiringPiTimerIrqRaw ; - +volatile unsigned int *_wiringPiRio ; // Data for use with the boardId functions. // The order of entries here to correspond with the PI_MODEL_X @@ -216,10 +276,11 @@ volatile unsigned int *_wiringPiTimerIrqRaw ; #define GPIO_PERI_BASE_OLD 0x20000000 #define GPIO_PERI_BASE_2835 0x3F000000 #define GPIO_PERI_BASE_2711 0xFE000000 +#define GPIO_PERI_BASE_2712 0x00 //unknown - 32-bit mapped global mem access not supported for now static volatile unsigned int piGpioBase = 0 ; -const char *piModelNames [21] = +const char *piModelNames [24] = { "Model A", // 0 "Model B", // 1 @@ -242,6 +303,18 @@ const char *piModelNames [21] = "Pi Zero2-W", // 18 "Pi 400", // 19 "CM4", // 20 + "CM4S", // 21 + "Unknown22", // 22 + "Pi 5", // 23 +} ; + +const char *piProcessor [5] = +{ + "BCM2835", + "BCM2836", + "BCM2837", + "BCM2711", + "BCM2712", } ; const char *piRevisionNames [16] = @@ -269,9 +342,9 @@ const char *piMakerNames [16] = "Sony", // 0 "Egoman", // 1 "Embest", // 2 - "Unknown", // 3 + "Unknown",// 3 "Embest", // 4 - "Unknown05", // 5 + "Stadium",// 5 "Unknown06", // 6 "Unknown07", // 7 "Unknown08", // 8 @@ -306,6 +379,8 @@ static int wiringPiMode = WPI_MODE_UNINITIALISED ; static volatile int pinPass = -1 ; static pthread_mutex_t pinMutex ; +static int RaspberryPiModel = -1; + // Debugging & Return codes int wiringPiDebug = FALSE ; @@ -450,6 +525,69 @@ static int physToGpioR2 [64] = -1, -1, } ; +const int _5v=-1; +const int _0v=-1; +const int _3v=-1; + + +static int physToSysGPIOPi5 [41] = +{ + -1, // 0 + _3v, _5v, // 1, 2 + 401, _5v, + 402, _0v, + 403, 413, + _0v, 414, + 416, 417, + 426, _0v, + 421, 422, + _3v, 423, + 409, _0v, + 408, 424, + 410, 407, + _0v, 406, + 399, 400, + 404, _0v, + 405, 411, + 412, _0v, + 418, 415, + 425, 419, + _0v, 420, //39, 40 +} ; + +int GPIOToSysFS(const int pin) { + int sysfspin = pin; + if (RaspberryPiModel<0) { //need to detect pi model + int model, rev, mem, maker, overVolted ; + piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + } + if (PI_MODEL_5 == RaspberryPiModel) { + sysfspin = pin + 399; + if (sysfspin<399 || sysfspin>426) { // only 399-426 supported, 40-pin GPIO header + sysfspin = -1; + } + } + if (wiringPiDebug) + printf ("GPIOToSysFS: translate bcm gpio %d to sysfs gpio %d\n", pin, sysfspin) ; + + return sysfspin; +} + +int GetMaxPin() { + return PI_MODEL_5 == RaspberryPiModel ? 27 : 63; +} + + +#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } + +int FailOnModel5() { + if (PI_MODEL_5 == RaspberryPiModel) { + return wiringPiFailure (WPI_ALMOST, "Function not supported on Raspberry Pi 5.\n" + " Unable to continue. Keep an eye of new versions at https://github.com/wiringpi/wiringpi\n") ; + } + return 0; +} + // gpioToGPFSEL: // Map a BCM_GPIO pin to it's Function Selection // control port. (GPFSEL 0-5) @@ -706,6 +844,7 @@ static void usingGpioMemCheck (const char *what) fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ; exit (EXIT_FAILURE) ; } + } @@ -756,11 +895,11 @@ int piGpioLayout (void) if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; - + +#ifdef DONT_CARE_ANYMORE // Start by looking for the Architecture to make sure we're really running // on a Pi. I'm getting fed-up with people whinging at me because // they can't get it to work on weirdFruitPi boards... - while (fgets (line, 120, cpuFd) != NULL) if (strncmp (line, "Hardware", 8) == 0) break ; @@ -779,7 +918,6 @@ 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) ; @@ -790,7 +928,6 @@ 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 @@ -811,7 +948,8 @@ int piGpioLayout (void) // 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. Or the next. - +#endif + // Isolate the Revision line rewind (cpuFd) ; @@ -1022,6 +1160,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) bMem = (revision & (0x07 << 20)) >> 20 ; bWarranty = (revision & (0x03 << 24)) != 0 ; + // Ref: https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes *model = bType ; *rev = bRev ; *mem = bMem ; @@ -1087,6 +1226,8 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } } + + RaspberryPiModel = *model; } @@ -1122,23 +1263,73 @@ int physPinToGpio (int physPin) * Set the PAD driver value ********************************************************************************* */ +void setPadDrivePin (int pin, int value) { + if (PI_MODEL_5 != RaspberryPiModel) return; + if (pin < 0 || pin > GetMaxPin()) return ; + + uint32_t wrVal; + value = value & 3; // 0-3 supported + wrVal = (value << 4); //Drive strength 0-3 + pads[1+pin] = (pads[1+pin] & RP1_INV_PAD_DRIVE_MASK) | wrVal; + if (wiringPiDebug) { + printf ("setPadDrivePin: pin: %d, value: %d (%08X)\n", pin, value, pads[1+pin]) ; + } +} + void setPadDrive (int group, int value) { - uint32_t wrVal ; + uint32_t wrVal, rdVal; if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { - if ((group < 0) || (group > 2)) - return ; + value = value & 7; // 0-7 supported + if (PI_MODEL_5 == RaspberryPiModel) { + if (-1==group) { + printf ("Pad register:\n"); + for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { + unsigned int drive = (pads[1+pin] & RP1_PAD_DRIVE_MASK)>>4; + printf (" Pin %2d: 0x%08X drive: 0x%d = %2dmA\n", pin, pads[1+pin], drive, 0==drive ? 2 : drive*4) ; + } + } + if (group !=0) { // only GPIO range @RP1 + return ; + } + switch(value) { + default: + /* bcm*/ // RP1 + case 0: /* 2mA*/ value=0; break; // 2mA + case 1: /* 4mA*/ + case 2: /* 6mA*/ value=1; break; // 4mA + case 3: /* 8mA*/ + case 4: /*10mA*/ value=2; break; // 8mA + case 5: /*12mA*/ + case 6: /*14mA*/ + case 7: /*16mA*/ value=3; break; //12mA + } + wrVal = (value << 4); //Drive strength 0-3 + //set for all pins even when it's avaiable for each pin separately + for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { + pads[1+pin] = (pads[1+pin] & RP1_INV_PAD_DRIVE_MASK) | wrVal; + } + rdVal = pads[1+17]; // only pin 17 readback, for logging + } else { + if (-1==group) { + printf ("Pad register: Group 0: 0x%08X, Group 1: 0x%08X, Group 2: 0x%08X\n", *(pads + 0 + 11), *(pads + 1 + 11), *(pads + 2 + 11)) ; + } + + if ((group < 0) || (group > 2)) + return ; - wrVal = BCM_PASSWORD | 0x18 | (value & 7) ; - *(pads + group + 11) = wrVal ; + wrVal = BCM_PASSWORD | 0x18 | value; //Drive strength 0-7 + *(pads + group + 11) = wrVal ; + rdVal = *(pads + group + 11); + } if (wiringPiDebug) { printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ; - printf ("Read : %08X\n", *(pads + group + 11)) ; + printf ("Read : %08X\n", rdVal) ; } } } @@ -1164,11 +1355,48 @@ int getAlt (int pin) else if (wiringPiMode != WPI_MODE_GPIO) return 0 ; - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; + if (PI_MODEL_5 == RaspberryPiModel) { + alt = (gpio[2*pin+1] & RP1_FSEL_NONE_HW); //0-4 function + + /* + BCM: + 000b = GPIO Pin 9 is an input + 001b = GPIO Pin 9 is an output + 100b = GPIO Pin 9 takes alternate function 0 + 101b = GPIO Pin 9 takes alternate function 1 + 110b = GPIO Pin 9 takes alternate function 2 + 111b = GPIO Pin 9 takes alternate function 3 + 011b = GPIO Pin 9 takes alternate function 4 + 010b = GPIO Pin 9 takes alternate function 5 + RP1: + 8 = alternate function 6 + 9 = alternate function 7 + 10 = alternate function 8 + 11 = alternate function 9 + */ + switch(alt) { + case 0: return 4; + case 1: return 5; + case 2: return 6; + case 3: return 7; + case 4: return 3; + case RP1_FSEL_GPIO: { + unsigned int outputmask = gpio[2*pin] & 0x3000; //Bit13-OETOPAD + Bit12-OEFROMPERI + return (outputmask==0x3000) ? 1 : 0; //1=OUT 0=IN + } + case 6: return 8; + case 7: return 9; + case 8: return 10; + case 9: return 11; + default:return alt; + } - alt = (*(gpio + fSel) >> shift) & 7 ; + } else { + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + alt = (*(gpio + fSel) >> shift) & 7 ; + } return alt ; } @@ -1183,6 +1411,7 @@ void pwmSetMode (int mode) { if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { + FailOnModel5(); if (mode == PWM_MODE_MS) *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ; else @@ -1200,6 +1429,7 @@ void pwmSetMode (int mode) void pwmSetRange (unsigned int range) { + FailOnModel5(); if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) { *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; @@ -1220,6 +1450,7 @@ void pwmSetClock (int divisor) { uint32_t pwm_control ; + FailOnModel5(); if (piGpioBase == GPIO_PERI_BASE_2711) { divisor = 540*divisor/192; @@ -1271,6 +1502,7 @@ void gpioClockSet (int pin, int freq) { int divi, divr, divf ; + FailOnModel5(); pin &= 63 ; /**/ if (wiringPiMode == WPI_MODE_PINS) @@ -1402,6 +1634,7 @@ void pinModeAlt (int pin, int mode) { int fSel, shift ; + RETURN_ON_MODEL5 setupCheck ("pinModeAlt") ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin @@ -1413,10 +1646,25 @@ void pinModeAlt (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; - fSel = gpioToGPFSEL [pin] ; - shift = gpioToShift [pin] ; + if (PI_MODEL_5 == RaspberryPiModel) { + + //confusion! diffrent to to BCM! this is taking directly the value for the register + /* + "alt0" 0b100 + "alt1" 0b101 + "alt2" 0b110 + "alt3" 0b111 + "alt4" 0b011 + "alt5" 0b010 + */ + gpio[2*pin+1] = (mode & RP1_FSEL_NONE_HW) | RP1_DEBOUNCE_DEFAULT; //0-4 function, 5-11 debounce time + } else { + fSel = gpioToGPFSEL [pin] ; + shift = gpioToShift [pin] ; + + *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; + } - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ; } } @@ -1427,12 +1675,21 @@ void pinModeAlt (int pin, int mode) ********************************************************************************* */ +//Default: rp1_set_pad(pin, 0, 1, 0, 1, 1, 1, 0); +void rp1_set_pad(int pin, int slewfast, int schmitt, int pulldown, int pullup, int drive, int inputenable, int outputdisable) { + + pads[1+pin] = (slewfast != 0) | ((schmitt != 0) << 1) | ((pulldown != 0) << 2) | ((pullup != 0) << 3) | ((drive & 0x3) << 4) | ((inputenable != 0) << 6) | ((outputdisable != 0) << 7); +} + void pinMode (int pin, int mode) { int fSel, shift, alt ; struct wiringPiNodeStruct *node = wiringPiNodes ; int origPin = pin ; + if (wiringPiDebug) + printf ("pinMode: pin:%d mode:%d\n", pin, mode) ; + setupCheck ("pinMode") ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin @@ -1444,27 +1701,43 @@ void pinMode (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; + if (wiringPiDebug) + printf ("pinMode: bcm pin:%d mode:%d\n", pin, mode) ; + softPwmStop (origPin) ; softToneStop (origPin) ; fSel = gpioToGPFSEL [pin] ; shift = gpioToShift [pin] ; - /**/ if (mode == INPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input - else if (mode == OUTPUT) - *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; - else if (mode == SOFT_PWM_OUTPUT) + if (mode == INPUT) { + if (PI_MODEL_5 == RaspberryPiModel) { + pads[1+pin] = (pin<=8) ? RP1_PAD_DEFAULT_0TO8 : RP1_PAD_DEFAULT_FROM9; + gpio[2*pin+1] = RP1_FSEL_GPIO | RP1_DEBOUNCE_DEFAULT; // GPIO + rio[RP1_RIO_OE + RP1_CLR_OFFSET] = 1<>4); - int pullshift = (pin & 0xf) << 1; - unsigned int pullbits; - unsigned int pull; - - switch (pud) - { - case PUD_OFF: pull = 0; break; - case PUD_UP: pull = 1; break; - case PUD_DOWN: pull = 2; break; + if (PI_MODEL_5 == RaspberryPiModel) { + unsigned int pullbits = pads[1+pin] & RP1_INV_PUD_MASK; // remove bits + switch (pud){ + case PUD_OFF: pads[1+pin] = pullbits; break; + case PUD_UP: pads[1+pin] = pullbits | RP1_PUD_UP; break; + case PUD_DOWN: pads[1+pin] = pullbits | RP1_PUD_DOWN; break; default: return ; /* An illegal value */ } + } else { + if (piGpioPupOffset == GPPUPPDN0) + { + // Pi 4B pull up/down method + int pullreg = GPPUPPDN0 + (pin>>4); + int pullshift = (pin & 0xf) << 1; + unsigned int pullbits; + unsigned int pull; + + switch (pud) + { + case PUD_OFF: pull = 0; break; + case PUD_UP: pull = 1; break; + case PUD_DOWN: pull = 2; break; + default: return ; /* An illegal value */ + } + + pullbits = *(gpio + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio + pullreg) = pullbits; + } + else + { + // legacy pull up/down method + *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; - pullbits = *(gpio + pullreg); - pullbits &= ~(3 << pullshift); - pullbits |= (pull << pullshift); - *(gpio + pullreg) = pullbits; - } - else - { - // legacy pull up/down method - *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; - - *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + } } } else // Extension module @@ -1591,10 +1876,18 @@ int digitalRead (int pin) else if (wiringPiMode != WPI_MODE_GPIO) return LOW ; - if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) - return HIGH ; - else - return LOW ; + if (PI_MODEL_5 == RaspberryPiModel) { + switch(gpio[2*pin] & RP1_STATUS_LEVEL_MASK) { + default: // 11 or 00 not allowed, give LOW! + case RP1_STATUS_LEVEL_LOW: return LOW ; + case RP1_STATUS_LEVEL_HIGH: return HIGH ; + } + } else { + if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) + return HIGH ; + else + return LOW ; + } } else { @@ -1640,12 +1933,12 @@ void digitalWrite (int pin, int value) { /**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode { - if (sysFds [pin] != -1) + if (sysFds [pin] != -1) { - if (value == LOW) - write (sysFds [pin], "0\n", 2) ; - else - write (sysFds [pin], "1\n", 2) ; + if (value == LOW) + write (sysFds [pin], "0\n", 2) ; + else + write (sysFds [pin], "1\n", 2) ; } return ; } @@ -1655,11 +1948,20 @@ void digitalWrite (int pin, int value) pin = physToGpio [pin] ; else if (wiringPiMode != WPI_MODE_GPIO) return ; - - if (value == LOW) - *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ; - else - *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ; + if (PI_MODEL_5 == RaspberryPiModel) { + if (value == LOW) { + //printf("Set pin %d >>0x%08x<< to low\n", pin, 1<>0x%08x<< to high\n", pin, 1< 63)) - return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ; + if (pin < 0 || pin > maxpin) + return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-%d (%d)\n", maxpin, pin) ; /**/ if (wiringPiMode == WPI_MODE_UNINITIALISED) return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ; @@ -2057,8 +2369,9 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) if (sysFds [bcmGpioPin] == -1) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ; - if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0) + 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)) ; } @@ -2240,6 +2553,19 @@ void wiringPiVersion (int *major, int *minor) } +int wiringPiUserLevelAccess(void) +{ + struct stat statBuf ; + const char* gpiomemModule = gpiomem_BCM; + + if (PI_MODEL_5 == RaspberryPiModel) { + gpiomemModule = gpiomem_RP1; + } + + return stat(gpiomemModule, &statBuf) == 0 ? 1 : 0; +} + + /* * wiringPiSetup: * Must be called once at the start of your program execution. @@ -2300,10 +2626,14 @@ int wiringPiSetup (void) switch (model) { - case PI_MODEL_A: case PI_MODEL_B: - case PI_MODEL_AP: case PI_MODEL_BP: - case PI_ALPHA: case PI_MODEL_CM: - case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: + case PI_MODEL_A: + case PI_MODEL_B: + case PI_MODEL_AP: + case PI_MODEL_BP: + case PI_ALPHA: + case PI_MODEL_CM: + case PI_MODEL_ZERO: + case PI_MODEL_ZERO_W: piGpioBase = GPIO_PERI_BASE_OLD ; piGpioPupOffset = GPPUD ; break ; @@ -2315,6 +2645,11 @@ int wiringPiSetup (void) piGpioPupOffset = GPPUPPDN0 ; break ; + case PI_MODEL_5: + piGpioBase = GPIO_PERI_BASE_2712 ; + piGpioPupOffset = 0 ; + break ; + default: piGpioBase = GPIO_PERI_BASE_2835 ; piGpioPupOffset = GPPUD ; @@ -2326,75 +2661,131 @@ 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) + const char* gpiomemGlobal = gpiomem_global; + const char* gpiomemModule = gpiomem_BCM; + + if (PI_MODEL_5 == model) { + gpiomemGlobal = pciemem_RP1; + gpiomemModule = gpiomem_RP1; + } + + if (gpiomemGlobal==NULL || (fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) < 0) { - if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem + + if (gpiomemModule && (fd = open (gpiomemModule, 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" + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open %s or %s: %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)) ; + " Try running with sudo?\n", gpiomemGlobal, gpiomemModule, strerror (errno)) ; + } + if (wiringPiDebug) { + printf ("wiringPi: access to %s succeded\n", usingGpioMem ? gpiomemModule : gpiomemGlobal) ; } - -// Set the offsets into the memory interface. - - GPIO_PADS = piGpioBase + 0x00100000 ; - GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; - GPIO_BASE = piGpioBase + 0x00200000 ; - GPIO_TIMER = piGpioBase + 0x0000B000 ; - GPIO_PWM = piGpioBase + 0x0020C000 ; - -// Map the individual hardware components - // GPIO: + if (PI_MODEL_5 != model) { + //Set the offsets into the memory interface. - gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; - if (gpio == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; - -// PWM - - pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; - if (pwm == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; - -// Clock control (needed for PWM) + GPIO_PADS = piGpioBase + 0x00100000 ; + GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; + GPIO_BASE = piGpioBase + 0x00200000 ; + GPIO_TIMER = piGpioBase + 0x0000B000 ; + GPIO_PWM = piGpioBase + 0x0020C000 ; + GPIO_RIO = 0x00 ; - clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; - if (clk == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; - -// The drive pads - - pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; - if (pads == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; - -// The system timer - - timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; - if (timer == MAP_FAILED) - return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; - -// Set the timer to free-running, 1MHz. -// 0xF9 is 249, the timer divide is base clock / (divide+1) -// so base clock is 250MHz / 250 = 1MHz. - - *(timer + TIMER_CONTROL) = 0x0000280 ; - *(timer + TIMER_PRE_DIV) = 0x00000F9 ; - timerIrqRaw = timer + TIMER_IRQ_RAW ; - -// Export the base addresses for any external software that might need them +// Map the individual hardware components - _wiringPiGpio = gpio ; - _wiringPiPwm = pwm ; - _wiringPiClk = clk ; - _wiringPiPads = pads ; - _wiringPiTimer = timer ; + // GPIO: + base = NULL; + gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; + if (gpio == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; + + // PWM + + pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; + if (pwm == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; + + // Clock control (needed for PWM) + + clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; + if (clk == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; + + // The drive pads + + pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; + if (pads == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; + + // The system timer + + timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; + if (timer == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; + + // Set the timer to free-running, 1MHz. + // 0xF9 is 249, the timer divide is base clock / (divide+1) + // so base clock is 250MHz / 250 = 1MHz. + + *(timer + TIMER_CONTROL) = 0x0000280 ; + *(timer + TIMER_PRE_DIV) = 0x00000F9 ; + timerIrqRaw = timer + TIMER_IRQ_RAW ; + + // Export the base addresses for any external software that might need them + _wiringPiBase = base ; + _wiringPiGpio = gpio ; + _wiringPiPwm = pwm ; + _wiringPiClk = clk ; + _wiringPiPads = pads ; + _wiringPiTimer = timer ; + _wiringPiRio = NULL ; + } else { + unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size; + + GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ; + GPIO_CLOCK_BASE = 0x00; + GPIO_BASE = (RP1_IO0_Addr-RP1_BASE_Addr) ; + GPIO_TIMER = 0x00; + GPIO_PWM = RP1_PWM0_Addr-RP1_BASE_Addr; + GPIO_RIO = (RP1_SYS_RIO0_Addr-RP1_IO0_Addr) ; + + //map hole RP1 memory block from beginning, + base = (unsigned int *)mmap(0, MMAP_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x00000000) ; + if (base == MAP_FAILED) + return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ; + if (usingGpioMem) { + gpio = base; // RP1 start adress of map memory for gpio (same as module memory) + } else { + gpio = &base[GPIO_BASE/4];// RP1 start adress of map memory for gpio + } + pads = &gpio[GPIO_PADS/4]; // RP1 start adress of map memory for pads + rio = &gpio[GPIO_RIO/4]; // RP1 start adress of map memory for rio + GPIO_PADS += GPIO_BASE; + GPIO_RIO += GPIO_BASE; + + // Export the base addresses for any external software that might need them + _wiringPiBase = base ; + _wiringPiGpio = gpio ; + _wiringPiPwm = NULL ; + _wiringPiClk = NULL ; + _wiringPiPads = pads ; + _wiringPiTimer = NULL ; + _wiringPiRio = rio ; + } + if (wiringPiDebug) { + printf ("wiringPi: memory map gpio 0x%x %s\n", GPIO_BASE , _wiringPiGpio ? "valid" : "invalid"); + printf ("wiringPi: memory map pads 0x%x %s\n", GPIO_PADS , _wiringPiPads ? "valid" : "invalid"); + printf ("wiringPi: memory map rio 0x%x %s\n", GPIO_RIO , _wiringPiRio ? "valid" : "invalid"); + printf ("wiringPi: memory map pwm 0x%x %s\n", GPIO_PWM , _wiringPiPwm ? "valid" : "invalid"); + printf ("wiringPi: memory map clk 0x%x %s\n", GPIO_CLOCK_BASE, _wiringPiClk ? "valid" : "invalid"); + printf ("wiringPi: memory map timer 0x%x %s\n", GPIO_TIMER,_wiringPiTimer ? "valid" : "invalid"); + } initialiseEpoch () ; @@ -2457,7 +2848,6 @@ int wiringPiSetupPhys (void) int wiringPiSetupSys (void) { - int pin ; char fName [128] ; if (wiringPiSetuped) @@ -2474,6 +2864,9 @@ int wiringPiSetupSys (void) if (wiringPiDebug) printf ("wiringPi: wiringPiSetupSys called\n") ; + int model, rev, mem, maker, overVolted ; + piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + if (piGpioLayout () == 1) { pinToGpio = pinToGpioR1 ; @@ -2488,10 +2881,13 @@ int wiringPiSetupSys (void) // Open and scan the directory, looking for exported GPIOs, and pre-open // the 'value' interface to speed things up for later - for (pin = 0 ; pin < 64 ; ++pin) + for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; - sysFds [pin] = open (fName, O_RDWR) ; + int pinFS = GPIOToSysFS(pin); + if (pinFS>=0) { + sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; + sysFds [pin] = open (fName, O_RDWR) ; + } } initialiseEpoch () ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index e001d8d8..94875b2b 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -107,6 +107,8 @@ #define PI_MODEL_ZERO_2W 18 #define PI_MODEL_400 19 #define PI_MODEL_CM4 20 +#define PI_MODEL_CM4S 21 +#define PI_MODEL_5 23 #define PI_VERSION_1 0 #define PI_VERSION_1_1 1 @@ -118,7 +120,9 @@ #define PI_MAKER_EMBEST 2 #define PI_MAKER_UNKNOWN 3 -extern const char *piModelNames [21] ; + +extern const char *piModelNames [24] ; +extern const char *piProcessor [ 5] ; extern const char *piRevisionNames [16] ; extern const char *piMakerNames [16] ; extern const int piMemorySize [ 8] ; @@ -199,7 +203,10 @@ extern int wiringPiFailure (int fatal, const char *message, ...) ; extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; +extern int GPIOToSysFS(const int pin) ; + extern void wiringPiVersion (int *major, int *minor) ; +extern int wiringPiUserLevelAccess (void) ; extern int wiringPiSetup (void) ; extern int wiringPiSetupSys (void) ; extern int wiringPiSetupGpio (void) ; @@ -230,6 +237,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 int getAlt (int pin) ; extern void pwmToneWrite (int pin, int freq) ; extern void pwmSetMode (int mode) ;