Merged from git.drogon.net, SPI driver helpers, C++ wrappers, softPwm, piNes, gertboard, SPI

This commit is contained in:
Gordon Henderson
2012-08-28 18:37:54 +01:00
committed by Philip Howard
parent 21f0472265
commit ae40bdaf6a
22 changed files with 1708 additions and 279 deletions

View File

@@ -41,7 +41,7 @@ OBJ = gpio.o
all: gpio
gpio: gpio.o
gpio: gpio.o /usr/local/lib/libwiringPi.a
@echo [LD]
@$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS)

View File

@@ -4,28 +4,55 @@
gpio \- Command-line access to Raspberry Pi and PiFace GPIO
.SH SYNOPSIS
.TP
.B gpio
.RB [ \-v ]
.TP
.B \-v
.PP
.B gpio
.RB [ \-g ]
.RB < read/write/pwm/mode ...>
.TP
.B [ \-g ]
.B read/write/pwm/mode ...
.PP
.B gpio
.RB [ \-p ]
.RB < read/write/mode ...>
.TP
.B [ \-p ]
.B read/write/mode
.B ...
.PP
.B gpio
.RB < export/edge/unexport/unexportall/exports ...>
.B unexportall/exports
.PP
.B gpio
.B export/edge/unexport
.B ...
.PP
.B gpio
.B drive
group value
.PP
.B gpio
.B pwm-bal/pwm-ms
.PP
.B gpio
.B pwmr
range
.PP
.B gpio
.B load \ i2c/spi
.PP
.B gpio
.B gbr
channel
.PP
.B gpio
.B gbw
channel value
.SH DESCRIPTION
.B GPIO
is a command line tool to allow the user easy access to the GPIO pins
on the Raspberry Pi. It's designed for simple testing and diagnostic
purposes, but can be used in shell scripts for general if somewhat slow
control of the GPIO pins.
is a swiss army knofe of a command line tool to allow the user easy
access to the GPIO pins on the Raspberry Pi and the SPI A/D and D/A
convertors on the Gertboard. It's designed for simple testing and
diagnostic purposes, but can be used in shell scripts for general if
somewhat slow control of the GPIO pins.
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
@@ -64,6 +91,14 @@ Set a pin into \fIinput\fR, \fIoutput\fR or \fIpwm\fR mode. Can also
use the literals \fIup\fR, \fIdown\fR or \fItri\fR to set the internal
pull-up, pull-down or tristate (off) controls.
.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
@@ -96,12 +131,41 @@ requiring root/sudo.
Un-Export a GPIO pin in the /sys/class/gpio directory.
.TP
.B unexportall
Un-Export all the GPIO pins in the /sys/class/gpio directory.
.B drive
group value
Change the pad driver value for the given pad group to the supplied drive
value. Group is 0, 1 or 2 and value is 0-7. Do not use unless you are
absolutely sure you know what you're doing.
.TP
.B exports
Print a list (if any) of all the exported GPIO pins and their current values.
.B pwm-bal/pwm-ms
Change the PWM mode to balanced (the default) or mark:space ratio (traditional)
.TP
.B pwmr
Change the PWM range register. The default is 1024.
.TP
.B load i2c/spi
This loads the i2c or the spi drivers into the system and changes the permissions on
the associated /dev/ entries so that the current user has access to them.
.TP
.B gbr
channel
This reads the analog to digital convertor on the Gertboard on the given
channel. The board jumpers need to be in-place to do this operation.
.TP
.B gbw
channel value
This writes the supplied value to the output channel on the Gertboards
SPI digital to analogue convertor.
The board jumpers need to be in-place to do this operation.
.SH "WiringPi vs. GPIO Pin numbering"
@@ -170,7 +234,7 @@ Gordon Henderson
.SH "REPORTING BUGS"
Report bugs to <gordon@drogon.net>
Report bugs to <projects@drogon.net>
.SH COPYRIGHT

View File

