Browse Source

#210

pull/228/head
mstroh76 6 months ago
parent
commit
d3a23725b8
5 changed files with 40 additions and 418 deletions
  1. +9
    -2
      examples/speed.c
  2. +6
    -66
      gpio/gpio.1
  3. +17
    -276
      gpio/gpio.c
  4. +8
    -11
      wiringPi/wiringPi.c
  5. +0
    -63
      wiringPi/wiringPiLegacy.c

+ 9
- 2
examples/speed.c View File

@@ -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 View File

@@ -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
.brq
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



+ 17
- 276
gpio/gpio.c View File

@@ -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:
@@ -392,160 +383,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:
@@ -630,142 +484,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:
@@ -1486,13 +1227,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:



+ 8
- 11
wiringPi/wiringPi.c View File

@@ -395,9 +395,6 @@ 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,
@@ -414,7 +411,7 @@ static int lineFds [64] =
-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,
@@ -2323,7 +2320,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
@@ -2338,10 +2335,10 @@ int waitForInterrupt (int pin, int mS)
} else {
//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) ;
@@ -2407,7 +2404,7 @@ 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);
@@ -2421,7 +2418,7 @@ 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]) ;
}
@@ -2434,9 +2431,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


+ 0
- 63
wiringPi/wiringPiLegacy.c View File

@@ -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…
Cancel
Save