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 * @file osint.h
* *
* Serial I/O functions used by PLoadLib.c * Serial I/O functions used by PLoadLib.c
* *
* Copyright (c) 2009 by John Steven Denson * Copyright (c) 2009 by John Steven Denson
* Modified in 2011 by David Michael Betz * Modified in 2011 by David Michael Betz
* *
@ -35,8 +35,11 @@
/* serial i/o definitions */ /* serial i/o definitions */
#define SERIAL_TIMEOUT -1 #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 */ /* 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_find(const char* prefix, int (*check)(const char* port, void* data), void* data);
int serial_init(const char *port, unsigned long baud); int serial_init(const char *port, unsigned long baud);
int serial_baud(unsigned long baud); int serial_baud(unsigned long baud);

View File

@ -44,17 +44,37 @@
#include <signal.h> #include <signal.h>
#include "osint.h" #include "osint.h"
#ifdef RASPBERRY_PI
#include "gpio_sysfs.h"
#endif
typedef int HANDLE; typedef int HANDLE;
static HANDLE hSerial = -1; static HANDLE hSerial = -1;
static struct termios old_sparm; 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 */ /* Normally we use DTR for reset */
static int use_rts_for_reset = 0; 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) 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) static void sigint_handler(int signum)
{ {
serial_done(); serial_done();
exit(1); continue_terminal = 0;
} }
/** /**
* open serial port * open serial port
* @param port - COMn port name * @param port - COMn port name
* @param baud - baud rate * @returns hSerial - file handle to serial port
* @returns 1 for success and 0 for failure
*/ */
int serial_init(const char* port, unsigned long baud) int serial_init(const char* port, unsigned long baud)
{ {
struct termios sparm; struct termios sparm;
int tbaud = 0;
/* open the port */ /* open the port */
#ifdef MACOSX #ifdef MACOSX
@ -124,7 +144,7 @@ int serial_init(const char* port, unsigned long baud)
} }
fcntl(hSerial, F_SETFL, 0); fcntl(hSerial, F_SETFL, 0);
/* set the baud rate */ /* set the baud rate */
if (!serial_baud(baud)) { if (!serial_baud(baud)) {
close(hSerial); close(hSerial);
@ -137,9 +157,10 @@ int serial_init(const char* port, unsigned long baud)
/* set raw input */ /* set raw input */
#ifdef MACOSX #ifdef MACOSX
cfmakeraw(&sparm); cfmakeraw(&sparm);
sparm.c_cc[VTIME] = 0; sparm.c_cc[VTIME] = 0;
sparm.c_cc[VMIN] = 1; sparm.c_cc[VMIN] = 1;
chk("cfsetspeed", cfsetspeed(&sparm, tbaud));
#else #else
memset(&sparm, 0, sizeof(sparm)); memset(&sparm, 0, sizeof(sparm));
sparm.c_cflag = CS8 | CLOCAL | CREAD; 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_iflag = IGNPAR | IGNBRK;
sparm.c_cc[VTIME] = 0; sparm.c_cc[VTIME] = 0;
sparm.c_cc[VMIN] = 1; sparm.c_cc[VMIN] = 1;
chk("cfsetispeed", cfsetispeed(&sparm, tbaud));
chk("cfsetospeed", cfsetospeed(&sparm, tbaud));
#endif #endif
/* set the options */ /* set the options */
@ -266,6 +289,12 @@ void serial_done(void)
close(hSerial); close(hSerial);
hSerial = -1; 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 * assert_reset ... Asserts the Propellers reset signal via DTR, RTS or GPIO pin.
* @param sparm - pointer to DCB serial control struct * @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 * @returns void
*/ */
void hwreset(void) void hwreset(void)
{ {
int cmd = use_rts_for_reset ? TIOCM_RTS : TIOCM_DTR; assert_reset();
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
msleep(10); msleep(10);
ioctl(hSerial, TIOCMBIC, &cmd); /* clear bit */ deassert_reset();
msleep(90); msleep(90);
tcflush(hSerial, TCIFLUSH); tcflush(hSerial, TCIFLUSH);
} }
@ -377,18 +462,17 @@ void msleep(int ms)
void terminal_mode(int check_for_exit, int pst_mode) void terminal_mode(int check_for_exit, int pst_mode)
{ {
struct termios oldt, newt; 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; ssize_t cnt;
fd_set set; fd_set set;
int exit_char = 0xdead; /* not a valid character */ int exit_char = 0xdead; /* not a valid character */
int sawexit_char = 0; int sawexit_char = 0;
int sawexit_valid = 0; int sawexit_valid = 0;
int exitcode = 0; int exitcode = 0;
int continue_terminal = 1;
tcgetattr(STDIN_FILENO, &oldt); tcgetattr(STDIN_FILENO, &oldt);
newt = oldt; newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO | ISIG); newt.c_lflag &= ~(ICANON | ECHO);
newt.c_iflag &= ~(ICRNL | INLCR); newt.c_iflag &= ~(ICRNL | INLCR);
newt.c_oflag &= ~OPOST; newt.c_oflag &= ~OPOST;
tcsetattr(STDIN_FILENO, TCSANOW, &newt); 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)) { switch (InitPort(PORT_PREFIX, port, baudRate, verbose, actualPort)) {
case CHECK_PORT_OK: case CHECK_PORT_OK:
printf("Found propeller version %d on %s\n", version, actualPort); printf("Found propeller version %d on %s\n", version, actualPort);