861 lines
18 KiB
C
861 lines
18 KiB
C
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "utils.h"
|
|
#include "sd_GPIO.h"
|
|
|
|
const char *_piModelNames [16] =
|
|
{
|
|
"Model A", // 0
|
|
"Model B", // 1
|
|
"Model A+", // 2
|
|
"Model B+", // 3
|
|
"Pi 2", // 4
|
|
"Alpha", // 5
|
|
"CM", // 6
|
|
"Unknown07", // 07
|
|
"Pi 3", // 08
|
|
"Pi Zero", // 09
|
|
"CM3", // 10
|
|
"Unknown11", // 11
|
|
"Pi Zero-W", // 12
|
|
"Pi 3+", // 13
|
|
"Unknown New 14", // 14
|
|
"Unknown New 15", // 15
|
|
} ;
|
|
|
|
static bool _ever = false;
|
|
void gpioDelay (unsigned int howLong);
|
|
|
|
#ifndef GPIO_SYSFS_MODE
|
|
|
|
static volatile uint32_t * _gpioReg = MAP_FAILED;
|
|
|
|
int piBoardId ()
|
|
{
|
|
FILE *cpuFd ;
|
|
char line [120] ;
|
|
char *c ;
|
|
unsigned int revision ;
|
|
//int bRev, bType, bProc, bMfg, bMem, bWarranty;
|
|
int bType;
|
|
|
|
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
|
|
logMessage (LOG_ERR, "piBoardId: Unable to open /proc/cpuinfo") ;
|
|
|
|
while (fgets (line, 120, cpuFd) != NULL)
|
|
if (strncmp (line, "Revision", 8) == 0)
|
|
break ;
|
|
|
|
fclose (cpuFd) ;
|
|
|
|
if (strncmp (line, "Revision", 8) != 0)
|
|
logMessage (LOG_ERR, "piBoardId: No \"Revision\" line") ;
|
|
|
|
// Chomp trailing CR/NL
|
|
for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
|
|
*c = 0 ;
|
|
|
|
logMessage (LOG_DEBUG, "piBoardId: Revision string: %s\n", line) ;
|
|
|
|
// Scan to the first character of the revision number
|
|
|
|
for (c = line ; *c ; ++c)
|
|
if (*c == ':')
|
|
break ;
|
|
|
|
if (*c != ':')
|
|
logMessage (LOG_ERR, "piBoardId: Unknown \"Revision\" line (no colon)") ;
|
|
|
|
// Chomp spaces
|
|
|
|
++c ;
|
|
while (isspace (*c))
|
|
++c ;
|
|
|
|
if (!isxdigit (*c))
|
|
logMessage (LOG_ERR, "piBoardId: Unknown \"Revision\" line (no hex digit at start of revision)") ;
|
|
|
|
revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x
|
|
|
|
// Check for new way:
|
|
|
|
if ((revision & (1 << 23)) != 0) // New way
|
|
{/*
|
|
bRev = (revision & (0x0F << 0)) >> 0 ;*/
|
|
bType = (revision & (0xFF << 4)) >> 4 ;
|
|
/*
|
|
bProc = (revision & (0x0F << 12)) >> 12 ; // Not used for now.
|
|
bMfg = (revision & (0x0F << 16)) >> 16 ;
|
|
bMem = (revision & (0x07 << 20)) >> 20 ;
|
|
bWarranty = (revision & (0x03 << 24)) != 0 ;
|
|
*/
|
|
|
|
logMessage (LOG_DEBUG, "piBoard Model: %s\n", _piModelNames[bType]) ;
|
|
|
|
return bType;
|
|
}
|
|
|
|
logMessage (LOG_ERR, "piBoard Model: UNKNOWN\n");
|
|
return PI_MODEL_UNKNOWN;
|
|
}
|
|
|
|
bool gpioSetup() {
|
|
int fd;
|
|
unsigned int piGPIObase = 0;
|
|
|
|
switch ( piBoardId() )
|
|
{
|
|
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:
|
|
//case PI_MODEL_UNKNOWN:
|
|
piGPIObase = (GPIO_BASE_P1 + GPIO_OFFSET);
|
|
break ;
|
|
|
|
default:
|
|
piGPIObase = (GPIO_BASE_P2 + GPIO_OFFSET);
|
|
break ;
|
|
}
|
|
|
|
fd = open("/dev/mem", O_RDWR | O_SYNC);
|
|
|
|
if (fd<0)
|
|
{
|
|
logMessage (LOG_ERR, "Failed to open '/dev/mem' for GPIO access (are we root?)\n");
|
|
return false;
|
|
}
|
|
|
|
_gpioReg = mmap
|
|
(
|
|
0,
|
|
GPIO_LEN,
|
|
PROT_READ|PROT_WRITE|PROT_EXEC,
|
|
MAP_SHARED|MAP_LOCKED,
|
|
fd,
|
|
piGPIObase);
|
|
|
|
close(fd);
|
|
|
|
_ever = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
int pinMode(unsigned gpio, unsigned mode) {
|
|
int reg, shift;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
reg = gpio / 10;
|
|
shift = (gpio % 10) * 3;
|
|
|
|
_gpioReg[reg] = (_gpioReg[reg] & ~(7 << shift)) | (mode << shift);
|
|
|
|
return true;
|
|
}
|
|
|
|
int getPinMode(unsigned gpio) {
|
|
int reg, shift;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
reg = gpio / 10;
|
|
shift = (gpio % 10) * 3;
|
|
|
|
return (*(_gpioReg + reg) >> shift) & 7;
|
|
}
|
|
|
|
int digitalRead(unsigned gpio) {
|
|
unsigned bank, bit;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
bank = gpio >> 5;
|
|
|
|
bit = (1 << (gpio & 0x1F));
|
|
|
|
if ((*(_gpioReg + GPLEV0 + bank) & bit) != 0)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int digitalWrite(unsigned gpio, unsigned level) {
|
|
unsigned bank, bit;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
bank = gpio >> 5;
|
|
|
|
bit = (1 << (gpio & 0x1F));
|
|
|
|
if (level == 0)
|
|
*(_gpioReg + GPCLR0 + bank) = bit;
|
|
else
|
|
*(_gpioReg + GPSET0 + bank) = bit;
|
|
|
|
return true;
|
|
}
|
|
|
|
int setPullUpDown(unsigned gpio, unsigned pud)
|
|
{
|
|
unsigned bank, bit;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
bank = gpio >> 5;
|
|
|
|
bit = (1 << (gpio & 0x1F));
|
|
|
|
/*
|
|
if (gpio > PI_MAX_GPIO)
|
|
SOFT_ERROR(PI_BAD_GPIO, "bad gpio (%d)", gpio);
|
|
*/
|
|
if (pud > PUD_UP || pud < PUD_OFF)
|
|
return false;
|
|
//SOFT_ERROR(PI_BAD_PUD, "gpio %d, bad pud (%d)", gpio, pud);
|
|
|
|
*(_gpioReg + GPPUD) = pud;
|
|
gpioDelay(1);
|
|
*(_gpioReg + GPPUDCLK0 + bank) = bit;
|
|
gpioDelay(1);
|
|
*(_gpioReg + GPPUD) = 0;
|
|
|
|
*(_gpioReg + GPPUDCLK0 + bank) = 0;
|
|
|
|
return true;
|
|
}
|
|
#else
|
|
|
|
bool gpioSetup() {return true;}
|
|
|
|
int pinMode (unsigned pin, unsigned mode)
|
|
{
|
|
//static const char s_directions_str[] = "in\0out\0";
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
char path[SYSFS_PATH_MAX];
|
|
int fd;
|
|
/*
|
|
if ( pinExport(pin) != true) {
|
|
logMessage (LOG_DEBUG, "start pinMode (pinExport) failed\n");
|
|
return false;
|
|
}
|
|
*/
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/direction", pin);
|
|
fd = open(path, O_WRONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open gpio direction for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open gpio '%s' for writing!\n",path);
|
|
return false;
|
|
}
|
|
|
|
//if (-1 == write(fd, &s_directions_str[INPUT == mode ? 0 : 3], INPUT == mode ? 2 : 3)) {
|
|
if (-1 == write(fd, (INPUT==mode?"in\n":"out\n"),(INPUT==mode?3:4))) {
|
|
//fprintf(stderr, "Failed to set direction!\n");
|
|
logMessage (LOG_ERR, "Failed to setup gpio input/output on '%s'!\n",path);
|
|
displayLastSystemError("");
|
|
return false;
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return true;
|
|
}
|
|
|
|
int getPinMode(unsigned gpio) {
|
|
char path[SYSFS_PATH_MAX];
|
|
char value_str[SYSFS_READ_MAX];
|
|
int fd;
|
|
|
|
if (! validGPIO(gpio))
|
|
return -1;
|
|
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/direction", gpio);
|
|
fd = open(path, O_RDONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open gpio direction for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open gpio '%s' for reading!\n",path);
|
|
return false;
|
|
}
|
|
|
|
if (-1 == read(fd, value_str, SYSFS_READ_MAX)) {
|
|
//fprintf(stderr, "Failed to read value!\n");
|
|
logMessage (LOG_ERR, "Failed to read value on '%s'!\n",path);
|
|
displayLastSystemError("");
|
|
return(-1);
|
|
}
|
|
|
|
close(fd);
|
|
|
|
if (strcasecmp(value_str, "out")==0)
|
|
return OUTPUT;
|
|
|
|
return INPUT;
|
|
}
|
|
|
|
int digitalRead (unsigned pin)
|
|
{
|
|
char path[SYSFS_PATH_MAX];
|
|
char value_str[SYSFS_READ_MAX];
|
|
int fd;
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/value", pin);
|
|
fd = open(path, O_RDONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open gpio value for reading!\n");
|
|
logMessage (LOG_ERR, "Failed to open gpio '%s' for reading!\n",path);
|
|
return(-1);
|
|
}
|
|
|
|
if (-1 == read(fd, value_str, SYSFS_READ_MAX)) {
|
|
//fprintf(stderr, "Failed to read value!\n");
|
|
logMessage (LOG_ERR, "Failed to read value on '%s'!\n",path);
|
|
displayLastSystemError("");
|
|
return(-1);
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return(atoi(value_str));
|
|
}
|
|
|
|
int digitalWrite (unsigned pin, unsigned value)
|
|
{
|
|
//static const char s_values_str[] = "01";
|
|
|
|
char path[SYSFS_PATH_MAX];
|
|
int fd;
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/value", pin);
|
|
fd = open(path, O_WRONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open gpio value for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open gpio '%s' for writing!\n",path);
|
|
return false;
|
|
}
|
|
|
|
//if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) {
|
|
if (1 != write(fd, (LOW==value?"0":"1"), 1)) {
|
|
//fprintf(stderr, "Failed to write value!\n");
|
|
logMessage (LOG_ERR, "Failed to write value to '%s'!\n",path);
|
|
displayLastSystemError("");
|
|
return false;
|
|
}
|
|
|
|
close(fd);
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
void gpioDelay (unsigned int howLong) // Microseconds (1000000 = 1 second)
|
|
{
|
|
struct timespec sleeper, dummy ;
|
|
|
|
sleeper.tv_sec = (time_t)(howLong / 1000) ;
|
|
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
|
|
|
|
nanosleep (&sleeper, &dummy) ;
|
|
}
|
|
|
|
bool isExported(unsigned pin)
|
|
{
|
|
char path[SYSFS_PATH_MAX];
|
|
struct stat sb;
|
|
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/", pin);
|
|
|
|
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool pinExport(unsigned pin)
|
|
{
|
|
|
|
char buffer[SYSFS_READ_MAX];
|
|
ssize_t bytes_written;
|
|
int fd;
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
fd = open("/sys/class/gpio/export", O_WRONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open export for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/export' for writing!\n");
|
|
return false;
|
|
}
|
|
|
|
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
|
|
write(fd, buffer, bytes_written);
|
|
close(fd);
|
|
return true;
|
|
}
|
|
|
|
bool pinUnexport(unsigned pin)
|
|
{
|
|
char buffer[SYSFS_READ_MAX];
|
|
ssize_t bytes_written;
|
|
int fd;
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
fd = open("/sys/class/gpio/unexport", O_WRONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open unexport for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/unexport' for writing!\n");
|
|
return false;
|
|
}
|
|
|
|
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
|
|
write(fd, buffer, bytes_written);
|
|
close(fd);
|
|
return true;
|
|
}
|
|
|
|
bool edgeSetup (unsigned pin, unsigned value)
|
|
{
|
|
//static const char s_values_str[] = "01";
|
|
|
|
char path[SYSFS_PATH_MAX];
|
|
int fd;
|
|
|
|
if (! validGPIO(pin))
|
|
return -1;
|
|
|
|
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/edge", pin);
|
|
fd = open(path, O_WRONLY);
|
|
if (-1 == fd) {
|
|
//fprintf(stderr, "Failed to open gpio value for writing!\n");
|
|
logMessage (LOG_ERR, "Failed to open gpio '%s' for writing!\n",path);
|
|
return false;
|
|
}
|
|
|
|
int rtn = 0;
|
|
if (value==INT_EDGE_RISING)
|
|
rtn = write(fd, "rising", 6);
|
|
else if (value==INT_EDGE_FALLING)
|
|
rtn = write(fd, "falling", 7);
|
|
else if (value==INT_EDGE_BOTH)
|
|
rtn = write(fd, "both", 4);
|
|
else
|
|
rtn = write(fd, "none", 4);
|
|
|
|
if (rtn <= 0) {
|
|
logMessage (LOG_ERR, "Failed to setup edge on '%s'!\n",path);
|
|
displayLastSystemError("");
|
|
return false;
|
|
}
|
|
|
|
close(fd);
|
|
return true;
|
|
}
|
|
|
|
#include <poll.h>
|
|
#include <pthread.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
struct threadGPIOinterupt{
|
|
void (*function)(void *args);
|
|
void *args;
|
|
unsigned pin;
|
|
};
|
|
static pthread_mutex_t pinMutex ;
|
|
|
|
#define MAX_FDS 64
|
|
static unsigned int _sysFds [MAX_FDS] =
|
|
{
|
|
-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,
|
|
} ;
|
|
|
|
void pushSysFds(int fd)
|
|
{
|
|
int i;
|
|
for (i=0; i< MAX_FDS; i++) {
|
|
if (_sysFds[i] == -1) {
|
|
_sysFds[i] = fd;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gpioShutdown() {
|
|
int i;
|
|
_ever = false;
|
|
|
|
for (i=0; i< MAX_FDS; i++) {
|
|
if (_sysFds[i] != -1) {
|
|
//printf("Closing fd %d\n",i);
|
|
close(_sysFds[i]);
|
|
_sysFds[i] = -1;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int waitForInterrupt (int pin, int mS, int fd)
|
|
{
|
|
int x;
|
|
uint8_t c ;
|
|
struct pollfd polls ;
|
|
|
|
// Setup poll structure
|
|
polls.fd = fd ;
|
|
polls.events = POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
|
|
|
// Wait for something ...
|
|
|
|
x = poll (&polls, 1, mS) ;
|
|
|
|
// If no error, do a dummy read to clear the interrupt
|
|
// A one character read appars to be enough.
|
|
|
|
if (x > 0)
|
|
{
|
|
lseek (fd, 0, SEEK_SET) ; // Rewind
|
|
(void)read (fd, &c, 1) ; // Read & clear
|
|
}
|
|
|
|
return x ;
|
|
}
|
|
|
|
static void *interruptHandler (void *arg)
|
|
{
|
|
struct threadGPIOinterupt *stuff = (struct threadGPIOinterupt *) arg;
|
|
int pin = stuff->pin;
|
|
void (*function)(void *args) = stuff->function;
|
|
void *args = stuff->args;
|
|
stuff->pin = -1;
|
|
|
|
char path[SYSFS_PATH_MAX];
|
|
int fd, count, i ;
|
|
uint8_t c ;
|
|
|
|
sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
|
|
|
|
if ((fd = open(path, O_RDONLY)) < 0)
|
|
{
|
|
logMessage (LOG_ERR, "Failed to open '%s'!\n",path);
|
|
return NULL;
|
|
}
|
|
|
|
pushSysFds(fd);
|
|
|
|
// Clear any initial pending interrupt
|
|
ioctl (fd, FIONREAD, &count) ;
|
|
for (i = 0 ; i < count ; ++i)
|
|
read (fd, &c, 1);
|
|
|
|
while (_ever == true) {
|
|
if (waitForInterrupt (pin, -1, fd) > 0) {
|
|
function(args);
|
|
} else {
|
|
printf("SOMETHING FAILED, reset\n");
|
|
gpioDelay(1);
|
|
}
|
|
}
|
|
|
|
printf("interruptHandler ended\n");
|
|
|
|
close(fd);
|
|
return NULL ;
|
|
}
|
|
|
|
|
|
bool registerGPIOinterrupt(int pin, int mode, void (*function)(void *args), void *args )
|
|
{
|
|
pthread_t threadId ;
|
|
struct threadGPIOinterupt stuff;
|
|
|
|
if (! validGPIO(pin))
|
|
return false;
|
|
|
|
// Check it's exported
|
|
if (! isExported(pin))
|
|
pinExport(pin);
|
|
|
|
// if the pin is putput, set as input to setup edge then reset to output.
|
|
if (getPinMode(pin) == OUTPUT) {
|
|
pinMode(pin, INPUT);
|
|
edgeSetup(pin, mode);
|
|
pinMode(pin, OUTPUT);
|
|
} else {
|
|
edgeSetup(pin, mode);
|
|
}
|
|
|
|
stuff.function = function;
|
|
stuff.args = args;
|
|
stuff.pin = pin;
|
|
|
|
pthread_mutex_lock (&pinMutex) ;
|
|
if (pthread_create (&threadId, NULL, interruptHandler, (void *)&stuff) < 0)
|
|
return false;
|
|
else {
|
|
while (stuff.pin == pin)
|
|
gpioDelay(1);
|
|
}
|
|
|
|
pthread_mutex_unlock (&pinMutex) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
#if defined(TEST_HARNESS) || defined(GPIO_MONITOR) || defined(GPIO_RW)
|
|
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
int _log_level = LOG_DEBUG;
|
|
|
|
void logMessage(int level, char *format, ...)
|
|
{
|
|
if (level > _log_level)
|
|
return;
|
|
|
|
char buffer[256];
|
|
va_list args;
|
|
va_start(args, format);
|
|
strncpy(buffer, " ", 8);
|
|
int size = vsnprintf (&buffer[8], 246-10, format, args);
|
|
va_end(args);
|
|
|
|
fprintf (stderr, buffer);
|
|
}
|
|
void displayLastSystemError (const char *on_what)
|
|
{
|
|
fputs (strerror (errno), stderr);
|
|
fputs (": ", stderr);
|
|
fputs (on_what, stderr);
|
|
fputc ('\n', stderr);
|
|
|
|
logMessage (LOG_ERR, "%d : %s", errno, on_what);
|
|
|
|
}
|
|
|
|
#endif //TEST_HARNESS || GPIO_MONITOR
|
|
|
|
#ifdef GPIO_RW
|
|
|
|
void errorParms()
|
|
{
|
|
printf("Missing Parameters:-\n\t[read|write] pin <value>\n\tgpio write 17 1\n");
|
|
exit(1);
|
|
}
|
|
int main(int argc, char *argv[]) {
|
|
|
|
bool isWrite=false;
|
|
int pin = 0;
|
|
int value = 0;
|
|
|
|
_log_level = LOG_ERR;
|
|
|
|
if (argc < 3) {
|
|
errorParms();
|
|
}
|
|
|
|
if (strcmp (argv[1], "read") == 0)
|
|
{
|
|
isWrite = false;
|
|
} else if (strcmp (argv[1], "write") == 0) {
|
|
isWrite = true;
|
|
if (argc < 4)
|
|
errorParms();
|
|
} else {
|
|
errorParms();
|
|
}
|
|
|
|
pin = atoi(argv[2]);
|
|
|
|
if (! gpioSetup()) {
|
|
logMessage (LOG_ERR, "Failed to setup GPIO\n");
|
|
return 1;
|
|
}
|
|
|
|
if (isWrite) {
|
|
value = atoi(argv[3]);
|
|
int pmode = getPinMode(pin);
|
|
pinMode (pin, OUTPUT);
|
|
digitalWrite(pin, value);
|
|
//if (pmode != OUTPUT)
|
|
// pinMode (pin, pmode);
|
|
}
|
|
|
|
printf ("%d\n", digitalRead(pin));
|
|
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef GPIO_MONITOR
|
|
|
|
bool FOREVER = true;
|
|
|
|
void intHandler(int signum) {
|
|
static int called=0;
|
|
logMessage (LOG_INFO, "Stopping! - signel(%d)\n",signum);
|
|
gpioShutdown();
|
|
FOREVER = false;
|
|
called++;
|
|
if (called > 3)
|
|
exit(1);
|
|
}
|
|
|
|
void event_trigger (int pin)
|
|
{
|
|
printf("Pin %d triggered, state=%d\n",pin,digitalRead(pin));
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
int i;
|
|
|
|
if (! gpioSetup()) {
|
|
logMessage (LOG_ERR, "Failed to setup GPIO\n");
|
|
return 1;
|
|
}
|
|
|
|
signal(SIGINT, intHandler);
|
|
signal(SIGTERM, intHandler);
|
|
signal(SIGSEGV, intHandler);
|
|
|
|
for (i=GPIO_MIN; i <= GPIO_MAX; i++) {
|
|
printf ("Pin %d is %d\n", i, digitalRead(i));
|
|
if (registerGPIOinterrupt (i, INT_EDGE_BOTH, (void *)&event_trigger, (void *)i) != true)
|
|
{
|
|
displayLastSystemError ("Unable to set interrupt handler for specified pin, exiting");
|
|
gpioShutdown();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
while(FOREVER) {
|
|
sleep(10);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif //GPIO_MONITOR
|
|
|
|
//#define TEST_HARNESS
|
|
|
|
#ifdef TEST_HARNESS
|
|
|
|
#define GPIO_OFF 0x00005000 /* Offset from IO_START to the GPIO reg's. */
|
|
|
|
/* IO_START and IO_BASE are defined in hardware.h */
|
|
|
|
#define GPIO_START (IO_START_2 + GPIO_OFF) /* Physical addr of the GPIO reg. */
|
|
#define GPIO_BASE_NEW (IO_BASE_2 + GPIO_OFF) /* Virtual addr of the GPIO reg. */
|
|
|
|
|
|
void *myCallBack(void * args) {
|
|
printf("Ping\n");
|
|
//struct threadGPIOinterupt *stuff = (struct threadGPIOinterupt *) args;
|
|
//printf("Pin is %d\n",stuff->pin);
|
|
}
|
|
|
|
#define PIN 17
|
|
#define POUT 27
|
|
int main(int argc, char *argv[]) {
|
|
|
|
int repeat = 3;
|
|
|
|
// if (-1 == GPIOExport(POUT) || -1 == GPIOExport(PIN))
|
|
// return(1);
|
|
gpioSetup();
|
|
/*
|
|
pinUnexport(POUT);
|
|
pinUnexport(PIN);
|
|
pinExport(POUT);
|
|
pinExport(PIN);
|
|
*/
|
|
sleep(1);
|
|
|
|
//edgeSetup(POUT, INT_EDGE_BOTH);
|
|
|
|
if (-1 == pinMode(POUT, OUTPUT) || -1 == pinMode(PIN, INPUT))
|
|
return (2);
|
|
|
|
//edgeSetup(PIN, INT_EDGE_RISING);
|
|
//edgeSetup(POUT, INT_EDGE_RISING);
|
|
|
|
if (pinExport(POUT) != true)
|
|
printf("Error exporting pin\n");
|
|
/*
|
|
if (registerGPIOinterrupt(POUT, INT_EDGE_RISING, (void *)&myCallBack, (void *)&repeat ) != true)
|
|
printf("Error registering interupt\n");
|
|
|
|
if (registerGPIOinterrupt(PIN, INT_EDGE_RISING, (void *)&myCallBack, (void *)&repeat ) != true)
|
|
printf("Error registering interupt\n");
|
|
*/
|
|
|
|
do {
|
|
|
|
printf("Writing %d to GPIO %d\n", repeat % 2, POUT);
|
|
if (-1 == digitalWrite(POUT, repeat % 2))
|
|
return (3);
|
|
|
|
|
|
printf("Read %d from GPIO %d (input)\n", digitalRead(PIN), PIN);
|
|
printf("Read %d from GPIO %d (output)\n", digitalRead(POUT), POUT);
|
|
|
|
usleep(500 * 1000);
|
|
} while (repeat--);
|
|
|
|
gpioShutdown();
|
|
|
|
sleep(1);
|
|
|
|
if (-1 == pinUnexport(POUT) || -1 == pinUnexport(PIN))
|
|
return (4);
|
|
|
|
sleep(1);
|
|
|
|
return (0);
|
|
}
|
|
#endif |