瀏覽代碼

Merge pull request #233 from WiringPi/GPIOAPI

Gpioapi
example
Manfred Wallner 6 月之前
committed by GitHub
父節點
當前提交
ac11fa2f95
沒有發現已知的金鑰在資料庫的簽署中 GPG 金鑰 ID: B5690EEEBB952194
共有 14 個檔案被更改,包括 823 行新增574 行删除
  1. +1
    -1
      VERSION
  2. +9
    -2
      examples/speed.c
  3. +6
    -66
      gpio/gpio.1
  4. +23
    -278
      gpio/gpio.c
  5. +2
    -2
      version.h
  6. +83
    -0
      wiringPi/test/wiringpi_test1_device.c
  7. +80
    -0
      wiringPi/test/wiringpi_test2_device.c
  8. +80
    -0
      wiringPi/test/wiringpi_test3_device.c
  9. +80
    -0
      wiringPi/test/wiringpi_test4_device.c
  10. +397
    -153
      wiringPi/wiringPi.c
  11. +19
    -8
      wiringPi/wiringPi.h
  12. +37
    -1
      wiringPi/wiringPiI2C.c
  13. +6
    -0
      wiringPi/wiringPiI2C.h
  14. +0
    -63
      wiringPi/wiringPiLegacy.c

+ 1
- 1
VERSION 查看文件

@@ -1 +1 @@
3.2
3.3

+ 9
- 2
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 ;
}

+ 6
- 66
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
@@ -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.



+ 23
- 278
gpio/gpio.c 查看文件

@@ -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:
@@ -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:



+ 2
- 2
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

+ 83
- 0
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 <wiringPi.h>
#include <stdio.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;

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<ToggleValue; loop++) {
digitalWriteEx(GPIO, LOW);
delayMicroseconds(600000);
digitalWriteEx(GPIO, 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, PUD_DOWN);
delayMicroseconds(600000);
pullUpDnControlEx (GPIO, PUD_UP);
delayMicroseconds(600000);
}

//Error wrong direction - only for fun
digitalWrite(GPIO, LOW);

return(EXIT_SUCCESS);
}


+ 80
- 0
wiringPi/test/wiringpi_test2_device.c 查看文件

@@ -0,0 +1,80 @@
// WiringPi test program: Kernel char device interface / sysfs successor
// Compile: gcc -Wall wiringpi_test2_device.c -o wiringpi_test2_device -lwiringPi

#include <wiringPi.h>
#include <stdio.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;

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);
}

+ 80
- 0
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 <wiringPi.h>
#include <stdio.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;

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);
}

+ 80
- 0
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 <wiringPi.h>
#include <stdio.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;

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);
}

+ 397
- 153
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<<pin; // Input
@@ -1621,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") ;

@@ -1638,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") ;

@@ -1663,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)
{
@@ -1672,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
@@ -1697,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 */
}

@@ -1730,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) {
@@ -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<<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)
@@ -2076,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;
@@ -2086,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
@@ -2099,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) ;
@@ -2117,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 = "";
@@ -2132,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;
@@ -2172,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) {
@@ -2181,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;
}

@@ -2195,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") ;
@@ -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);
}

+ 19
- 8
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) ;


+ 37
- 1
wiringPi/wiringPiI2C.c 查看文件

@@ -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:


+ 6
- 0
wiringPi/wiringPiI2C.h 查看文件

@@ -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) ;


+ 0
- 63
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 ;
}
*/

Loading…
取消
儲存