Add GPIO reset support for the RaspberryPi.
This commit is contained in:
parent
4e4f90c107
commit
6adc7f3c1e
7
osint.h
7
osint.h
@ -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);
|
||||||
|
124
osint_linux.c
124
osint_linux.c
@ -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);
|
||||||
|
4
p1load.c
4
p1load.c
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user