@@ -1,6 +1,7 @@
/*
* gpio.c:
* Set-UID command-line interface to the Raspberry Pi's GPIO
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
* Pi's GPIO.
* Copyright (c) 2012 Gordon Henderson
***********************************************************************
* This file is part of wiringPi:
@@ -21,7 +22,6 @@
***********************************************************************
*/
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
@@ -32,15 +32,144 @@
#include <sys/types.h>
#include <fcntl.h>
#include <wiringPi.h>
#include <gertboard.h>
#define VERSION "1.0"
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
#define VERSION "1.2"
static int wpMode ;
char *usage = "Usage: gpio -v\n"
" gpio -h\n"
" gpio [-g] <read/write/pwm/mode> ...\n"
" gpio [-p] <read/write/mode> ...\n"
" gpio <export/edge/unexport/unexportall/exports> ..." ;
" gpio export/edge/unexport/unexportall/exports ...\n"
" gpio drive <group> <value>\n"
" gpio pwm-bal/pwm-ms \n"
" gpio pwmr <range> \n"
" gpio load spi/i2c\n"
" gpio gbr <channel>\n"
" gpio gbw <channel> <value>\n" ;
/*
* changeOwner:
* Change the ownership of the file to the real userId of the calling
* program so we can access it.
*********************************************************************************
*/
static void changeOwner (char *cmd, char *file)
{
uid_t uid = getuid () ;
uid_t gid = getgid () ;
if (chown (file, uid, gid) != 0)
{
if (errno == ENOENT) // Warn that it's not there
fprintf (stderr, "%s: Warning: File not present: %s\n", cmd, file) ;
else
{
fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
exit (1) ;
}
}
}
/*
* moduleLoaded:
* Return true/false if the supplied module is loaded
*********************************************************************************
*/
static int moduleLoaded (char *modName)
{
int len = strlen (modName) ;
int found = FALSE ;
FILE *fd = fopen ("/proc/modules", "r") ;
char line [80] ;
if (fd == NULL)
{
fprintf (stderr, "gpio: Unable to check modules: %s\n", strerror (errno)) ;
exit (1) ;
}
while (fgets (line, 80, fd) != NULL)
{
if (strncmp (line, modName, len) != 0)
continue ;
found = TRUE ;
break ;
}
fclose (fd) ;
return found ;
}
/*
* doLoad:
* Load either the spi or i2c modules and change device ownerships, etc.
*********************************************************************************
*/
static void _doLoadUsage (char *argv [])
{
fprintf (stderr, "Usage: %s load <spi/i2c>\n", argv [0]) ;
exit (1) ;
}
static void doLoad (int argc, char *argv [])
{
char *module ;
char cmd [80] ;
char *file1, *file2 ;
if (argc != 3)
_doLoadUsage (argv) ;
/**/ if (strcasecmp (argv [2], "spi") == 0)
{
module = "spi_bcm2708" ;
file1 = "/dev/spidev0.0" ;
file2 = "/dev/spidev0.1" ;
}
else if (strcasecmp (argv [2], "i2c") == 0)
{
module = "i2c_bcm2708" ;
file1 = "/dev/i2c-0" ;
file2 = "/dev/i2c-1" ;
}
else
_doLoadUsage (argv) ;
if (!moduleLoaded (module))
{
sprintf (cmd, "modprobe %s", module) ;
system (cmd) ;
}
if (!moduleLoaded (module))
{
fprintf (stderr, "%s: Unable to load %s\n", argv [0], module) ;
exit (1) ;
}
sleep (1) ; // To let things get settled
changeOwner (argv [0], file1) ;
changeOwner (argv [0], file2) ;
}
/*
@@ -49,7 +178,7 @@ char *usage = "Usage: gpio -v\n"
*********************************************************************************
*/
void doExports (void)
static void doExports (int argc, char *argv [])
{
int fd ;
int i, l, first ;
@@ -140,8 +269,6 @@ void doExport (int argc, char *argv [])
int pin ;
char *mode ;
char fName [128] ;
uid_t uid ;
gid_t gid ;
if (argc != 4)
{
@@ -183,27 +310,11 @@ void doExport (int argc, char *argv [])
// Change ownership so the current user can actually use it!
uid = getuid () ;
gid = getgid () ;
sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
// Also change ownership of the edge file - if it exists
changeOwner (argv [0], fName) ;
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
if (chown (fName, uid, gid) != 0)
{
if (errno != ENOENT) // Silently ignore File not found - older kernel
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
}
changeOwner (argv [0], fName) ;
}
@@ -222,8 +333,6 @@ void doEdge (int argc, char *argv [])
int pin ;
char *mode ;
char fName [128] ;
uid_t uid ;
gid_t gid ;
if (argc != 4)
{
@@ -231,8 +340,7 @@ void doEdge (int argc, char *argv [])
exit (1) ;
}
pin = atoi (argv [2]) ;
pin = atoi (argv [2]) ;
mode = argv [3] ;
// Export the pin and set direction to input
@@ -263,40 +371,23 @@ void doEdge (int argc, char *argv [])
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") ;
/**/ 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 so the current user can actually use it!
uid = getuid () ;
gid = getgid () ;
// Change ownership of the value and edge files, so the current user can actually use it!
sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
// Also change ownership of the edge file
changeOwner (argv [0], fName) ;
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
changeOwner (argv [0], fName) ;
fclose (fd) ;
}
@@ -383,18 +474,12 @@ void doMode (int argc, char *argv [])
mode = argv [3] ;
/**/ if (strcasecmp (mode, "in") == 0)
pinMode (pin, INPUT) ;
else if (strcasecmp (mode, "out") == 0)
pinMode (pin, OUTPUT) ;
else if (strcasecmp (mode, "pwm") == 0)
pinMode (pin, PWM_OUTPUT) ;
else if (strcasecmp (mode, "up") == 0)
pullUpDnControl (pin, PUD_UP) ;
else if (strcasecmp (mode, "down") == 0)
pullUpDnControl (pin, PUD_DOWN) ;
else if (strcasecmp (mode, "tri") == 0)
pullUpDnControl (pin, PUD_OFF) ;
/**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
else
{
fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
@@ -402,13 +487,125 @@ void doMode (int argc, char *argv [])
}
}
/*
* doPadDrive:
* gpio drive group value
*********************************************************************************
*/
static void doPadDrive (int argc, char *argv [])
{
int group, val ;
if (argc != 4)
{
fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
exit (1) ;
}
group = atoi (argv [2]) ;
val = atoi (argv [3]) ;
if ((group < 0) || (group > 2))
{
fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
exit (1) ;
}
if ((val < 0) || (val > 7))
{
fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
exit (1) ;
}
setPadDrive (group, val) ;
}
/*
* doGbw:
* gpio gbw channel value
*********************************************************************************
*/
static void doGbw (int argc, char *argv [])
{
int channel, value ;
if (argc != 4)
{
fprintf (stderr, "Usage: %s gbr <channel> <value>\n", argv [0]) ;
exit (1) ;
}
channel = atoi (argv [2]) ;
value = atoi (argv [3]) ;
if ((channel < 0) || (channel > 1))
{
fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
exit (1) ;
}
if ((value < 0) || (value > 1023))
{
fprintf (stderr, "%s: value must be from 0 to 255\n", argv [0]) ;
exit (1) ;
}
if (gertboardSPISetup () == -1)
{
fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
exit (1) ;
}
gertboardAnalogWrite (channel, value) ;
}
/*
* doGbr:
* gpio gbr channel
*********************************************************************************
*/
static void doGbr (int argc, char *argv [])
{
int channel ;
if (argc != 3)
{
fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ;
exit (1) ;
}
channel = atoi (argv [2]) ;
if ((channel < 0) || (channel > 1))
{
fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
exit (1) ;
}
if (gertboardSPISetup () == -1)
{
fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
exit (1) ;
}
printf ("%d\n",gertboardAnalogRead (channel)) ;
}
/*
* doWrite:
* gpio write pin value
*********************************************************************************
*/
void doWrite (int argc, char *argv [])
static void doWrite (int argc, char *argv [])
{
int pin, val ;
@@ -489,6 +686,39 @@ void doPwm (int argc, char *argv [])
}
/*
* doPwmMode: doPwmRange:
* Change the PWM mode and Range values
*********************************************************************************
*/
static void doPwmMode (int mode)
{
pwmSetMode (mode) ;
}
static void doPwmRange (int argc, char *argv [])
{
unsigned int range ;
if (argc != 3)
{
fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
exit (1) ;
}
range = (unsigned int)strtoul (argv [2], NULL, 10) ;
if (range == 0)
{
fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
exit (1) ;
}
pwmSetRange (range) ;
}
/*
* main:
* Start here
@@ -505,10 +735,10 @@ int main (int argc, char *argv [])
return 1 ;
}
if (geteuid () != 0)
if (strcasecmp (argv [1], "-h") == 0)
{
fprintf (stderr, "%s: Must be root to run\n", argv [0]) ;
return 1 ;
printf ("%s: %s\n", argv [0], usage) ;
return 0 ;
}
if (strcasecmp (argv [1], "-v") == 0)
@@ -516,21 +746,54 @@ int main (int argc, char *argv [])
printf ("gpio version: %s\n", VERSION) ;
printf ("Copyright (c) 2012 Gordon Henderson\n") ;
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
printf ("For details type: %s -warranty\n", argv [0]) ;
return 0 ;
}
if (strcasecmp (argv [1], "-warranty") == 0)
{
printf ("gpio version: %s\n", VERSION) ;
printf ("Copyright (c) 2012 Gordon Henderson\n") ;
printf ("\n") ;
printf (" This program is free software; you can redistribute it and/or modify\n") ;
printf (" it under the terms of the GNU Leser General Public License as published\n") ;
printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
printf (" (at your option) any later version.\n") ;
printf ("\n") ;
printf (" This program is distributed in the hope that it will be useful,\n") ;
printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
printf (" GNU Lesser General Public License for more details.\n") ;
printf ("\n") ;
printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
printf ("\n") ;
return 0 ;
}
if (geteuid () != 0)
{
fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
return 1 ;
}
// Initial test for /sys/class/gpio operations:
/**/ if (strcasecmp (argv [1], "exports" ) == 0)
{ doExports () ; 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], "unexportall") == 0)
{ doUnexportall (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexport") == 0)
{ doUnexport (argc, argv) ; return 0 ; }
/**/ 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], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
// Check for drive or load commands:
if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; }
if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; }
// Gertboard commands
if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; }
if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; }
// Check for -g argument
@@ -538,7 +801,7 @@ int main (int argc, char *argv [])
{
if (wiringPiSetupGpio () == -1)
{
fprintf (stderr, "%s: Unable to initialise GPIO in GPIO mode.\n", argv [0]) ;
fprintf (stderr, "%s: Unable to initialise GPIO mode.\n", argv [0]) ;
exit (1) ;
}
@@ -570,23 +833,30 @@ int main (int argc, char *argv [])
{
if (wiringPiSetup () == -1)
{
fprintf (stderr, "%s: Unable to initialise GPIO in wiringPi mode\n", argv [0]) ;
fprintf (stderr, "%s: Unable to initialise wiringPi mode\n", argv [0]) ;
exit (1) ;
}
wpMode = WPI_MODE_PINS ;
}
/**/ if (strcasecmp (argv [1], "write" ) == 0)
doWrite (argc, argv) ;
else if (strcasecmp (argv [1], "read" ) == 0)
doRead (argc, argv) ;
else if (strcasecmp (argv [1], "mode" ) == 0)
doMode (argc, argv) ;
else if (strcasecmp (argv [1], "pwm" ) == 0)
doPwm (argc, argv) ;
// Check for PWM operations
if (wpMode != WPI_MODE_PIFACE)
{
if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; }
if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; }
if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; }
}
// Check for wiring commands
/**/ if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ;
else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
else
{
fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode expected)\n", argv [0], argv [1]) ;
fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
exit (1) ;
}
return 0 ;