diff --git a/VERSION b/VERSION index a3ec5a4..eb39e53 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2 +3.3 diff --git a/examples/speed.c b/examples/speed.c index 2cd2fe1..19b2b06 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -84,12 +84,19 @@ int main (void) pinMode (11, OUTPUT) ; speedTest (11, FAST_COUNT) ; -// Switch to SYS mode: +// Switch to SYS mode: -> character device ABI - system ("/usr/local/bin/gpio export 17 out") ; printf ("\n/sys/class/gpio method: (%8d iterations)\n", SLOW_COUNT) ; wiringPiSetupSys () ; speedTest (17, SLOW_COUNT) ; +// character device ABI + + printf ("\ncharacter device ABI method: (%8d iterations)\n", SLOW_COUNT) ; + wiringPiSetupGpioDevice () ; + pinMode (17, OUTPUT) ; + speedTest (17, SLOW_COUNT) ; + + return 0 ; } diff --git a/gpio/gpio.1 b/gpio/gpio.1 index b1be603..7b71596 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -29,13 +29,6 @@ gpio \- Command-line access to Raspberry Pi's GPIO .B readall .PP .B gpio -.B unexportall/exports -.PP -.B gpio -.B export/edge/unexport -.B ... -.PP -.B gpio .B wfi .B ... .PP @@ -77,10 +70,6 @@ somewhat slow control of the GPIO pins. It can also control the IO's on the PiFace IO board and load the SPI and I2C kernel modules if required. -Additionally, it can be used to set the exports in the \fI/sys/class/gpio\fR -system directory to allow subsequent programs to use the \fR/sys/class/gpio\fR -interface without needing to be run as root. - .SH OPTIONS .TP @@ -90,15 +79,14 @@ Output the current version including the board revision of the Raspberry Pi. .TP .B \-g Use the BCM_GPIO pins numbers rather than wiringPi pin numbers. -\fINote:\fR The BCM_GPIO pin numbers are always used with the -export and edge commands. +.\" \fINote:\fR The BCM_GPIO pin numbers are always used with character device ABI. .TP .B \-1 Use the physical pin numbers rather than wiringPi pin numbers. \fINote:\fR that this applies to the P1 connector only. It is not possible to use pins on the Revision 2 P5 connector this way, and as with \-g the -BCM_GPIO pin numbers are always used with the export and edge commands. +.\" BCM_GPIO pin numbers are always used with character device ABI. .TP .B \-x extension @@ -190,47 +178,6 @@ pull-up, pull-down or tristate (off) controls. The ALT modes can also be set using \fIalt0\fR, \fIalt1\fR, ... \fIalt5\fR. -.TP -.B unexportall -Un-Export all the GPIO pins in the /sys/class/gpio directory. - -.TP -.B exports -Print a list (if any) of all the exported GPIO pins and their current values. - -.TP -.B export -Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the -mode command above however only \fIin\fR, \fIout\fR, \fIhigh\fR and -\fRlow\fR are supported at this time. Note that the pin number is the -\fBBCM_GPIO\fR number and not the wiringPi number. The \fIhigh\fR and -\fIlow\fR commands pre-set the output value at the same time as the -export to output mode. - -Once a GPIO pin has been exported, the \fBgpio\fR program changes the -ownership of the \fI/sys/class/gpio/gpioX/value\fR and if present in -later kernels, the \fI/sys/class/gpio/gpioX/edge\fR pseudo files to -that of the user running the \fBgpio\fR program. This means that you -can have a small script of gpio exports to setup the gpio pins as your -program requires without the need to run anything as root, or with the -sudo command. - -.TP -.B edge -This exports a GPIO pin in the \fI/sys/class/gpio\fR directory, set -the direction to input and set the edge interrupt method to \fInone\fR, -\fIrising\fR, \fIfalling\fR or \fIboth\fR. Use like the export command -above and note that \fBBCM_GPIO\fR pin number is used not not wiringPi pin -numbering. - -Like the export commands above, ownership is set to that of the -calling user, allowing subsequent access from user programs without -requiring root/sudo. - -.TP -.B unexport -Un-Export a GPIO pin in the /sys/class/gpio directory. - .TP .B wfi This set the given pin to the supplied interrupt mode: rising, falling @@ -299,18 +246,10 @@ gpio mode 1 pwm # Set pin 1 to PWM mode .PP gpio pwm 1 512 # Set pin 1 to PWM value 512 - half brightness .PP -gpio export 17 out # Set GPIO Pin 17 to output -.PP -gpio export 0 in # Set GPIO Pin 0 (SDA0) to input. -.PP gpio -g read 0 # Read GPIO Pin 0 (SDA0) .SH "NOTES" -When using the \fIexport\fR, \fIedge\fR or \fIunexport\fR commands, the -pin numbers are \fBalways\fR native BCM_GPIO numbers and never wiringPi -pin numbers. - As of kernels 4.1.7, a user-level GPIO access mechanism is available, however wiringPi will not use this by default - because at this time there appears to be issues when trying to program the PWM or clock output @@ -326,13 +265,13 @@ in future releases once the /dev/gpiomem interface is fully operational. .SH "SEE ALSO" .LP -WiringPi's home page +WiringPi's development .IP https://github.com/WiringPi/WiringPi/ .SH AUTHOR -Gordon Henderson +Gordon Henderson and contributors .SH "REPORTING BUGS" @@ -340,7 +279,8 @@ Please report bugs to https://github.com/WiringPi/WiringPi/issues .SH COPYRIGHT -Copyright (c) 2012-2018 Gordon Henderson +Copyright (c) 2012-2024 Gordon Henderson and contributors +.br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/gpio/gpio.c b/gpio/gpio.c index 84b3bb0..af853ab 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -72,8 +72,8 @@ char *usage = "Usage: gpio -v\n" " gpio ...\n" " gpio \n" " gpio readall\n" - " gpio unexportall/exports\n" - " gpio export/edge/unexport ...\n" +// " gpio unexportall/exports\n" +// " gpio export/edge/unexport ...\n" " gpio wfi \n" " gpio drive \n" " gpio pwm-bal/pwm-ms \n" @@ -89,15 +89,6 @@ 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: @@ -432,160 +423,23 @@ static void doI2Cdetect (UNU int argc, char *argv []) } +void SYSFS_DEPRECATED(const char *progName) { + fprintf(stderr, "%s: GPIO Sysfs Interface for Userspace is deprecated (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt).\n Function is now useless and empty.\n\n", progName); +} + /* - * doExports: + * doExports: -> deprecated, removed * List all GPIO exports ********************************************************************************* */ -static void doExports (UNU int argc, UNU char *argv []) -{ - int fd ; - int pin, l, first ; - char fName [128] ; - char buf [16] ; - - for (first = 0, pin = 0 ; pin < 64 ; ++pin) // Crude, but effective - { - -// Try to read the direction - 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 ; - - if (first == 0) - { - ++first ; - printf ("GPIO Pins exported:\n") ; - } - - if(pinFS==pin) { - printf ("%4d: ", pin) ; - } else { - printf ("%4d (%4d): ", pin, pinFS) ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf ("%-3s", buf) ; - - close (fd) ; - -// Try to Read the value - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - if ((fd = open (fName, O_RDONLY)) == -1) - { - printf ("No Value file (huh?)\n") ; - continue ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf (" %s", buf) ; - -// Read any edge trigger file - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - if ((fd = open (fName, O_RDONLY)) == -1) - { - printf ("\n") ; - continue ; - } - - if ((l = read (fd, buf, 16)) == 0) - sprintf (buf, "%s", "?") ; - - buf [l] = 0 ; - if ((buf [strlen (buf) - 1]) == '\n') - buf [strlen (buf) - 1] = 0 ; - - printf (" %-8s\n", buf) ; - - close (fd) ; - } -} - - /* - * doExport: + * doExport: -> deprecated, removed * gpio export pin mode * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doExport (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - char *mode ; - char fName [128] ; - - if (argc != 4) - { - fprintf (stderr, "Usage: %s export pin mode\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - mode = argv [3] ; - - if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; - 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)) ; - exit (1) ; - } - - /**/ if ((strcasecmp (mode, "in") == 0) || (strcasecmp (mode, "input") == 0)) - fprintf (fd, "in\n") ; - else if ((strcasecmp (mode, "out") == 0) || (strcasecmp (mode, "output") == 0)) - fprintf (fd, "out\n") ; - else if ((strcasecmp (mode, "high") == 0) || (strcasecmp (mode, "up") == 0)) - fprintf (fd, "high\n") ; - else if ((strcasecmp (mode, "low") == 0) || (strcasecmp (mode, "down") == 0)) - fprintf (fd, "low\n") ; - else - { - fprintf (stderr, "%s: Invalid mode: %s. Should be in, out, high or low\n", argv [1], mode) ; - exit (1) ; - } - - fclose (fd) ; - -// Change ownership so the current user can actually use it - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - changeOwner (argv [0], fName) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - changeOwner (argv [0], fName) ; - -} - /* * doWfi: @@ -669,142 +523,29 @@ void doWfi (int argc, char *argv []) } - /* - * doEdge: + * doEdge: -> deprecated, removed * gpio edge pin mode * Easy access to changing the edge trigger on a GPIO pin * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doEdge (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - char *mode ; - char fName [128] ; - - if (argc != 4) - { - fprintf (stderr, "Usage: %s edge pin mode\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - mode = argv [3] ; - -// Export the pin and set direction to input - - if ((fd = fopen ("/sys/class/gpio/export", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface: %s\n", argv [0], strerror (errno)) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; - - 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)) ; - exit (1) ; - } - - fprintf (fd, "in\n") ; - fclose (fd) ; - - 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)) ; - exit (1) ; - } - - /**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ; - else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ; - else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ; - else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ; - else - { - fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ; - exit (1) ; - } - -// Change ownership of the value and edge files, so the current user can actually use it! - - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - changeOwner (argv [0], fName) ; - - sprintf (fName, "/sys/class/gpio/gpio%d/edge", pinFS) ; - changeOwner (argv [0], fName) ; - - fclose (fd) ; -} - - /* - * doUnexport: + * doUnexport: -> deprecated, removed * gpio unexport pin * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doUnexport (int argc, char *argv []) -{ - FILE *fd ; - int pin ; - - if (argc != 3) - { - fprintf (stderr, "Usage: %s unexport pin\n", argv [0]) ; - exit (1) ; - } - - pin = atoi (argv [2]) ; - int pinFS = GPIOToSysFS_ExitonFail(pin, argv [0]); - - if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL) - { - fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ; - exit (1) ; - } - - fprintf (fd, "%d\n", pinFS) ; - fclose (fd) ; -} - - /* - * doUnexportAll: + * doUnexportAll: -> deprecated, removed * gpio unexportall * Un-Export all the GPIO pins. * This uses the /sys/class/gpio device interface. ********************************************************************************* */ -void doUnexportall (char *progName) -{ - FILE *fd ; - int pin ; - - for (pin = 0 ; pin < 63 ; ++pin) - { - 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) ; - } - } -} - /* * doReset: @@ -1402,7 +1143,7 @@ static void doVersion (char *argv []) piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ; // Check for device tree - printf ("System details:\n") ; + printf ("\nSystem details:\n") ; if (stat ("/proc/device-tree", &statBuf) == 0) { // We're on a devtree system ... printf (" * Device tree present.\n") ; } @@ -1436,9 +1177,13 @@ static void doVersion (char *argv []) } else { printf (" * Does not support basic user-level GPIO access via /dev/gpiomem.\n") ; if(0==bGlobalAccess) { - printf (" * root or sudo may be required for GPIO access.\n") ; + printf (" * root or sudo may be required for direct GPIO access.\n") ; } } + if (wiringPiGpioDeviceGetFd()>0) { + printf (" * Supports basic user-level GPIO access via /dev/gpiochip (slow).\n") ; + } + } @@ -1524,13 +1269,13 @@ int main (int argc, char *argv []) exit (EXIT_FAILURE) ; } -// Initial test for /sys/class/gpio operations: +// Initial test for /sys/class/gpio operations: - -> deprecated, empty but still there - /**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; } - else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argv [0]) ; return 0 ; } + /**/ if (strcasecmp (argv [1], "exports" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "export" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "edge" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "unexport" ) == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } + else if (strcasecmp (argv [1], "unexportall") == 0) { SYSFS_DEPRECATED(argv[0]); return 0 ; } // Check for load command: diff --git a/version.h b/version.h index bbf3ef7..6f3b26e 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.2" +#define VERSION "3.3" #define VERSION_MAJOR 3 -#define VERSION_MINOR 2 +#define VERSION_MINOR 3 diff --git a/wiringPi/test/wiringpi_test1_device.c b/wiringPi/test/wiringpi_test1_device.c new file mode 100644 index 0000000..189dd9f --- /dev/null +++ b/wiringPi/test/wiringpi_test1_device.c @@ -0,0 +1,83 @@ +// WiringPi test program: Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi + +#include +#include +#include +#include +#include +#include +#include + + +const int GPIO = 19; +const int GPIOIN = 26; +const int ToggleValue = 4; + +void CheckGPIO(int out) { + int in = digitalRead(GPIOIN); + int read = digitalRead(GPIO); + + int pass = 0; + if (out==in && in==read) { + pass = 1; + } + printf("GPIO%d = %d (GPIO%d = %d) -> %s\n", GPIOIN, in, GPIO, read, pass ? "passed":"failed" ); +} + +void digitalWriteEx(int pin, int mode) { + digitalWrite(pin, mode); + printf("out = %d ", mode); + delayMicroseconds(5000); + CheckGPIO(mode); +} + +void pullUpDnControlEx (int pin ,int mode) { + pullUpDnControl (pin, mode); + int out = mode==PUD_UP ? 1:0; + printf("in = %4s ", mode==PUD_UP ? "up":"down"); + delayMicroseconds(5000); + CheckGPIO(out); +} + +int main (void) { + + printf("WiringPi GPIO test program 1 (using GPIO%d (output) and GPIO%d (input) via sys)\n", GPIO, GPIOIN); + printf(" testing digitalWrite, digitalRead and pullUpDnControl\n"); + + if (wiringPiSetupSys() == -1) { + printf("wiringPiSetupGpioDevice failed\n\n"); + exit(EXIT_FAILURE); + } + pinMode(GPIOIN, INPUT); + pinMode(GPIO, OUTPUT); + + printf("toggle %d times ...\n", ToggleValue); + for (int loop=1; loop +#include +#include +#include +#include +#include +#include + + +const int GPIO = 19; +const int GPIOIN = 26; +const int ToggleValue = 4; + +void CheckGPIO(int out) { + int in = digitalRead(GPIOIN); + int read = digitalRead(GPIO); + + int pass = 0; + if (out==in && in==read) { + pass = 1; + } + printf("GPIO%d = %d (GPIO%d = %d) -> %s\n", GPIOIN, in, GPIO, read, pass ? "passed":"failed" ); +} + +void digitalWriteEx(int pin, int mode) { + digitalWrite(pin, mode); + printf("out = %d ", mode); + delayMicroseconds(5000); + CheckGPIO(mode); +} + +void pullUpDnControlEx (int pin ,int mode) { + pullUpDnControl (pin, mode); + int out = mode==PUD_UP ? 1:0; + printf("in = %4s ", mode==PUD_UP ? "up":"down"); + delayMicroseconds(5000); + CheckGPIO(out); +} + +int main (void) { + + printf("WiringPi GPIO test program 2 (using GPIO%d (output) and GPIO%d (input) via sys)\n", GPIO, GPIOIN); + printf(" testing pullUpDnControl and pinMode PM_OFF\n"); + + if (wiringPiSetupSys() == -1) { + printf("wiringPiSetupSys failed\n\n"); + exit(EXIT_FAILURE); + } + pinMode(GPIOIN, INPUT); + pinMode(GPIO, OUTPUT); + + printf("\nTest output\n"); + digitalWriteEx(GPIO, HIGH); + delayMicroseconds(600000); + digitalWriteEx(GPIO, LOW); + delayMicroseconds(600000); + + printf("\nTest output off with pull up\n"); + pinMode(GPIO, OUTPUT); + digitalWriteEx(GPIO, LOW); + pullUpDnControl (GPIO, PUD_UP); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(HIGH); + delayMicroseconds(600000); + + printf("\nTest output off with pull down\n"); + pullUpDnControl (GPIO, PUD_DOWN); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(LOW); + delayMicroseconds(600000); + + return(EXIT_SUCCESS); +} diff --git a/wiringPi/test/wiringpi_test3_device.c b/wiringPi/test/wiringpi_test3_device.c new file mode 100644 index 0000000..362ae68 --- /dev/null +++ b/wiringPi/test/wiringpi_test3_device.c @@ -0,0 +1,80 @@ +// WiringPi test program: Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test3_device.c -o wiringpi_test3_device -lwiringPi + +#include +#include +#include +#include +#include +#include +#include + + +const int GPIO = 24; //BCM 19 +const int GPIOIN = 25; //BCM 26; +const int ToggleValue = 4; + +void CheckGPIO(int out) { + int in = digitalRead(GPIOIN); + int read = digitalRead(GPIO); + + int pass = 0; + if (out==in && in==read) { + pass = 1; + } + printf("GPIO%d = %d (GPIO%d = %d) -> %s\n", GPIOIN, in, GPIO, read, pass ? "passed":"failed" ); +} + +void digitalWriteEx(int pin, int mode) { + digitalWrite(pin, mode); + printf("out = %d ", mode); + delayMicroseconds(5000); + CheckGPIO(mode); +} + +void pullUpDnControlEx (int pin ,int mode) { + pullUpDnControl (pin, mode); + int out = mode==PUD_UP ? 1:0; + printf("in = %4s ", mode==PUD_UP ? "up":"down"); + delayMicroseconds(5000); + CheckGPIO(out); +} + +int main (void) { + + printf("WiringPi GPIO test program 2 (using WiringPi GPIO%d (output) and GPIO%d (input) via GPIO device)\n", GPIO, GPIOIN); + printf(" testing pullUpDnControl and pinMode PM_OFF\n"); + + if (wiringPiSetupGpioDevice(WPI_PIN_WPI) == -1) { + printf("wiringPiSetupGpioDevice failed\n\n"); + exit(EXIT_FAILURE); + } + pinMode(GPIOIN, INPUT); + pinMode(GPIO, OUTPUT); + + printf("\nTest output\n"); + digitalWriteEx(GPIO, HIGH); + delayMicroseconds(600000); + digitalWriteEx(GPIO, LOW); + delayMicroseconds(600000); + + printf("\nTest output off with pull up\n"); + pinMode(GPIO, OUTPUT); + digitalWriteEx(GPIO, LOW); + pullUpDnControl (GPIO, PUD_UP); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(HIGH); + delayMicroseconds(600000); + + printf("\nTest output off with pull down\n"); + pullUpDnControl (GPIO, PUD_DOWN); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(LOW); + delayMicroseconds(600000); + + return(EXIT_SUCCESS); +} diff --git a/wiringPi/test/wiringpi_test4_device.c b/wiringPi/test/wiringpi_test4_device.c new file mode 100644 index 0000000..f336212 --- /dev/null +++ b/wiringPi/test/wiringpi_test4_device.c @@ -0,0 +1,80 @@ +// WiringPi test program: Kernel char device interface / sysfs successor +// Compile: gcc -Wall wiringpi_test4_device.c -o wiringpi_test4_device -lwiringPi + +#include +#include +#include +#include +#include +#include +#include + + +const int GPIO = 35; //BCM 19 +const int GPIOIN = 37; //BCM 26; +const int ToggleValue = 4; + +void CheckGPIO(int out) { + int in = digitalRead(GPIOIN); + int read = digitalRead(GPIO); + + int pass = 0; + if (out==in && in==read) { + pass = 1; + } + printf("GPIO%d = %d (GPIO%d = %d) -> %s\n", GPIOIN, in, GPIO, read, pass ? "passed":"failed" ); +} + +void digitalWriteEx(int pin, int mode) { + digitalWrite(pin, mode); + printf("out = %d ", mode); + delayMicroseconds(5000); + CheckGPIO(mode); +} + +void pullUpDnControlEx (int pin ,int mode) { + pullUpDnControl (pin, mode); + int out = mode==PUD_UP ? 1:0; + printf("in = %4s ", mode==PUD_UP ? "up":"down"); + delayMicroseconds(5000); + CheckGPIO(out); +} + +int main (void) { + + printf("WiringPi GPIO test program 2 (using physical GPIO%d (output) and GPIO%d (input) via GPIO device)\n", GPIO, GPIOIN); + printf(" testing pullUpDnControl and pinMode PM_OFF\n"); + + if (wiringPiSetupGpioDevice(WPI_PIN_PHYS) == -1) { + printf("wiringPiSetupGpioDevice failed\n\n"); + exit(EXIT_FAILURE); + } + pinMode(GPIOIN, INPUT); + pinMode(GPIO, OUTPUT); + + printf("\nTest output\n"); + digitalWriteEx(GPIO, HIGH); + delayMicroseconds(600000); + digitalWriteEx(GPIO, LOW); + delayMicroseconds(600000); + + printf("\nTest output off with pull up\n"); + pinMode(GPIO, OUTPUT); + digitalWriteEx(GPIO, LOW); + pullUpDnControl (GPIO, PUD_UP); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(HIGH); + delayMicroseconds(600000); + + printf("\nTest output off with pull down\n"); + pullUpDnControl (GPIO, PUD_DOWN); + pinMode(GPIO, PM_OFF); + delayMicroseconds(600000); + printf("out = off "); + CheckGPIO(LOW); + delayMicroseconds(600000); + + return(EXIT_SUCCESS); +} diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index b15e260..ad81678 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -395,10 +395,23 @@ int wiringPiReturnCodes = FALSE ; int wiringPiTryGpioMem = FALSE ; -// sysFds: -// Map a file descriptor from the /sys/class/gpio/gpioX/value +static unsigned int lineFlags [64] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} ; -static int sysFds [64] = +static int lineFds [64] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +} ; + +static int isrFds [64] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -531,27 +544,13 @@ static int physToGpioR2 [64] = -1, -1, } ; -const int _5v=-1; -const int _0v=-1; -const int _3v=-1; - -int GPIOToSysFS(const int pin) { - int sysfspin = pin; +int piBoard() { if (RaspberryPiModel<0) { //need to detect pi model - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + 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; + return RaspberryPiModel<0 ? 0 : 1; } int GetMaxPin() { @@ -559,8 +558,8 @@ int GetMaxPin() { } -#define RETURN_ON_MODEL5 if (PI_MODEL_5 == RaspberryPiModel) { if (wiringPiDebug) printf("Function not supported on Pi5\n"); return; } - +#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" @@ -859,6 +858,10 @@ void piFunctionOops (const char *function, const char* suggestion, const char* u exit (EXIT_FAILURE) ; } +void ReportDeviceError(const char *function, int pin, const char *mode, int ret) { + fprintf(stderr, "wiringPi: ERROR: ioctl %s of %d (%s) returned error '%s' (%d)\n", function, pin, mode, strerror(errno), ret); +} + /* * piGpioLayout: @@ -898,10 +901,7 @@ void piGpioLayoutOops (const char *why) int piGpioLayout (void) { - if (-1==RaspberryPiLayout) { - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - } + piBoard(); return RaspberryPiLayout; } @@ -1110,6 +1110,37 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) } RaspberryPiModel = *model; + + switch (RaspberryPiModel){ + 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 ; + + case PI_MODEL_4B: + case PI_MODEL_400: + case PI_MODEL_CM4: + piGpioBase = GPIO_PERI_BASE_2711 ; + piGpioPupOffset = GPPUPPDN0 ; + break ; + + case PI_MODEL_5: + piGpioBase = GPIO_PERI_BASE_2712 ; + piGpioPupOffset = 0 ; + break ; + + default: + piGpioBase = GPIO_PERI_BASE_2835 ; + piGpioPupOffset = GPPUD ; + break ; + } } @@ -1169,16 +1200,16 @@ void setPadDrive (int group, int value) if (PI_MODEL_5 == RaspberryPiModel) { if (-1==group) { printf ("Pad register:\n"); - for (int pin=0, maxpin=GetMaxPin(); pin<=maxpin; ++pin) { + 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: + default: /* bcm*/ // RP1 case 0: /* 2mA*/ value=0; break; // 2mA case 1: /* 4mA*/ @@ -1189,9 +1220,9 @@ void setPadDrive (int group, int value) case 6: /*14mA*/ case 7: /*16mA*/ value=3; break; //12mA } - wrVal = (value << 4); //Drive strength 0-3 + 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) { + 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 @@ -1203,7 +1234,7 @@ void setPadDrive (int group, int value) if ((group < 0) || (group > 2)) return ; - wrVal = BCM_PASSWORD | 0x18 | value; //Drive strength 0-7 + wrVal = BCM_PASSWORD | 0x18 | value; //Drive strength 0-7 *(pads + group + 11) = wrVal ; rdVal = *(pads + group + 11); } @@ -1500,6 +1531,65 @@ void pinEnableED01Pi (int pin) #endif +const char DEV_GPIO_PI[] ="/dev/gpiochip0"; +const char DEV_GPIO_PI5[]="/dev/gpiochip4"; + +int wiringPiGpioDeviceGetFd() { + if (chipFd<0) { + piBoard(); + const char* gpiochip = PI_MODEL_5 == RaspberryPiModel ? DEV_GPIO_PI5 : DEV_GPIO_PI; + chipFd = open(gpiochip, O_RDWR); + if (chipFd < 0) { + fprintf(stderr, "wiringPi: ERROR: %s open ret=%d\n", gpiochip, chipFd); + } else if (wiringPiDebug) { + printf ("wiringPi: Open chip %s succeded, fd=%d\n", gpiochip, chipFd) ; + } + } + return chipFd; +} + +void releaseLine(int pin) { + + if (wiringPiDebug) + printf ("releaseLine: pin:%d\n", pin) ; + lineFlags[pin] = 0; + close(lineFds[pin]); + lineFds[pin] = -1; +} + +int requestLine(int pin, unsigned int lineRequestFlags) { + struct gpiohandle_request rq; + + if (lineFds[pin]>=0) { + if (lineRequestFlags == lineFlags[pin]) { + //already requested + return lineFds[pin]; + } else { + //different request -> rerequest + releaseLine(pin); + } + } + + //requested line + if (wiringPiGpioDeviceGetFd()<0) { + return -1; // error + } + rq.lineoffsets[0] = pin; + rq.lines = 1; + rq.flags = lineRequestFlags; + int ret = ioctl(chipFd, GPIO_GET_LINEHANDLE_IOCTL, &rq); + if (ret || rq.fd<0) { + ReportDeviceError("get line handle", pin, "RequestLine", ret); + return -1; // error + } + + lineFlags[pin] = lineRequestFlags; + lineFds[pin] = rq.fd; + if (wiringPiDebug) + printf ("requestLine succeeded: pin:%d, flags: %u, fd :%d\n", pin, lineRequestFlags, lineFds[pin]) ; + return lineFds[pin]; +} + /* ********************************************************************************* * Core Functions @@ -1530,7 +1620,7 @@ void pinModeAlt (int pin, int mode) if (PI_MODEL_5 == RaspberryPiModel) { - //confusion! diffrent to to BCM! this is taking directly the value for the register + //confusion! diffrent to to BCM! this is taking directly the value for the register /* "alt0" 0b100 "alt1" 0b101 @@ -1563,6 +1653,35 @@ void rp1_set_pad(int pin, int slewfast, int schmitt, int pulldown, int pullup, i pads[1+pin] = (slewfast != 0) | ((schmitt != 0) << 1) | ((pulldown != 0) << 2) | ((pullup != 0) << 3) | ((drive & 0x3) << 4) | ((inputenable != 0) << 6) | ((outputdisable != 0) << 7); } +void pinModeFlagsDevice (int pin, int mode, unsigned int flags) { + unsigned int lflag = flags; + if (wiringPiDebug) + printf ("pinModeFlagsDevice: pin:%d mode:%d, flags: %u\n", pin, mode, flags) ; + + lflag &= ~(GPIOHANDLE_REQUEST_INPUT | GPIOHANDLE_REQUEST_OUTPUT); + switch(mode) { + default: + fprintf(stderr, "pinMode: invalid mode request (only input und output supported)\n"); + return; + case INPUT: + lflag |= GPIOHANDLE_REQUEST_INPUT; + break; + case OUTPUT: + lflag |= GPIOHANDLE_REQUEST_OUTPUT; + break; + case PM_OFF: + pinModeFlagsDevice(pin, INPUT, 0); + releaseLine(pin); + return; + } + + requestLine(pin, lflag); +} + +void pinModeDevice (int pin, int mode) { + pinModeFlagsDevice(pin, mode, lineFlags[pin]); +} + void pinMode (int pin, int mode) { int fSel, shift, alt ; @@ -1570,18 +1689,34 @@ void pinMode (int pin, int mode) int origPin = pin ; if (wiringPiDebug) - printf ("pinMode: pin:%d mode:%d\n", pin, mode) ; + printf ("pinMode: pin:%d mode:%d\n", pin, mode) ; setupCheck ("pinMode") ; if ((pin & PI_GPIO_MASK) == 0) // On-board pin { - /**/ if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; + switch(wiringPiMode) { + default: //WPI_MODE_GPIO_SYS + fprintf(stderr, "pinMode: invalid mode\n"); + return; + case WPI_MODE_PINS: + pin = pinToGpio [pin]; + break; + case WPI_MODE_PHYS: + pin = physToGpio [pin]; + break; + case WPI_MODE_GPIO_DEVICE_BCM: + pinModeDevice(pin, mode); + return; + case WPI_MODE_GPIO_DEVICE_WPI: + pinModeDevice(pinToGpio[pin], mode); + return; + case WPI_MODE_GPIO_DEVICE_PHYS: + pinModeDevice(physToGpio[pin], mode); + return; + case WPI_MODE_GPIO: + break; + } if (wiringPiDebug) printf ("pinMode: bcm pin:%d mode:%d\n", pin, mode) ; @@ -1593,7 +1728,7 @@ void pinMode (int pin, int mode) shift = gpioToShift [pin] ; if (mode == INPUT) { - if (PI_MODEL_5 == RaspberryPiModel) { + 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<=0) { + struct gpiohandle_data data; + int ret = ioctl(lineFds[pin], GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); + if (ret) { + ReportDeviceError("get line values", pin, "digitalRead", ret); + return LOW; // error + } + return data.values[0]; + } + return LOW; // error , need to request line before +} + + int digitalRead (int pin) { struct wiringPiNodeStruct *node = wiringPiNodes ; if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - if (wiringPiMode == WPI_MODE_GPIO_SYS) - return LOW ; - else if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return LOW ; + switch(wiringPiMode) { + default: //WPI_MODE_GPIO_SYS + fprintf(stderr, "digitalRead: invalid mode\n"); + return LOW; + case WPI_MODE_PINS: + pin = pinToGpio [pin]; + break; + case WPI_MODE_PHYS: + pin = physToGpio [pin]; + break; + case WPI_MODE_GPIO_DEVICE_BCM: + return digitalReadDevice(pin); + case WPI_MODE_GPIO_DEVICE_WPI: + return digitalReadDevice(pinToGpio[pin]); + case WPI_MODE_GPIO_DEVICE_PHYS: + return digitalReadDevice(physToGpio[pin]); + case WPI_MODE_GPIO: + break; + } if (PI_MODEL_5 == RaspberryPiModel) { switch(gpio[2*pin] & RP1_STATUS_LEVEL_MASK) { @@ -1800,27 +2000,67 @@ unsigned int digitalRead8 (int pin) ********************************************************************************* */ +void digitalWriteDevice (int pin, int value) { + + if (wiringPiDebug) + printf ("digitalWriteDevice: ioctl pin:%d value: %d\n", pin, value) ; + + if (lineFds[pin]<0) { + // line not requested - auto request on first write as output + pinModeDevice(pin, OUTPUT); + } + if (lineFds[pin]>=0 && (lineFlags[pin] & GPIOHANDLE_REQUEST_OUTPUT)>0) { + struct gpiohandle_data data; + data.values[0] = value; + if (wiringPiDebug) + printf ("digitalWriteDevice: ioctl pin:%d cmd: GPIOHANDLE_SET_LINE_VALUES_IOCTL, value: %d\n", pin, value) ; + int ret = ioctl(lineFds[pin], GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); + if (ret) { + ReportDeviceError("set line values", pin, "digitalWrite", ret); + return; // error + } + } else { + fprintf(stderr, "digitalWrite: no output (%d)\n", lineFlags[pin]); + } + return; // error +} + void digitalWrite (int pin, int value) { struct wiringPiNodeStruct *node = wiringPiNodes ; if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode - return ; - else if (wiringPiMode == WPI_MODE_PINS) - pin = pinToGpio [pin] ; - else if (wiringPiMode == WPI_MODE_PHYS) - pin = physToGpio [pin] ; - else if (wiringPiMode != WPI_MODE_GPIO) - return ; + switch(wiringPiMode) { + default: //WPI_MODE_GPIO_SYS + fprintf(stderr, "digitalWrite: invalid mode\n"); + return; + case WPI_MODE_PINS: + pin = pinToGpio [pin]; + break; + case WPI_MODE_PHYS: + pin = physToGpio [pin]; + break; + case WPI_MODE_GPIO_DEVICE_BCM: + digitalWriteDevice(pin, value); + return; + case WPI_MODE_GPIO_DEVICE_WPI: + digitalWriteDevice(pinToGpio[pin], value); + return; + case WPI_MODE_GPIO_DEVICE_PHYS: + digitalWriteDevice(physToGpio[pin], value); + return; + case WPI_MODE_GPIO: + break; + } + 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<0) { + if (isrFds[pin]>0) { if (wiringPiDebug) { printf ("wiringPi: waitForInterruptClose close thread 0x%lX\n", (unsigned long)isrThreads[pin]) ; - } + } if (pthread_cancel(isrThreads[pin]) == 0) { if (wiringPiDebug) { printf ("wiringPi: waitForInterruptClose thread canceled successfuly\n") ; @@ -2208,9 +2437,9 @@ int waitForInterruptClose (int pin) { fprintf (stderr, "wiringPi: waitForInterruptClose could not cancel thread\n"); } } - close(sysFds [pin]); + close(isrFds [pin]); } - sysFds [pin] = -1; + isrFds [pin] = -1; isrFunctions [pin] = NULL; /* -not closing so far - other isr may be using it - only close if no other is using - will code later @@ -2298,7 +2527,7 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) if(waitForInterruptInit (pin, mode)<0) { if (wiringPiDebug) { fprintf (stderr, "wiringPi: waitForInterruptInit failed\n") ; - } + } }; if (wiringPiDebug) { @@ -2497,10 +2726,7 @@ int wiringPiUserLevelAccess(void) struct stat statBuf ; const char* gpiomemModule = gpiomem_BCM; - if (RaspberryPiModel<0) { //need to detect pi model - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - } + piBoard(); if (PI_MODEL_5 == RaspberryPiModel) { gpiomemModule = gpiomem_RP1; } @@ -2516,10 +2742,7 @@ int wiringPiGlobalMemoryAccess(void) unsigned int MMAP_size; unsigned int BaseAddr, PWMAddr; - if (RaspberryPiModel<0) { //need to detect pi model - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - } + piBoard(); if (PI_MODEL_5 == RaspberryPiModel) { gpiomemGlobal = pciemem_RP1; MMAP_size = pciemem_RP1_Size; @@ -2539,7 +2762,7 @@ int wiringPiGlobalMemoryAccess(void) if (lgpio == MAP_FAILED) { returnvalue = 0; if (wiringPiDebug) - fprintf(stderr,"wiringPiGlobalMemoryAccess: mmap (GPIO) failed: %s\n", strerror (errno)) ; + fprintf(stderr,"wiringPiGlobalMemoryAccess: mmap (GPIO 0x%X,0x%X) failed: %s\n", BaseAddr, MMAP_size, strerror (errno)) ; } else { munmap(lgpio, MMAP_size); if (PI_MODEL_5 == RaspberryPiModel) { @@ -2550,7 +2773,7 @@ int wiringPiGlobalMemoryAccess(void) if (lpwm == MAP_FAILED) { returnvalue = 1; // only GPIO accessible if (wiringPiDebug) - fprintf(stderr,"wiringPiGlobalMemoryAccess: mmap (PWM) failed: %s\n", strerror (errno)) ; + fprintf(stderr,"wiringPiGlobalMemoryAccess: mmap (PWM 0x%X,0x%X) failed: %s\n", PWMAddr, MMAP_size, strerror (errno)) ; } else { returnvalue = 2; // GPIO & PWM accessible munmap(lpwm, BLOCK_SIZE); @@ -2620,40 +2843,6 @@ int wiringPiSetup (void) physToGpio = physToGpioR2 ; } -// ... - - 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: - piGpioBase = GPIO_PERI_BASE_OLD ; - piGpioPupOffset = GPPUD ; - break ; - - case PI_MODEL_4B: - case PI_MODEL_400: - case PI_MODEL_CM4: - piGpioBase = GPIO_PERI_BASE_2711 ; - piGpioPupOffset = GPPUPPDN0 ; - break ; - - case PI_MODEL_5: - piGpioBase = GPIO_PERI_BASE_2712 ; - piGpioPupOffset = 0 ; - break ; - - default: - piGpioBase = GPIO_PERI_BASE_2835 ; - piGpioPupOffset = GPPUD ; - break ; - } - // Open the master /dev/ memory control device // Device strategy: December 2016: // Try /dev/mem. If that fails, then @@ -2746,7 +2935,7 @@ int wiringPiSetup (void) _wiringPiPads = pads ; _wiringPiTimer = timer ; _wiringPiRio = NULL ; - } else { + } else { unsigned int MMAP_size = (usingGpioMem) ? gpiomem_RP1_Size : pciemem_RP1_Size; GPIO_PADS = (RP1_PADS0_Addr-RP1_IO0_Addr) ; @@ -2837,21 +3026,76 @@ int wiringPiSetupPhys (void) return 0 ; } +int wiringPiSetupPinType (enum WPIPinType pinType) { + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupPinType(%d) called\n", (int) pinType) ; + switch (pinType) { + case WPI_PIN_BCM: return wiringPiSetupGpio(); + case WPI_PIN_WPI: return wiringPiSetup(); + case WPI_PIN_PHYS: return wiringPiSetupPhys(); + default: return -1; + } +} + + +int wiringPiSetupGpioDevice (enum WPIPinType pinType) { + if (wiringPiSetuped) + return 0 ; + if (wiringPiDebug) { + printf ("wiringPi: wiringPiSetupGpioDevice(%d) called\n", (int)pinType) ; + } + if (getenv (ENV_DEBUG) != NULL) + wiringPiDebug = TRUE ; + + if (getenv (ENV_CODES) != NULL) + wiringPiReturnCodes = TRUE ; + + if (wiringPiGpioDeviceGetFd()<0) { + return -1; + } + wiringPiSetuped = TRUE ; + + if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1){ + pinToGpio = pinToGpioR1 ; + physToGpio = physToGpioR1 ; + } else { + pinToGpio = pinToGpioR2 ; + physToGpio = physToGpioR2 ; + } + + initialiseEpoch () ; + + switch (pinType) { + case WPI_PIN_BCM: + wiringPiMode = WPI_MODE_GPIO_DEVICE_BCM; + break; + case WPI_PIN_WPI: + wiringPiMode = WPI_MODE_GPIO_DEVICE_WPI; + break; + case WPI_PIN_PHYS: + wiringPiMode = WPI_MODE_GPIO_DEVICE_PHYS; + break; + default: + wiringPiSetuped = FALSE; + return -1; + } + + return 0 ; +} /* * wiringPiSetupSys: * GPIO Sysfs Interface for Userspace is deprecated * https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html - * The last Raspberry Pi Kernel with Sysfs was 6.1. - * If needed, please use WiringPi 3.1. - * + * + * Switched to new GPIO driver Interface in version 3.3 */ int wiringPiSetupSys (void) { - piFunctionOops("wiringPiSetupSys", - "use WiringPi 3.1 (last version with GPIO Sysfs interface)", - "https://www.kernel.org/doc/html/v5.5/admin-guide/gpio/sysfs.html"); - - return 0 ; + if (wiringPiSetuped) + return 0 ; + if (wiringPiDebug) + printf ("wiringPi: wiringPiSetupSys called\n") ; + return wiringPiSetupGpioDevice(WPI_PIN_BCM); } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 3f19ee8..9bd749f 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -46,12 +46,15 @@ // wiringPi modes -#define WPI_MODE_PINS 0 -#define WPI_MODE_GPIO 1 -#define WPI_MODE_GPIO_SYS 2 -#define WPI_MODE_PHYS 3 -#define WPI_MODE_PIFACE 4 -#define WPI_MODE_UNINITIALISED -1 +#define WPI_MODE_PINS 0 +#define WPI_MODE_GPIO 1 +#define WPI_MODE_GPIO_SYS 2 // deprecated since 3.2 +#define WPI_MODE_PHYS 3 +#define WPI_MODE_PIFACE 4 +#define WPI_MODE_GPIO_DEVICE_BCM 5 // BCM pin numbers like WPI_MODE_GPIO +#define WPI_MODE_GPIO_DEVICE_WPI 6 // WiringPi pin numbers like WPI_MODE_PINS +#define WPI_MODE_GPIO_DEVICE_PHYS 7 // Physic pin numbers like WPI_MODE_PHYS +#define WPI_MODE_UNINITIALISED -1 // Pin modes @@ -62,6 +65,7 @@ #define SOFT_PWM_OUTPUT 4 #define SOFT_TONE_OUTPUT 5 #define PWM_TONE_OUTPUT 6 +#define PM_OFF 7 // to input / release line #define LOW 0 #define HIGH 1 @@ -205,16 +209,23 @@ 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) ; +enum WPIPinType { + WPI_PIN_BCM = 1, + WPI_PIN_WPI, + WPI_PIN_PHYS, +}; extern void wiringPiVersion (int *major, int *minor) ; -extern int wiringPiGlobalMemoryAccess(void); //Interface 3.3 +extern int wiringPiGlobalMemoryAccess(void); //Interface V3.3 extern int wiringPiUserLevelAccess (void) ; extern int wiringPiSetup (void) ; extern int wiringPiSetupSys (void) ; extern int wiringPiSetupGpio (void) ; extern int wiringPiSetupPhys (void) ; +extern int wiringPiSetupPinType (enum WPIPinType pinType); //Interface V3.3 +extern int wiringPiSetupGpioDevice(enum WPIPinType pinType); //Interface V3.3 +extern int wiringPiGpioDeviceGetFd(); //Interface V3.3 extern void pinModeAlt (int pin, int mode) ; extern void pinMode (int pin, int mode) ; extern void pullUpDnControl (int pin, int pud) ; diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c index 3fa787d..0bd166a 100644 --- a/wiringPi/wiringPiI2C.c +++ b/wiringPi/wiringPiI2C.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include #include @@ -154,6 +154,26 @@ int wiringPiI2CReadReg16 (int fd, int reg) return data.word & 0xFFFF ; } +int wiringPiI2CReadBlockData (int fd, int reg, uint8_t *values, uint8_t size) +{ + union i2c_smbus_data data; + + if (size>I2C_SMBUS_BLOCK_MAX) { + size = I2C_SMBUS_BLOCK_MAX; + } + data.block[0] = size; + int result = i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (result<0) { + return result; + } + memcpy(values, &data.block[1], size); + return data.block[0]; +} + +int wiringPiI2CRawRead (int fd, uint8_t *values, uint8_t size) +{ + return(read(fd, values, size)); +} /* * wiringPiI2CWrite: @@ -189,6 +209,22 @@ int wiringPiI2CWriteReg16 (int fd, int reg, int value) return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, &data) ; } +int wiringPiI2CWriteBlockData (int fd, int reg, const uint8_t *values, uint8_t size) +{ + union i2c_smbus_data data; + + if (size>I2C_SMBUS_BLOCK_MAX) { + size = I2C_SMBUS_BLOCK_MAX; + } + data.block[0] = size; + memcpy(&data.block[1], values, size); + return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BLOCK_DATA, &data) ; +} + +int wiringPiI2CRawWrite (int fd, const uint8_t *values, uint8_t size) +{ + return(write(fd, values, size)); +} /* * wiringPiI2CSetupInterface: diff --git a/wiringPi/wiringPiI2C.h b/wiringPi/wiringPiI2C.h index 73f031c..d9660b9 100644 --- a/wiringPi/wiringPiI2C.h +++ b/wiringPi/wiringPiI2C.h @@ -22,6 +22,8 @@ *********************************************************************** */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -29,10 +31,14 @@ extern "C" { extern int wiringPiI2CRead (int fd) ; extern int wiringPiI2CReadReg8 (int fd, int reg) ; extern int wiringPiI2CReadReg16 (int fd, int reg) ; +extern int wiringPiI2CReadBlockData (int fd, int reg, uint8_t *values, uint8_t size); //Interface 3.3 +extern int wiringPiI2CRawRead (int fd, uint8_t *values, uint8_t size); //Interface 3.3 extern int wiringPiI2CWrite (int fd, int data) ; extern int wiringPiI2CWriteReg8 (int fd, int reg, int data) ; extern int wiringPiI2CWriteReg16 (int fd, int reg, int data) ; +extern int wiringPiI2CWriteBlockData (int fd, int reg, const uint8_t *values, uint8_t size); //Interface 3.3 +extern int wiringPiI2CRawWrite (int fd, const uint8_t *values, uint8_t size); //Interface 3.3 extern int wiringPiI2CSetupInterface (const char *device, int devId) ; extern int wiringPiI2CSetup (const int devId) ; diff --git a/wiringPi/wiringPiLegacy.c b/wiringPi/wiringPiLegacy.c index e14b45a..0ec4f8c 100644 --- a/wiringPi/wiringPiLegacy.c +++ b/wiringPi/wiringPiLegacy.c @@ -186,66 +186,3 @@ int piGpioLayoutLegacy (void) return gpioLayout ; } - - -/* - * wiringPiSetupSys: - * Must be called once at the start of your program execution. - * - * Initialisation (again), however this time we are using the /sys/class/gpio - * interface to the GPIO systems - slightly slower, but always usable as - * a non-root user, assuming the devices are already exported and setup correctly. - */ - -/* -int wiringPiSetupSys (void) -{ - char fName [128] ; - - if (wiringPiSetuped) - return 0 ; - - wiringPiSetuped = TRUE ; - - if (getenv (ENV_DEBUG) != NULL) - wiringPiDebug = TRUE ; - - if (getenv (ENV_CODES) != NULL) - wiringPiReturnCodes = TRUE ; - - if (wiringPiDebug) - printf ("wiringPi: wiringPiSetupSys called\n") ; - - int model, rev, mem, maker, overVolted ; - piBoardId (&model, &rev, &mem, &maker, &overVolted) ; - - if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1) - { - pinToGpio = pinToGpioR1 ; - physToGpio = physToGpioR1 ; - } - else - { - pinToGpio = pinToGpioR2 ; - physToGpio = physToGpioR2 ; - } - -// Open and scan the directory, looking for exported GPIOs, and pre-open -// the 'value' interface to speed things up for later - - for (int pin = 0, maxpin=GetMaxPin() ; pin <= maxpin ; ++pin) - { - int pinFS = GPIOToSysFS(pin); - if (pinFS>=0) { - sprintf (fName, "/sys/class/gpio/gpio%d/value", pinFS) ; - sysFds [pin] = open (fName, O_RDWR) ; - } - } - - initialiseEpoch () ; - - wiringPiMode = WPI_MODE_GPIO_SYS ; - - return 0 ; -} -*/