Add GPIO reset support for the RaspberryPi.

This commit is contained in:
David Betz 2015-01-26 22:14:34 -05:00
parent 4e4f90c107
commit 6adc7f3c1e
3 changed files with 113 additions and 22 deletions

View File

@ -2,7 +2,7 @@
* @file osint.h
*
* Serial I/O functions used by PLoadLib.c
*
*
* Copyright (c) 2009 by John Steven Denson
* Modified in 2011 by David Michael Betz
*
@ -35,8 +35,11 @@
/* serial i/o definitions */
#define SERIAL_TIMEOUT -1
/* Method of issuing reset to the Propeller chip. */
typedef enum {RESET_WITH_RTS, RESET_WITH_DTR, RESET_WITH_GPIO} reset_method_t;
/* serial i/o routines */
void serial_use_rts_for_reset(int use_rts);
int use_reset_method(char* method);
int serial_find(const char* prefix, int (*check)(const char* port, void* data), void* data);
int serial_init(const char *port, unsigned long baud);
int serial_baud(unsigned long baud);

View File

@ -44,17 +44,37 @@
#include <signal.h>
#include "osint.h"
#ifdef RASPBERRY_PI
#include "gpio_sysfs.h"
#endif
typedef int HANDLE;
static HANDLE hSerial = -1;
static struct termios old_sparm;
static int continue_terminal = 1;
/* normally we use DTR for reset but setting this variable to non-zero will use RTS instead */
static int use_rts_for_reset = 0;
/* Normally we use DTR for reset */
static reset_method_t reset_method = RESET_WITH_DTR;
void serial_use_rts_for_reset(int use_rts)
int use_reset_method(char* method)
{
use_rts_for_reset = use_rts;
if (strcasecmp(method, "dtr") == 0)
reset_method = RESET_WITH_DTR;
else if (strcasecmp(method, "rts") == 0)
reset_method = RESET_WITH_RTS;
#ifdef RASPBERRY_PI
else if (strcasecmp(method, "gpio") == 0)
{
reset_method = RESET_WITH_GPIO;
gpio_export(17);
gpio_write(17, 0);
gpio_direction(17, 1);
}
#endif
else {
return -1;
}
return 0;
}
static void chk(char *fun, int sts)
@ -89,19 +109,19 @@ int serial_find(const char* prefix, int (*check)(const char* port, void* data),
static void sigint_handler(int signum)
{
serial_done();
exit(1);
serial_done();
continue_terminal = 0;
}
/**
* open serial port
* @param port - COMn port name
* @param baud - baud rate
* @returns 1 for success and 0 for failure
* @returns hSerial - file handle to serial port
*/
int serial_init(const char* port, unsigned long baud)
{
struct termios sparm;
int tbaud = 0;
/* open the port */
#ifdef MACOSX
@ -124,7 +144,7 @@ int serial_init(const char* port, unsigned long baud)
}
fcntl(hSerial, F_SETFL, 0);
/* set the baud rate */
if (!serial_baud(baud)) {
close(hSerial);
@ -137,9 +157,10 @@ int serial_init(const char* port, unsigned long baud)
/* set raw input */
#ifdef MACOSX
cfmakeraw(&sparm);
sparm.c_cc[VTIME] = 0;
sparm.c_cc[VMIN] = 1;
cfmakeraw(&sparm);
sparm.c_cc[VTIME] = 0;
sparm.c_cc[VMIN] = 1;
chk("cfsetspeed", cfsetspeed(&sparm, tbaud));
#else
memset(&sparm, 0, sizeof(sparm));
sparm.c_cflag = CS8 | CLOCAL | CREAD;
@ -149,6 +170,8 @@ int serial_init(const char* port, unsigned long baud)
sparm.c_iflag = IGNPAR | IGNBRK;
sparm.c_cc[VTIME] = 0;
sparm.c_cc[VMIN] = 1;
chk("cfsetispeed", cfsetispeed(&sparm, tbaud));
chk("cfsetospeed", cfsetospeed(&sparm, tbaud));
#endif
/* set the options */
@ -266,6 +289,12 @@ void serial_done(void)
close(hSerial);
hSerial = -1;
}
#ifdef RASPBERRY_PI
if (reset_method == RESET_WITH_GPIO)
{
gpio_unexport(17);
}
#endif
}
/**
@ -336,16 +365,72 @@ int rx_timeout(uint8_t* buff, int n, int timeout)
}
/**
* hwreset ... resets Propeller hardware using DTR or RTS
* @param sparm - pointer to DCB serial control struct
* assert_reset ... Asserts the Propellers reset signal via DTR, RTS or GPIO pin.
* @returns void
*/
static void assert_reset(void)
{
int cmd;
switch (reset_method)
{
case RESET_WITH_DTR:
cmd = TIOCM_DTR;
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
break;
case RESET_WITH_RTS:
cmd = TIOCM_RTS;
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
break;
#ifdef RASPBERRY_PI
case RESET_WITH_GPIO:
gpio_write(17, 1);
break;
#endif
default:
// should be reached
break;
}
}
/**
* deassert_reset ... Deasserts the Propellers reset signal via DTR, RTS or GPIO pin.
* @returns void
*/
static void deassert_reset(void)
{
int cmd;
switch (reset_method)
{
case RESET_WITH_DTR:
cmd = TIOCM_DTR;
ioctl(hSerial, TIOCMBIC, &cmd); /* assert bit */
break;
case RESET_WITH_RTS:
cmd = TIOCM_RTS;
ioctl(hSerial, TIOCMBIC, &cmd); /* assert bit */
break;
#ifdef RASPBERRY_PI
case RESET_WITH_GPIO:
gpio_write(17, 0);
break;
#endif
default:
// should be reached
break;
}
}
/**
* hwreset ... resets Propeller hardware.
* @returns void
*/
void hwreset(void)
{
int cmd = use_rts_for_reset ? TIOCM_RTS : TIOCM_DTR;
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
assert_reset();
msleep(10);
ioctl(hSerial, TIOCMBIC, &cmd); /* clear bit */
deassert_reset();
msleep(90);
tcflush(hSerial, TCIFLUSH);
}
@ -377,18 +462,17 @@ void msleep(int ms)
void terminal_mode(int check_for_exit, int pst_mode)
{
struct termios oldt, newt;
char buf[128], realbuf[256]; // double in case buf is filled with \r in PST mode
char buf[128], realbuf[256];
ssize_t cnt;
fd_set set;
int exit_char = 0xdead; /* not a valid character */
int sawexit_char = 0;
int sawexit_valid = 0;
int exitcode = 0;
int continue_terminal = 1;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO | ISIG);
newt.c_lflag &= ~(ICANON | ECHO);
newt.c_iflag &= ~(ICRNL | INLCR);
newt.c_oflag &= ~OPOST;
tcsetattr(STDIN_FILENO, TCSANOW, &newt);

View File

@ -156,6 +156,10 @@ int main(int argc, char *argv[])
}
}
#ifdef RASPBERRY_PI
use_reset_method("gpio");
#endif
switch (InitPort(PORT_PREFIX, port, baudRate, verbose, actualPort)) {
case CHECK_PORT_OK:
printf("Found propeller version %d on %s\n", version, actualPort);