@@ -1 +1 @@ | |||
3.2 | |||
3.4 |
@@ -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 ; | |||
} |
@@ -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 | |||
@@ -191,47 +179,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 <pin> <mode> | |||
This set the given pin to the supplied interrupt mode: rising, falling | |||
or both then waits for the interrupt to happen. It's a non-busy wait, | |||
@@ -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. | |||
@@ -72,8 +72,8 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio <mode/read/write/aread/awritewb/pwm/pwmTone/clock> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall\n" | |||
" gpio unexportall/exports\n" | |||
" gpio export/edge/unexport ...\n" | |||
// " gpio unexportall/exports\n" | |||
// " gpio export/edge/unexport ...\n" | |||
" gpio wfi <pin> <mode>\n" | |||
" gpio drive <group> <value>\n" | |||
" gpio pwm-bal/pwm-ms \n" | |||
@@ -89,15 +89,6 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio gbw <channel> <value>" ; // 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: | |||
@@ -290,13 +281,33 @@ static void doLoad (int argc, char *argv []) | |||
if (!moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||
system (cmd) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||
system (cmd) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (!moduleLoaded (module2)) | |||
@@ -350,13 +361,33 @@ static void doUnLoad (int argc, char *argv []) | |||
if (moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||
system (cmd) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
if (moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||
system (cmd) ; | |||
int ret = system(cmd); | |||
if (ret == -1) { | |||
perror("Error executing command"); | |||
} else if (WIFEXITED(ret)) { | |||
int exit_status = WEXITSTATUS(ret); | |||
if (exit_status != 0) { | |||
fprintf(stderr, "Command failed with exit status %d\n", exit_status); | |||
} | |||
} else { | |||
fprintf(stderr, "Command terminated by signal\n"); | |||
} | |||
} | |||
} | |||
@@ -392,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: | |||
@@ -562,15 +456,14 @@ static volatile int globalCounter ; | |||
void printgpioflush(const char* text) { | |||
if (gpioDebug) { | |||
printf(text); | |||
printf("%s", text); | |||
fflush(stdout); | |||
} | |||
} | |||
void printgpio(const char* text) { | |||
if (gpioDebug) { | |||
printf(text); | |||
fflush(stdout); | |||
printf("%s", text); | |||
} | |||
} | |||
@@ -620,7 +513,7 @@ void doWfi (int argc, char *argv []) | |||
exit (1) ; | |||
} | |||
printgpio("wait for interrupt function call \n"); | |||
printgpio("wait for interrupt function call\n"); | |||
for (int Sec=0; Sec<timeoutSec; ++Sec) { | |||
printgpioflush("."); | |||
delay (999); | |||
@@ -630,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: | |||
@@ -1358,29 +1138,52 @@ static void doVersion (char *argv []) | |||
printf ("\n") ; | |||
piBoardId (&model, &rev, &mem, &maker, &warranty) ; | |||
printf ("Raspberry Pi Details:\n") ; | |||
printf ("Hardware details:\n") ; | |||
printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s %s\n", | |||
piModelNames [model], piRevisionNames [rev], piMemorySize [mem], piMakerNames [maker], warranty ? "[Out of Warranty]" : "") ; | |||
// Check for device tree | |||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | |||
printf (" * Device tree is enabled.\n") ; | |||
printf ("\nSystem details:\n") ; | |||
if (stat ("/proc/device-tree", &statBuf) == 0) { // We're on a devtree system ... | |||
printf (" * Device tree present.\n") ; | |||
} | |||
if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type | |||
{ | |||
if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) | |||
{ | |||
fgets (name, 80, fd) ; | |||
if (fgets(name, sizeof(name), fd) == NULL) { | |||
// Handle error or end of file condition | |||
perror("Error reading /proc/device-tree/model"); | |||
} | |||
fclose (fd) ; | |||
printf (" *--> %s\n", name) ; | |||
printf (" Model: %s\n", name) ; | |||
} | |||
} | |||
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") ; | |||
int bGlobalAccess = wiringPiGlobalMemoryAccess(); // User level GPIO is GO | |||
switch(bGlobalAccess) { | |||
case 0: | |||
printf (" * Does not support basic user-level GPIO access via memory.\n") ; | |||
break; | |||
case 1: | |||
printf (" * Supports basic user-level GPIO access via /dev/mem.\n") ; | |||
break; | |||
case 2: | |||
printf (" * Supports full user-level GPIO access via memory.\n") ; | |||
break; | |||
} | |||
if (wiringPiUserLevelAccess()) { | |||
printf (" * Supports basic user-level GPIO access via /dev/gpiomem.\n") ; | |||
} 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 direct GPIO access.\n") ; | |||
} | |||
} | |||
if (wiringPiGpioDeviceGetFd()>0) { | |||
printf (" * Supports basic user-level GPIO access via /dev/gpiochip (slow).\n") ; | |||
} | |||
} | |||
@@ -1466,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: | |||
@@ -1,3 +1,3 @@ | |||
#define VERSION "3.2" | |||
#define VERSION "3.4" | |||
#define VERSION_MAJOR 3 | |||
#define VERSION_MINOR 2 | |||
#define VERSION_MINOR 4 |
@@ -43,15 +43,20 @@ | |||
********************************************************************************* | |||
*/ | |||
void waitForConversion (int fd, unsigned char *buffer, int n) | |||
void waitForConversion(int fd, unsigned char *buffer, int n) | |||
{ | |||
for (;;) | |||
{ | |||
read (fd, buffer, n) ; | |||
if ((buffer [n-1] & 0x80) == 0) | |||
break ; | |||
delay (1) ; | |||
} | |||
for (;;) { | |||
ssize_t bytes_read = read(fd, buffer, n); | |||
if (bytes_read != n) { | |||
perror("Error reading from file descriptor"); | |||
return; | |||
} | |||
if ((buffer[n - 1] & 0x80) == 0) | |||
break; | |||
delay(1); | |||
} | |||
} | |||
/* | |||
@@ -24,6 +24,7 @@ | |||
*/ | |||
#include <unistd.h> | |||
#include <stdio.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiI2C.h" | |||
@@ -41,7 +42,10 @@ static void myAnalogWrite (struct wiringPiNodeStruct *node, UNU int pin, int val | |||
unsigned char b [2] ; | |||
b [0] = 0x40 ; | |||
b [1] = value & 0xFF ; | |||
write (node->fd, b, 2) ; | |||
ssize_t bytes_written = write(node->fd, b, 2); | |||
if (bytes_written != 2) { | |||
perror("Error writing to file descriptor"); | |||
} | |||
} | |||
@@ -35,9 +35,12 @@ | |||
#define SHARED_NAME "wiringPiPseudoPins" | |||
#define PSEUDO_PINS 64 | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
#include <sys/mman.h> | |||
#include <fcntl.h> | |||
#include <stdint.h> | |||
#include <sys/stat.h> | |||
#include <fcntl.h> | |||
@@ -45,21 +48,20 @@ | |||
#include "pseudoPins.h" | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
static int myAnalogRead(struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int *ptr = (int *)node->data0 ; | |||
int myPin = pin - node->pinBase ; | |||
int *ptr = (int *)(intptr_t)node->data0; // Cast to intptr_t to handle pointer-to-integer conversion | |||
int myPin = pin - node->pinBase; | |||
return *(ptr + myPin) ; | |||
return *(ptr + myPin); | |||
} | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
static void myAnalogWrite(struct wiringPiNodeStruct *node, int pin, int value) | |||
{ | |||
int *ptr = (int *)node->data0 ; | |||
int myPin = pin - node->pinBase ; | |||
int *ptr = (int *)(intptr_t)node->data0; | |||
int myPin = pin - node->pinBase; | |||
*(ptr + myPin) = value ; | |||
*(ptr + myPin) = value; | |||
} | |||
@@ -69,27 +71,39 @@ static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
********************************************************************************* | |||
*/ | |||
int pseudoPinsSetup (const int pinBase) | |||
{ | |||
struct wiringPiNodeStruct *node ; | |||
void *ptr ; | |||
node = wiringPiNewNode (pinBase, PSEUDO_PINS) ; | |||
node->fd = shm_open (SHARED_NAME, O_CREAT | O_RDWR, 0666) ; | |||
if (node->fd < 0) | |||
return FALSE ; | |||
if (ftruncate (node->fd, PSEUDO_PINS * sizeof (int)) < 0) | |||
return FALSE ; | |||
ptr = mmap (NULL, PSEUDO_PINS * sizeof (int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0) ; | |||
node->data0 = (unsigned int)ptr ; | |||
node->analogRead = myAnalogRead ; | |||
node->analogWrite = myAnalogWrite ; | |||
return TRUE ; | |||
int pseudoPinsSetup(const int pinBase) | |||
{ | |||
struct wiringPiNodeStruct *node; | |||
void *ptr; | |||
node = wiringPiNewNode(pinBase, PSEUDO_PINS); | |||
if (node == NULL) { | |||
fprintf(stderr, "Error creating new wiringPi node"); | |||
return FALSE; | |||
} | |||
node->fd = shm_open(SHARED_NAME, O_CREAT | O_RDWR, 0666); | |||
if (node->fd < 0) { | |||
perror("Error opening shared memory"); | |||
return FALSE; | |||
} | |||
if (ftruncate(node->fd, PSEUDO_PINS * sizeof(int)) < 0) { | |||
perror("Error resizing shared memory"); | |||
return FALSE; | |||
} | |||
ptr = mmap(NULL, PSEUDO_PINS * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0); | |||
if (ptr == MAP_FAILED) { | |||
perror("Error mapping shared memory"); | |||
return FALSE; | |||
} | |||
node->data0 = (unsigned int)(uintptr_t)ptr; | |||
node->analogRead = myAnalogRead; | |||
node->analogWrite = myAnalogWrite; | |||
return TRUE; | |||
} |
@@ -0,0 +1,38 @@ | |||
CC = gcc | |||
CFLAGS = -Wall | |||
LDFLAGS = | |||
tests = wiringpi_test1_sysfs wiringpi_test2_sysfs wiringpi_test3_device_wpi wiringpi_test4_device_phys wiringpi_test5_default wiringpi_test6_isr wiringpi_test7_version | |||
all: $(tests) | |||
wiringpi_test1_sysfs: | |||
${CC} ${CFLAGS} wiringpi_test1_sysfs.c -o wiringpi_test1_sysfs -lwiringPi | |||
wiringpi_test2_sysfs: | |||
${CC} ${CFLAGS} wiringpi_test2_sysfs.c -o wiringpi_test2_sysfs -lwiringPi | |||
wiringpi_test3_device_wpi: | |||
${CC} ${CFLAGS} wiringpi_test3_device_wpi.c -o wiringpi_test3_device_wpi -lwiringPi | |||
wiringpi_test4_device_phys: | |||
${CC} ${CFLAGS} wiringpi_test4_device_phys.c -o wiringpi_test4_device_phys -lwiringPi | |||
wiringpi_test5_default: | |||
${CC} ${CFLAGS} wiringpi_test5_default.c -o wiringpi_test5_default -lwiringPi | |||
wiringpi_test6_isr: | |||
${CC} ${CFLAGS} wiringpi_test6_isr.c -o wiringpi_test6_isr -lwiringPi | |||
wiringpi_test7_version: | |||
${CC} ${CFLAGS} wiringpi_test7_version.c -o wiringpi_test7_version -lwiringPi | |||
test: | |||
for t in $(tests) ; do \ | |||
echo === unit test: $${t} === ; \ | |||
time ./$${t} ; \ | |||
echo ; echo ; \ | |||
done | |||
clean: | |||
for t in $(tests) ; do rm -fv $${t} ; done |
@@ -0,0 +1,57 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
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("wiringPiSetupSys failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
printf("toggle %d times ...\n", ToggleValue); | |||
for (int loop=1; loop<ToggleValue; loop++) { | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
digitalWriteEx(GPIO, GPIOIN, HIGH); | |||
delayMicroseconds(600000); | |||
} | |||
digitalWrite(GPIO, LOW); | |||
printf("\nWiringPi GPIO test program (using GPIO%d (input pull up/down) and GPIO%d (input) via sys)\n", GPIO, GPIOIN); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, INPUT); | |||
delayMicroseconds(3000000); | |||
pullUpDnControl (GPIOIN, PUD_OFF); | |||
for (int loop=1; loop<ToggleValue; loop++) { | |||
pullUpDnControlEx (GPIO, GPIOIN, PUD_DOWN); | |||
delayMicroseconds(600000); | |||
pullUpDnControlEx (GPIO, GPIOIN, PUD_UP); | |||
delayMicroseconds(600000); | |||
} | |||
//Error wrong direction - only for fun | |||
digitalWrite(GPIO, LOW); | |||
return(EXIT_SUCCESS); | |||
} | |||
@@ -0,0 +1,54 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test2_device.c -o wiringpi_test2_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
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, GPIOIN, HIGH); | |||
delayMicroseconds(600000); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
printf("\nTest output off with pull up\n"); | |||
pinMode(GPIO, OUTPUT); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, PM_OFF); | |||
delayMicroseconds(600000); | |||
printf("out = off "); | |||
CheckGPIO(GPIO, GPIOIN, 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(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
} |
@@ -0,0 +1,54 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test3_device.c -o wiringpi_test3_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
const int GPIO = 24; //BCM 19 | |||
const int GPIOIN = 25; //BCM 26; | |||
const int ToggleValue = 4; | |||
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, GPIOIN, HIGH); | |||
delayMicroseconds(600000); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
printf("\nTest output off with pull up\n"); | |||
pinMode(GPIO, OUTPUT); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, PM_OFF); | |||
delayMicroseconds(600000); | |||
printf("out = off "); | |||
CheckGPIO(GPIO, GPIOIN, 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(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
} |
@@ -0,0 +1,54 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test4_device.c -o wiringpi_test4_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
const int GPIO = 35; //BCM 19 | |||
const int GPIOIN = 37; //BCM 26; | |||
const int ToggleValue = 4; | |||
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, GPIOIN, HIGH); | |||
delayMicroseconds(600000); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
printf("\nTest output off with pull up\n"); | |||
pinMode(GPIO, OUTPUT); | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, PM_OFF); | |||
delayMicroseconds(600000); | |||
printf("out = off "); | |||
CheckGPIO(GPIO, GPIOIN, 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(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
return(EXIT_SUCCESS); | |||
} |
@@ -0,0 +1,57 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <stdlib.h> | |||
#include <signal.h> | |||
#include <string.h> | |||
#include <time.h> | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
int main (void) { | |||
printf("WiringPi GPIO test program 1 (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); | |||
printf(" testing digitalWrite, digitalRead and pullUpDnControl\n"); | |||
if (wiringPiSetupGpio() == -1) { | |||
printf("wiringPiSetupGpio failed\n\n"); | |||
exit(EXIT_FAILURE); | |||
} | |||
pinMode(GPIOIN, INPUT); | |||
pinMode(GPIO, OUTPUT); | |||
printf("toggle %d times ...\n", ToggleValue); | |||
for (int loop=1; loop<ToggleValue; loop++) { | |||
digitalWriteEx(GPIO, GPIOIN, LOW); | |||
delayMicroseconds(600000); | |||
digitalWriteEx(GPIO, GPIOIN, HIGH); | |||
delayMicroseconds(600000); | |||
} | |||
digitalWrite(GPIO, LOW); | |||
printf("\nWiringPi GPIO test program (using GPIO%d (input pull up/down) and GPIO%d (input))\n", GPIO, GPIOIN); | |||
pullUpDnControl (GPIO, PUD_UP); | |||
pinMode(GPIO, INPUT); | |||
delayMicroseconds(3000000); | |||
pullUpDnControl (GPIOIN, PUD_OFF); | |||
for (int loop=1; loop<ToggleValue; loop++) { | |||
pullUpDnControlEx (GPIO, GPIOIN, PUD_DOWN); | |||
delayMicroseconds(600000); | |||
pullUpDnControlEx (GPIO, GPIOIN, PUD_UP); | |||
delayMicroseconds(600000); | |||
} | |||
//Error wrong direction - only for fun | |||
digitalWrite(GPIO, LOW); | |||
return(EXIT_SUCCESS); | |||
} | |||
@@ -0,0 +1,170 @@ | |||
// WiringPi test program: Kernel char device interface / sysfs successor | |||
// Compile: gcc -Wall wiringpi_test1_device.c -o wiringpi_test1_device -lwiringPi | |||
#include "wpi_test.h" | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <stdlib.h> | |||
#include <unistd.h> | |||
#include <sys/time.h> | |||
const int GPIO = 19; | |||
const int GPIOIN = 26; | |||
const int ToggleValue = 4; | |||
static volatile int globalCounter; | |||
volatile long long gStartTime, gEndTime; | |||
static void wfi (void) { | |||
struct timeval now; | |||
gettimeofday(&now, 0); | |||
if (0==gStartTime) { | |||
gStartTime = now.tv_sec*1000000LL + now.tv_usec; | |||
} else { | |||
gEndTime = now.tv_sec*1000000LL + now.tv_usec; | |||
} | |||
globalCounter++; | |||
} | |||
double StartSequence (int Enge, int OUTpin) { | |||
int expected; | |||
double timeExpected; | |||
gStartTime = 0; | |||
gEndTime = 0; | |||
globalCounter = 0; | |||
printf("Start\n"); | |||
digitalWrite(OUTpin, HIGH); | |||
delay(200); | |||
digitalWrite(OUTpin, LOW); | |||
delay(100); | |||
digitalWrite(OUTpin, HIGH); | |||
delay(200); | |||
digitalWrite(OUTpin, LOW); | |||
delay(100); | |||
printf("Stop\n"); | |||
int globalCounterCopy = globalCounter; | |||
if (INT_EDGE_BOTH == Enge) { | |||
expected = 4; | |||
timeExpected = 500; | |||
} else { | |||
expected = 2; | |||
timeExpected = 300; | |||
} | |||
if (globalCounter==expected) { | |||
double fTime = (gEndTime - gStartTime) / 1000000.0; | |||
printf("IRQ worked %g sec (~%gs expected)", fTime, timeExpected/1000.0); | |||
double diff = fTime-(timeExpected/1000.0); | |||
if(diff<0.05 && diff>0) { | |||
printf(" -> %spassed%s\n", COLORGRN, COLORDEF); | |||
} else { | |||
printf(" -> %sfailed%s\n", COLORRED, COLORDEF); | |||
} | |||
return fTime; | |||
} else { | |||
printf("IRQ not worked got %d iterations (%d exprected)\n\n", globalCounterCopy, expected); | |||
return 0; | |||
} | |||
} | |||
double DurationTime(int Enge, int OUTpin, int IRQpin) { | |||
struct timeval now; | |||
double fTime = 0.0; | |||
gStartTime = 0; | |||
gEndTime = 0; | |||
globalCounter = 0; | |||
printf("Start\n"); | |||
if (INT_EDGE_RISING == Enge) { | |||
digitalWrite(OUTpin, LOW); | |||
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; | |||
sleep(1); | |||
gettimeofday(&now, 0); | |||
gStartTime = now.tv_sec*1000000LL + now.tv_usec; | |||
digitalWrite(OUTpin, HIGH); | |||
delay(20); | |||
digitalWrite(OUTpin, LOW); | |||
} else if (INT_EDGE_FALLING == Enge) { | |||
digitalWrite(OUTpin, HIGH); | |||
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; | |||
sleep(1); | |||
gettimeofday(&now, 0); | |||
gStartTime = now.tv_sec*1000000LL + now.tv_usec; | |||
digitalWrite(OUTpin, LOW); | |||
} | |||
sleep(1); | |||
fTime = (gEndTime - gStartTime); | |||
printf("IRQ detect time %g usec", fTime); | |||
if (fTime<2000 && fTime>0) { | |||
printf(" -> %spassed%s\n", COLORGRN, COLORDEF); | |||
} else { | |||
printf(" -> %sfailed%s\n", COLORRED, COLORDEF); | |||
} | |||
wiringPiISRStop (IRQpin) ; | |||
return fTime; | |||
} | |||
int main (void) { | |||
const int IRQpin = GPIOIN ; | |||
const int OUTpin = GPIO ; | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
printf("WiringPi GPIO test program 1 (using GPIO%d (output) and GPIO%d (input))\n", GPIO, GPIOIN); | |||
printf(" testing irq\n"); | |||
printf("\nISR test (WiringPi %d.%d)\n", major, minor); | |||
wiringPiSetupGpio() ; | |||
pinMode(IRQpin, INPUT); | |||
pinMode(OUTpin, OUTPUT); | |||
digitalWrite (OUTpin, LOW) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_RISING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_RISING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_FALLING, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_FALLING, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
printf("Testing IRQ @ GPIO%d with trigger @ GPIO%d both\n", IRQpin, OUTpin); | |||
wiringPiISR (IRQpin, INT_EDGE_BOTH, &wfi) ; | |||
sleep(1); | |||
StartSequence (INT_EDGE_BOTH, OUTpin); | |||
printf("Testing close\n"); | |||
wiringPiISRStop (IRQpin) ; | |||
for (int count=0; count<2; count++) { | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d rising\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_RISING, OUTpin, IRQpin); | |||
printf("Measuring duration IRQ @ GPIO%d with trigger @ GPIO%d falling\n", IRQpin, OUTpin); | |||
DurationTime(INT_EDGE_FALLING, OUTpin, IRQpin); | |||
} | |||
pinMode(OUTpin, INPUT); | |||
return 0 ; | |||
} |
@@ -0,0 +1,11 @@ | |||
#include "wpi_test.h" | |||
#include "../../version.h" | |||
int main (void) { | |||
int major, minor; | |||
wiringPiVersion(&major, &minor); | |||
CheckSame("version major", major, VERSION_MAJOR); | |||
CheckSame("version minor", minor, VERSION_MINOR); | |||
} |
@@ -0,0 +1,48 @@ | |||
#include <wiringPi.h> | |||
#include <stdio.h> | |||
#define COLORDEF "\x1B[0m" | |||
#define COLORRED "\x1B[31m" | |||
#define COLORGRN "\x1B[32m" | |||
void CheckGPIO(int GPIO, int GPIOIN, int out) { | |||
int in = digitalRead(GPIOIN); | |||
int read = digitalRead(GPIO); | |||
int pass = 0; | |||
if (out==in && in==read) { | |||
pass = 1; | |||
} | |||
if (pass) { | |||
printf("GPIO%d = %d (GPIO%d = %d) -> %spassed%s\n", GPIOIN, in, GPIO, read, COLORGRN, COLORDEF ); | |||
} else { | |||
printf("GPIO%d = %d (GPIO%d = %d) -> %sfailed%s\n", GPIOIN, in, GPIO, read, COLORRED, COLORDEF ); | |||
} | |||
} | |||
void digitalWriteEx(int GPIO, int GPIOIN, int mode) { | |||
digitalWrite(GPIO, mode); | |||
printf("out = %d ", mode); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, mode); | |||
} | |||
void pullUpDnControlEx (int GPIO, int GPIOIN, int mode) { | |||
pullUpDnControl (GPIO, mode); | |||
int out = mode==PUD_UP ? 1:0; | |||
printf("in = %4s ", mode==PUD_UP ? "up":"down"); | |||
delayMicroseconds(5000); | |||
CheckGPIO(GPIO, GPIOIN, out); | |||
} | |||
void CheckSame(const char* msg, int value, int expect) { | |||
if (value==expect) { | |||
printf("%s -> %spassed%s\n", msg, COLORGRN, COLORDEF ); | |||
} else { | |||
printf("%s -> %sfailed%s\n", msg, COLORRED, COLORDEF ); | |||
} | |||
} |
@@ -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 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 sysFds [64] = | |||
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,52 +544,13 @@ 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; | |||
int piBoard() { | |||
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; | |||
} | |||
int model, rev, mem, maker, overVolted; | |||
piBoardId (&model, &rev, &mem, &maker, &overVolted); | |||
} | |||
if (wiringPiDebug) | |||
printf ("GPIOToSysFS: translate bcm gpio %d to sysfs gpio %d\n", pin, sysfspin) ; | |||
return sysfspin; | |||
return RaspberryPiModel<0 ? 0 : 1; | |||
} | |||
int GetMaxPin() { | |||
@@ -584,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" | |||
@@ -857,12 +831,12 @@ static void usingGpioMemCheck (const char *what) | |||
void PrintSystemStdErr () { | |||
struct utsname sys_info; | |||
if (uname(&sys_info) == 0) { | |||
fprintf (stderr, " wiringpi = %d.%d\n", VERSION_MAJOR, VERSION_MINOR); | |||
fprintf (stderr, " system name = %s\n", sys_info.sysname); | |||
//fprintf (stderr, " node name = %s\n", sys_info.nodename); | |||
fprintf (stderr, " release = %s\n", sys_info.release); | |||
fprintf (stderr, " version = %s\n", sys_info.version); | |||
fprintf (stderr, " machine = %s\n", sys_info.machine); | |||
fprintf (stderr, " WiringPi : %d.%d\n", VERSION_MAJOR, VERSION_MINOR); | |||
fprintf (stderr, " system name : %s\n", sys_info.sysname); | |||
//fprintf (stderr, " node name : %s\n", sys_info.nodename); | |||
fprintf (stderr, " release : %s\n", sys_info.release); | |||
fprintf (stderr, " version : %s\n", sys_info.version); | |||
fprintf (stderr, " machine : %s\n", sys_info.machine); | |||
if (strstr(sys_info.machine, "arm") == NULL && strstr(sys_info.machine, "aarch")==NULL) { | |||
fprintf (stderr, " -> This is not an ARM architecture; it cannot be a Raspberry Pi.\n") ; | |||
} | |||
@@ -884,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: | |||
@@ -923,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; | |||
} | |||
@@ -1135,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 ; | |||
} | |||
} | |||
@@ -1194,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*/ | |||
@@ -1214,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 | |||
@@ -1228,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); | |||
} | |||
@@ -1525,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 | |||
@@ -1555,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 | |||
@@ -1588,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 ; | |||
@@ -1595,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) ; | |||
@@ -1618,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<<pin; // Input | |||
@@ -1646,7 +1756,7 @@ void pinMode (int pin, int mode) | |||
{ | |||
RETURN_ON_MODEL5 | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
return ; | |||
return ; | |||
usingGpioMemCheck ("pinMode PWM") ; | |||
@@ -1663,7 +1773,7 @@ void pinMode (int pin, int mode) | |||
{ | |||
RETURN_ON_MODEL5 | |||
if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin | |||
return ; | |||
return ; | |||
usingGpioMemCheck ("pinMode CLOCK") ; | |||
@@ -1688,6 +1798,28 @@ void pinMode (int pin, int mode) | |||
* Control the internal pull-up/down resistors on a GPIO pin. | |||
********************************************************************************* | |||
*/ | |||
void pullUpDnControlDevice (int pin, int pud) { | |||
unsigned int flag = lineFlags[pin]; | |||
unsigned int biasflags = GPIOHANDLE_REQUEST_BIAS_DISABLE | GPIOHANDLE_REQUEST_BIAS_PULL_UP | GPIOHANDLE_REQUEST_BIAS_PULL_DOWN; | |||
flag &= ~biasflags; | |||
switch (pud){ | |||
case PUD_OFF: flag |= GPIOHANDLE_REQUEST_BIAS_DISABLE; break; | |||
case PUD_UP: flag |= GPIOHANDLE_REQUEST_BIAS_PULL_UP; break; | |||
case PUD_DOWN: flag |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN; break; | |||
default: return ; /* An illegal value */ | |||
} | |||
// reset input/output | |||
if (lineFlags[pin] & GPIOHANDLE_REQUEST_OUTPUT) { | |||
pinModeFlagsDevice (pin, OUTPUT, flag); | |||
} else if(lineFlags[pin] & GPIOHANDLE_REQUEST_INPUT) { | |||
pinModeFlagsDevice (pin, INPUT, flag); | |||
} else { | |||
lineFlags[pin] = flag; // only store for later | |||
} | |||
} | |||
void pullUpDnControl (int pin, int pud) | |||
{ | |||
@@ -1697,13 +1829,25 @@ void pullUpDnControl (int pin, int pud) | |||
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: | |||
return pullUpDnControlDevice(pin, pud); | |||
case WPI_MODE_GPIO_DEVICE_WPI: | |||
return pullUpDnControlDevice(pinToGpio[pin], pud); | |||
case WPI_MODE_GPIO_DEVICE_PHYS: | |||
return pullUpDnControlDevice(physToGpio[pin], pud); | |||
case WPI_MODE_GPIO: | |||
break; | |||
} | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
unsigned int pullbits = pads[1+pin] & RP1_INV_PUD_MASK; // remove bits | |||
@@ -1722,11 +1866,10 @@ void pullUpDnControl (int pin, int pud) | |||
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; | |||
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 */ | |||
} | |||
@@ -1755,26 +1898,58 @@ void pullUpDnControl (int pin, int pud) | |||
} | |||
/* | |||
* digitalRead: | |||
* Read the value of a given Pin, returning HIGH or LOW | |||
********************************************************************************* | |||
*/ | |||
int digitalReadDevice (int pin) { // INPUT and OUTPUT should work | |||
if (lineFds[pin]<0) { | |||
// line not requested - auto request on first read as input | |||
pinModeDevice(pin, INPUT); | |||
} | |||
if (lineFds[pin]>=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) { | |||
@@ -1825,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<<pin); | |||
rio[RP1_RIO_OUT + RP1_CLR_OFFSET] = 1<<pin; | |||
} else { | |||
//printf("Set pin %d >>0x%08x<< to high\n", pin, 1<<pin); | |||
rio[RP1_RIO_OUT + RP1_SET_OFFSET] = 1<<pin; | |||
rio[RP1_RIO_OUT + RP1_SET_OFFSET] = 1<<pin; | |||
} | |||
} else { | |||
if (value == LOW) | |||
@@ -2101,7 +2316,7 @@ unsigned int digitalReadByte2 (void) | |||
int waitForInterrupt (int pin, int mS) | |||
{ | |||
int fd, ret; | |||
int fd, ret; | |||
struct pollfd polls ; | |||
struct gpioevent_data evdata; | |||
//struct gpio_v2_line_request req2; | |||
@@ -2111,7 +2326,7 @@ int waitForInterrupt (int pin, int mS) | |||
else if (wiringPiMode == WPI_MODE_PHYS) | |||
pin = physToGpio [pin] ; | |||
if ((fd = sysFds [pin]) == -1) | |||
if ((fd = isrFds [pin]) == -1) | |||
return -2 ; | |||
// Setup poll structure | |||
@@ -2124,12 +2339,12 @@ int waitForInterrupt (int pin, int mS) | |||
if (ret <= 0) { | |||
fprintf(stderr, "wiringPi: ERROR: poll returned=%d\n", ret); | |||
} else { | |||
//if (polls.revents & POLLIN) | |||
//if (polls.revents & POLLIN) | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, sysFds [pin]) ; | |||
printf ("wiringPi: IRQ line %d received %d, fd=%d\n", pin, ret, isrFds[pin]) ; | |||
} | |||
/* read event data */ | |||
int readret = read(sysFds [pin], &evdata, sizeof(evdata)); | |||
int readret = read(isrFds [pin], &evdata, sizeof(evdata)); | |||
if (readret == sizeof(evdata)) { | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: IRQ data id: %d, timestamp: %lld\n", evdata.id, evdata.timestamp) ; | |||
@@ -2142,9 +2357,6 @@ int waitForInterrupt (int pin, int mS) | |||
return ret; | |||
} | |||
const char DEV_GPIO_PI[] ="/dev/gpiochip0"; | |||
const char DEV_GPIO_PI5[]="/dev/gpiochip4"; | |||
int waitForInterruptInit (int pin, int mode) | |||
{ | |||
const char* strmode = ""; | |||
@@ -2157,16 +2369,8 @@ int waitForInterruptInit (int pin, int mode) | |||
/* open gpio */ | |||
sleep(1); | |||
const char* gpiochip = PI_MODEL_5 == RaspberryPiModel ? DEV_GPIO_PI5 : DEV_GPIO_PI; | |||
if (chipFd < 0) { | |||
chipFd = open(gpiochip, O_RDWR); | |||
if (chipFd < 0) { | |||
fprintf(stderr, "wiringPi: ERROR: %s open ret=%d\n", gpiochip, chipFd); | |||
return -1; | |||
} | |||
} | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: Open chip %s succeded, fd=%d\n", gpiochip, chipFd) ; | |||
if (wiringPiGpioDeviceGetFd()<0) { | |||
return -1; | |||
} | |||
struct gpioevent_request req; | |||
@@ -2197,7 +2401,7 @@ int waitForInterruptInit (int pin, int mode) | |||
//later implement GPIO_V2_GET_LINE_IOCTL req2 | |||
int ret = ioctl(chipFd, GPIO_GET_LINEEVENT_IOCTL, &req); | |||
if (ret) { | |||
fprintf(stderr, "wiringPi: ERROR: %s ioctl get line %d %s returned %d\n", gpiochip, pin, strmode, ret); | |||
ReportDeviceError("get line event", pin , strmode, ret); | |||
return -1; | |||
} | |||
if (wiringPiDebug) { | |||
@@ -2206,12 +2410,12 @@ int waitForInterruptInit (int pin, int mode) | |||
/* set event fd nonbloack read */ | |||
int fd_line = req.fd; | |||
sysFds [pin] = fd_line; | |||
isrFds [pin] = fd_line; | |||
int flags = fcntl(fd_line, F_GETFL); | |||
flags |= O_NONBLOCK; | |||
ret = fcntl(fd_line, F_SETFL, flags); | |||
if (ret) { | |||
fprintf(stderr, "wiringPi: ERROR: %s fcntl set nonblock read=%d\n", gpiochip, chipFd); | |||
fprintf(stderr, "wiringPi: ERROR: fcntl set nonblock return=%d\n", ret); | |||
return -1; | |||
} | |||
@@ -2220,10 +2424,10 @@ int waitForInterruptInit (int pin, int mode) | |||
int waitForInterruptClose (int pin) { | |||
if (sysFds[pin]>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") ; | |||
@@ -2233,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 | |||
@@ -2323,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) { | |||
@@ -2522,6 +2726,7 @@ int wiringPiUserLevelAccess(void) | |||
struct stat statBuf ; | |||
const char* gpiomemModule = gpiomem_BCM; | |||
piBoard(); | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
gpiomemModule = gpiomem_RP1; | |||
} | |||
@@ -2530,6 +2735,58 @@ int wiringPiUserLevelAccess(void) | |||
} | |||
int wiringPiGlobalMemoryAccess(void) | |||
{ | |||
const char* gpiomemGlobal; | |||
int fd=-1; | |||
unsigned int MMAP_size; | |||
unsigned int BaseAddr, PWMAddr; | |||
piBoard(); | |||
if (PI_MODEL_5 == RaspberryPiModel) { | |||
gpiomemGlobal = pciemem_RP1; | |||
MMAP_size = pciemem_RP1_Size; | |||
BaseAddr = 0x00000000; | |||
PWMAddr = 0x00000000; //not supported so far | |||
} else { | |||
gpiomemGlobal = gpiomem_global; | |||
MMAP_size = BLOCK_SIZE; | |||
BaseAddr = piGpioBase + 0x00200000 ; | |||
PWMAddr = piGpioBase + 0x0020C000 ; | |||
} | |||
if ((fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) >0) { | |||
int returnvalue = 1; // OK | |||
uint32_t * lgpio = (uint32_t *)mmap(0, MMAP_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, BaseAddr) ; | |||
if (lgpio == MAP_FAILED) { | |||
returnvalue = 0; | |||
if (wiringPiDebug) | |||
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) { | |||
returnvalue = 2; // GPIO & PWM accessible (same area, nothing to mmap) | |||
} else { | |||
//check PWM area | |||
uint32_t* lpwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PWMAddr) ; | |||
if (lpwm == MAP_FAILED) { | |||
returnvalue = 1; // only GPIO accessible | |||
if (wiringPiDebug) | |||
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); | |||
} | |||
} | |||
} | |||
close(fd); | |||
return returnvalue; | |||
} | |||
return 0; // Failed! | |||
} | |||
/* | |||
* wiringPiSetup: | |||
* Must be called once at the start of your program execution. | |||
@@ -2586,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 | |||
@@ -2633,9 +2856,12 @@ int wiringPiSetup (void) | |||
gpiomemModule = gpiomem_RP1; | |||
} | |||
usingGpioMem = FALSE; | |||
if (gpiomemGlobal==NULL || (fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) < 0) | |||
{ | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: no access to %s try %s\n", gpiomemGlobal, gpiomemModule) ; | |||
} | |||
if (gpiomemModule && (fd = open (gpiomemModule, O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem | |||
{ | |||
piGpioBase = 0 ; | |||
@@ -2648,7 +2874,7 @@ int wiringPiSetup (void) | |||
" Try running with sudo?\n", gpiomemGlobal, gpiomemModule, strerror (errno)) ; | |||
} | |||
if (wiringPiDebug) { | |||
printf ("wiringPi: access to %s succeded\n", usingGpioMem ? gpiomemModule : gpiomemGlobal) ; | |||
printf ("wiringPi: access to %s succeded %d\n", usingGpioMem ? gpiomemModule : gpiomemGlobal, fd) ; | |||
} | |||
// GPIO: | |||
if (PI_MODEL_5 != model) { | |||
@@ -2709,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) ; | |||
@@ -2800,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 wringpi 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); | |||
} |
@@ -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,15 +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 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) ; | |||
@@ -47,7 +47,7 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <stdint.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <string.h> | |||
#include <fcntl.h> | |||
@@ -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: | |||
@@ -22,6 +22,8 @@ | |||
*********************************************************************** | |||
*/ | |||
#include <stdint.h> | |||
#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) ; | |||
@@ -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 ; | |||
} | |||
*/ |
@@ -153,9 +153,12 @@ void serialClose (const int fd) | |||
********************************************************************************* | |||
*/ | |||
void serialPutchar (const int fd, const unsigned char c) | |||
void serialPutchar(const int fd, const unsigned char c) | |||
{ | |||
write (fd, &c, 1) ; | |||
ssize_t bytes_written = write(fd, &c, 1); | |||
if (bytes_written != 1) { | |||
perror("Error writing to file descriptor"); | |||
} | |||
} | |||
@@ -165,9 +168,13 @@ void serialPutchar (const int fd, const unsigned char c) | |||
********************************************************************************* | |||
*/ | |||
void serialPuts (const int fd, const char *s) | |||
void serialPuts(const int fd, const char *s) | |||
{ | |||
write (fd, s, strlen (s)) ; | |||
size_t len = strlen(s); | |||
ssize_t bytes_written = write(fd, s, len); | |||
if (bytes_written != (ssize_t)len) { | |||
perror("Error writing to file descriptor"); | |||
} | |||
} | |||
/* | |||