sport: serial IO abstraction layer.
This commit is contained in:
parent
eee0bc0352
commit
b8dd765a5b
2
Makefile
2
Makefile
|
@ -65,7 +65,7 @@ mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
|
|||
fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o \
|
||||
cmddb.o stdcmd.o prog.o flash_bsl.o list.o simio.o simio_tracer.o \
|
||||
simio_timer.o simio_wdt.o simio_hwmult.o simio_gpio.o aliasdb.o \
|
||||
gdb_proto.o gdbc.o
|
||||
gdb_proto.o gdbc.o sport.o
|
||||
$(CC) $(LDFLAGS) $(PORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
|
||||
|
||||
.c.o:
|
||||
|
|
54
bsl.c
54
bsl.c
|
@ -22,23 +22,18 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bsl.h"
|
||||
#include "util.h"
|
||||
#include "output.h"
|
||||
#include "fet_error.h"
|
||||
|
||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#define B460800 460800
|
||||
#endif
|
||||
#include "sport.h"
|
||||
|
||||
struct bsl_device {
|
||||
struct device base;
|
||||
|
||||
int serial_fd;
|
||||
sport_t serial_fd;
|
||||
uint8_t reply_buf[256];
|
||||
int reply_len;
|
||||
};
|
||||
|
@ -51,7 +46,7 @@ static int bsl_ack(struct bsl_device *dev)
|
|||
{
|
||||
uint8_t reply;
|
||||
|
||||
if (read_with_timeout(dev->serial_fd, &reply, 1) < 0) {
|
||||
if (sport_read(dev->serial_fd, &reply, 1) < 0) {
|
||||
printc_err("bsl: failed to receive reply\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -74,13 +69,13 @@ static int bsl_sync(struct bsl_device *dev)
|
|||
static const uint8_t c = DATA_HDR;
|
||||
int tries = 2;
|
||||
|
||||
if (tcflush(dev->serial_fd, TCIFLUSH) < 0) {
|
||||
if (sport_flush(dev->serial_fd) < 0) {
|
||||
pr_error("bsl: tcflush");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (tries--)
|
||||
if (!(write_all(dev->serial_fd, &c, 1) || bsl_ack(dev)))
|
||||
if (!(sport_write_all(dev->serial_fd, &c, 1) || bsl_ack(dev)))
|
||||
return 0;
|
||||
|
||||
printc_err("bsl: sync failed\n");
|
||||
|
@ -122,7 +117,7 @@ static int send_command(struct bsl_device *dev,
|
|||
pktbuf[pktlen + 4] = cklow;
|
||||
pktbuf[pktlen + 5] = ckhigh;
|
||||
|
||||
return write_all(dev->serial_fd, pktbuf, pktlen + 6);
|
||||
return sport_write_all(dev->serial_fd, pktbuf, pktlen + 6);
|
||||
}
|
||||
|
||||
static int verify_checksum(struct bsl_device *dev)
|
||||
|
@ -150,10 +145,10 @@ static int fetch_reply(struct bsl_device *dev)
|
|||
dev->reply_len = 0;
|
||||
|
||||
for (;;) {
|
||||
int r = read_with_timeout(dev->serial_fd,
|
||||
dev->reply_buf + dev->reply_len,
|
||||
sizeof(dev->reply_buf) -
|
||||
dev->reply_len);
|
||||
int r = sport_read(dev->serial_fd,
|
||||
dev->reply_buf + dev->reply_len,
|
||||
sizeof(dev->reply_buf) -
|
||||
dev->reply_len);
|
||||
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
@ -208,7 +203,7 @@ static void bsl_destroy(device_t dev_base)
|
|||
struct bsl_device *dev = (struct bsl_device *)dev_base;
|
||||
|
||||
bsl_xfer(dev, CMD_RESET, 0, NULL, 0);
|
||||
close(dev->serial_fd);
|
||||
sport_close(dev->serial_fd);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
@ -326,29 +321,20 @@ static int bsl_erase(device_t dev_base, device_erase_type_t type,
|
|||
static int enter_via_fet(struct bsl_device *dev)
|
||||
{
|
||||
uint8_t buf[16];
|
||||
uint8_t *data = buf;
|
||||
int len = 8;
|
||||
|
||||
/* Enter bootloader command */
|
||||
if (write_all(dev->serial_fd,
|
||||
(uint8_t *)"\x7e\x24\x01\x9d\x5a\x7e", 6)) {
|
||||
if (sport_write_all(dev->serial_fd,
|
||||
(uint8_t *)"\x7e\x24\x01\x9d\x5a\x7e", 6)) {
|
||||
printc_err("bsl: couldn't write bootloader transition "
|
||||
"command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait for reply */
|
||||
while (len) {
|
||||
int r = read_with_timeout(dev->serial_fd, data, len);
|
||||
|
||||
if (r < 0) {
|
||||
printc_err("bsl: couldn't read bootloader "
|
||||
"transition acknowledgement\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += r;
|
||||
len -= r;
|
||||
if (sport_read_all(dev->serial_fd, buf, 8) < 0) {
|
||||
printc_err("bsl: couldn't read bootloader "
|
||||
"transition acknowledgement\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that it's what we expect */
|
||||
|
@ -380,8 +366,8 @@ static device_t bsl_open(const struct device_args *args)
|
|||
|
||||
dev->base.type = &device_bsl;
|
||||
|
||||
dev->serial_fd = open_serial(args->path, B460800);
|
||||
if (dev->serial_fd < 0) {
|
||||
dev->serial_fd = sport_open(args->path, B460800, 0);
|
||||
if (SPORT_ISERR(dev->serial_fd)) {
|
||||
printc_err("bsl: can't open %s: %s\n",
|
||||
args->path, strerror(errno));
|
||||
free(dev);
|
||||
|
@ -412,7 +398,7 @@ static device_t bsl_open(const struct device_args *args)
|
|||
return (device_t)dev;
|
||||
|
||||
fail:
|
||||
close(dev->serial_fd);
|
||||
sport_close(dev->serial_fd);
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
|
85
flash_bsl.c
85
flash_bsl.c
|
@ -22,29 +22,24 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "flash_bsl.h"
|
||||
#include "util.h"
|
||||
#include "output.h"
|
||||
#include "fet_error.h"
|
||||
#include "sport.h"
|
||||
|
||||
struct flash_bsl_device {
|
||||
struct device base;
|
||||
|
||||
int serial_fd;
|
||||
int long_password;
|
||||
sport_t serial_fd;
|
||||
int long_password;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_PACKET 256
|
||||
|
||||
|
||||
/* adapted from TI's published BSL source code */
|
||||
#define CRC_INIT 0xffff
|
||||
static uint16_t crc_ccitt(const uint8_t *data, int len) {
|
||||
|
@ -66,21 +61,24 @@ static void crc_selftest(void) {
|
|||
uint16_t crc_expected = 0x5590;
|
||||
uint16_t crc_actual = crc_ccitt((uint8_t *)"\x52\x02", 2);
|
||||
if (crc_expected != crc_actual) {
|
||||
printc_err("flash_bsl: CRC malfunction (expected 0x%04x got 0x%04x)\n",
|
||||
printc_err("flash_bsl: CRC malfunction "
|
||||
"(expected 0x%04x got 0x%04x)\n",
|
||||
crc_expected, crc_actual);
|
||||
}
|
||||
|
||||
crc_expected = 0x121d;
|
||||
crc_actual = crc_ccitt((uint8_t *)"\x3a\x04\x01", 3);
|
||||
if (crc_expected != crc_actual) {
|
||||
printc_err("flash_bsl: CRC malfunction (expected 0x%04x got 0x%04x)\n",
|
||||
printc_err("flash_bsl: CRC malfunction "
|
||||
"(expected 0x%04x got 0x%04x)\n",
|
||||
crc_expected, crc_actual);
|
||||
}
|
||||
|
||||
crc_expected = 0x528b;
|
||||
crc_actual = crc_ccitt((uint8_t *)"\x1a", 1);
|
||||
if (crc_expected != crc_actual) {
|
||||
printc_err("flash_bsl: CRC malfunction (expected 0x%04x got 0x%04x)\n",
|
||||
printc_err("flash_bsl: CRC malfunction "
|
||||
"(expected 0x%04x got 0x%04x)\n",
|
||||
crc_expected, crc_actual);
|
||||
}
|
||||
|
||||
|
@ -112,7 +110,8 @@ static int flash_bsl_send(struct flash_bsl_device *dev,
|
|||
crc = crc_ccitt(data, len);
|
||||
|
||||
if (len > MAX_PACKET) {
|
||||
printc_err("flash_bsl: attempted to transmit long packet (len=%d)\n", len);
|
||||
printc_err("flash_bsl: attempted to transmit "
|
||||
"long packet (len=%d)\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -123,12 +122,12 @@ static int flash_bsl_send(struct flash_bsl_device *dev,
|
|||
cmd_buf[len + 3] = (crc & 0xff);
|
||||
cmd_buf[len + 4] = (crc >> 8) & 0xff;
|
||||
|
||||
if (write_all(dev->serial_fd, cmd_buf, len + 5) < 0) {
|
||||
if (sport_write_all(dev->serial_fd, cmd_buf, len + 5) < 0) {
|
||||
printc_err("flash_bsl: serial write failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_all_with_timeout(dev->serial_fd, &response, 1) < 0) {
|
||||
if (sport_read_all(dev->serial_fd, &response, 1) < 0) {
|
||||
if (errno == ETIMEDOUT) {
|
||||
printc_err("flash_bsl: serial read timed out\n");
|
||||
} else {
|
||||
|
@ -140,16 +139,19 @@ static int flash_bsl_send(struct flash_bsl_device *dev,
|
|||
if (response != 0) {
|
||||
switch (response) {
|
||||
case 0x51:
|
||||
printc_err("flash_bsl: BSL reports incorrect packet header\n");
|
||||
printc_err("flash_bsl: BSL reports incorrect "
|
||||
"packet header\n");
|
||||
break;
|
||||
case 0x52:
|
||||
printc_err("flash_bsl: BSL reports checksum incorrect\n");
|
||||
printc_err("flash_bsl: BSL reports checksum "
|
||||
"incorrect\n");
|
||||
break;
|
||||
case 0x53:
|
||||
printc_err("flash_bsl: BSL got zero-size packet\n");
|
||||
break;
|
||||
case 0x54:
|
||||
printc_err("flash_bsl: BSL receive buffer overflowed\n");
|
||||
printc_err("flash_bsl: BSL receive buffer "
|
||||
"overflowed\n");
|
||||
break;
|
||||
case 0x55:
|
||||
printc_err("flash_bsl: (known-)unknown error\n");
|
||||
|
@ -175,7 +177,7 @@ static int flash_bsl_recv(struct flash_bsl_device *dev,
|
|||
uint16_t recv_len;
|
||||
uint16_t crc_value;
|
||||
|
||||
if (read_all_with_timeout(dev->serial_fd, header, 3) < 0) {
|
||||
if (sport_read_all(dev->serial_fd, header, 3) < 0) {
|
||||
if (errno == ETIMEDOUT) {
|
||||
printc_err("flash_bsl: response timed out\n");
|
||||
return -1;
|
||||
|
@ -204,13 +206,13 @@ static int flash_bsl_recv(struct flash_bsl_device *dev,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (read_all_with_timeout(dev->serial_fd, recv_buf, recv_len) < 0) {
|
||||
if (sport_read_all(dev->serial_fd, recv_buf, recv_len) < 0) {
|
||||
perror("receive message");
|
||||
printc_err("flash_bsl: error receiving message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_all_with_timeout(dev->serial_fd, crc_bytes, 2) < 0) {
|
||||
if (sport_read_all(dev->serial_fd, crc_bytes, 2) < 0) {
|
||||
perror("receive message CRC");
|
||||
printc_err("flash_bsl: error receiving message CRC\n");
|
||||
return -1;
|
||||
|
@ -547,51 +549,40 @@ static void entry_delay(void)
|
|||
usleep(1000);
|
||||
}
|
||||
|
||||
static int set_serial_bits(int fd, int bits)
|
||||
{
|
||||
if (ioctl(fd, TIOCMSET, &bits) >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int enter_via_dtr_rts(struct flash_bsl_device *dev)
|
||||
{
|
||||
/*
|
||||
* Implement the sequence shown on page 8 of TI document SLAU319A,
|
||||
* via serial-port control lines.
|
||||
*/
|
||||
|
||||
int fd = dev->serial_fd;
|
||||
|
||||
sport_t fd = dev->serial_fd;
|
||||
|
||||
/* drive RST# line low */
|
||||
if (set_serial_bits(fd, TIOCM_RTS | TIOCM_DTR) != 0) {
|
||||
if (sport_set_modem(fd, TIOCM_RTS | TIOCM_DTR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
|
||||
/* drive TEST line high then low again */
|
||||
if (set_serial_bits(fd, TIOCM_DTR) != 0) {
|
||||
if (sport_set_modem(fd, TIOCM_DTR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
if (set_serial_bits(fd, TIOCM_RTS | TIOCM_DTR) != 0) {
|
||||
if (sport_set_modem(fd, TIOCM_RTS | TIOCM_DTR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
|
||||
/* drive TEST line high followed by RST# line */
|
||||
if (set_serial_bits(fd, TIOCM_DTR) != 0) {
|
||||
if (sport_set_modem(fd, TIOCM_DTR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
if (set_serial_bits(fd, 0) != 0) {
|
||||
if (sport_set_modem(fd, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
if (set_serial_bits(fd, TIOCM_RTS) != 0) {
|
||||
if (sport_set_modem(fd, TIOCM_RTS) != 0) {
|
||||
return -1;
|
||||
}
|
||||
entry_delay( );
|
||||
|
@ -603,16 +594,16 @@ static int enter_via_dtr_rts(struct flash_bsl_device *dev)
|
|||
|
||||
static void exit_via_dtr_rts(struct flash_bsl_device *dev)
|
||||
{
|
||||
int fd = dev->serial_fd;
|
||||
sport_t fd = dev->serial_fd;
|
||||
|
||||
/* RST# and TEST LOW */
|
||||
set_serial_bits(fd, TIOCM_RTS | TIOCM_DTR);
|
||||
sport_set_modem(fd, TIOCM_RTS | TIOCM_DTR);
|
||||
|
||||
/* wait a brief period */
|
||||
entry_delay( );
|
||||
|
||||
/* RST# HIGH */
|
||||
set_serial_bits(fd, TIOCM_DTR);
|
||||
sport_set_modem(fd, TIOCM_DTR);
|
||||
}
|
||||
|
||||
static void flash_bsl_destroy(device_t dev_base)
|
||||
|
@ -621,7 +612,7 @@ static void flash_bsl_destroy(device_t dev_base)
|
|||
|
||||
exit_via_dtr_rts(dev);
|
||||
|
||||
close(dev->serial_fd);
|
||||
sport_close(dev->serial_fd);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
@ -648,8 +639,8 @@ static device_t flash_bsl_open(const struct device_args *args)
|
|||
memset(dev, 0, sizeof(*dev));
|
||||
dev->base.type = &device_flash_bsl;
|
||||
|
||||
dev->serial_fd = open_serial_even_parity(args->path, B9600);
|
||||
if (dev->serial_fd < 0) {
|
||||
dev->serial_fd = sport_open(args->path, B9600, SPORT_EVEN_PARITY);
|
||||
if (SPORT_ISERR(dev->serial_fd)) {
|
||||
printc_err("flash_bsl: can't open %s: %s\n",
|
||||
args->path, strerror(errno));
|
||||
free(dev);
|
||||
|
@ -678,8 +669,8 @@ static device_t flash_bsl_open(const struct device_args *args)
|
|||
}
|
||||
|
||||
if (flash_bsl_recv(dev, tx_bsl_version_response,
|
||||
sizeof(tx_bsl_version_response)) < sizeof(tx_bsl_version_response)) {
|
||||
|
||||
sizeof(tx_bsl_version_response)) <
|
||||
sizeof(tx_bsl_version_response)) {
|
||||
printc_err("flash_bsl: BSL responded with invalid version");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -690,7 +681,7 @@ static device_t flash_bsl_open(const struct device_args *args)
|
|||
return (device_t)dev;
|
||||
|
||||
fail:
|
||||
close(dev->serial_fd);
|
||||
sport_close(dev->serial_fd);
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
|
3
gdbc.c
3
gdbc.c
|
@ -278,8 +278,7 @@ static int gdbc_ctl(device_t dev_base, device_ctl_t op)
|
|||
|
||||
case DEVICE_CTL_HALT:
|
||||
if (dev->is_running) {
|
||||
if (write_all(dev->gdb.sock,
|
||||
(const uint8_t *)"\003", 1) < 0) {
|
||||
if (send(dev->gdb.sock, "\003", 1, 0) < 1) {
|
||||
pr_error("gdbc: write");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sport.h"
|
||||
|
||||
sport_t sport_open(const char *device, int rate, int flags)
|
||||
{
|
||||
int fd = open(device, O_RDWR | O_NOCTTY);
|
||||
struct termios attr;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
tcgetattr(fd, &attr);
|
||||
cfmakeraw(&attr);
|
||||
cfsetispeed(&attr, rate);
|
||||
cfsetospeed(&attr, rate);
|
||||
|
||||
if (flags & SPORT_EVEN_PARITY)
|
||||
attr.c_cflag |= PARENB;
|
||||
|
||||
if (tcsetattr(fd, TCSAFLUSH, &attr) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void sport_close(sport_t s)
|
||||
{
|
||||
close(s);
|
||||
}
|
||||
|
||||
int sport_flush(sport_t s)
|
||||
{
|
||||
return tcflush(s, TCIFLUSH);
|
||||
}
|
||||
|
||||
int sport_set_modem(sport_t s, int bits)
|
||||
{
|
||||
return ioctl(s, TIOCMSET, &bits);
|
||||
}
|
||||
|
||||
int sport_read(sport_t s, uint8_t *data, int len)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
struct timeval tv = {
|
||||
.tv_sec = 5,
|
||||
.tv_usec = 0
|
||||
};
|
||||
|
||||
fd_set set;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(s, &set);
|
||||
|
||||
r = select(s + 1, &set, NULL, NULL, &tv);
|
||||
if (r > 0)
|
||||
r = read(s, data, len);
|
||||
|
||||
if (!r)
|
||||
errno = ETIMEDOUT;
|
||||
if (r <= 0 && errno != EINTR)
|
||||
return -1;
|
||||
} while (r <= 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sport_write(sport_t s, const uint8_t *data, int len)
|
||||
{
|
||||
return write(s, data, len);
|
||||
}
|
||||
|
||||
int sport_read_all(sport_t s, uint8_t *data, int len)
|
||||
{
|
||||
while (len) {
|
||||
int r = sport_read(s, data, len);
|
||||
|
||||
if (r <= 0)
|
||||
return -1;
|
||||
|
||||
data += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sport_write_all(sport_t s, const uint8_t *data, int len)
|
||||
{
|
||||
while (len) {
|
||||
int r = sport_write(s, data, len);
|
||||
|
||||
if (r <= 0)
|
||||
return -1;
|
||||
|
||||
data += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPORT_H_
|
||||
#define SPORT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifndef B460800
|
||||
#define B460800 460800
|
||||
#endif
|
||||
|
||||
#ifndef B500000
|
||||
#define B500000 500000
|
||||
#endif
|
||||
|
||||
typedef int sport_t;
|
||||
|
||||
#define SPORT_ISERR(x) ((x) < 0)
|
||||
|
||||
/* Various utility functions for IO */
|
||||
|
||||
#define SPORT_EVEN_PARITY 0x01
|
||||
|
||||
sport_t sport_open(const char *device, int rate, int flags);
|
||||
void sport_close(sport_t s);
|
||||
|
||||
int sport_flush(sport_t s);
|
||||
int sport_set_modem(sport_t s, int bits);
|
||||
|
||||
/* Read/write a serial port. These functions return the number of
|
||||
* bytes transferred, or -1 on error.
|
||||
*/
|
||||
int sport_read(sport_t s, uint8_t *data, int len);
|
||||
int sport_write(sport_t s, const uint8_t *data, int len);
|
||||
|
||||
/* Same as above, but requires that all data be transferred. */
|
||||
int sport_read_all(sport_t s, uint8_t *data, int len);
|
||||
int sport_write_all(sport_t s, const uint8_t *data, int len);
|
||||
|
||||
#endif
|
35
uif.c
35
uif.c
|
@ -23,30 +23,21 @@
|
|||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/serial.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "uif.h"
|
||||
#include "util.h"
|
||||
#include "output.h"
|
||||
#include "sport.h"
|
||||
|
||||
#ifndef B460800
|
||||
#define B460800 460800
|
||||
#endif
|
||||
#ifndef B500000
|
||||
#define B500000 500000
|
||||
#if defined(__linux__)
|
||||
#include <linux/serial.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
struct uif_transport {
|
||||
struct transport base;
|
||||
|
||||
int serial_fd;
|
||||
sport_t serial_fd;
|
||||
};
|
||||
|
||||
static int serial_send(transport_t tr_base, const uint8_t *data, int len)
|
||||
|
@ -57,7 +48,7 @@ static int serial_send(transport_t tr_base, const uint8_t *data, int len)
|
|||
debug_hexdump("Serial transfer out:", data, len);
|
||||
#endif
|
||||
|
||||
if (write_all(tr->serial_fd, data, len) < 0) {
|
||||
if (sport_write_all(tr->serial_fd, data, len) < 0) {
|
||||
pr_error("uif: write error");
|
||||
return -1;
|
||||
}
|
||||
|
@ -70,7 +61,7 @@ static int serial_recv(transport_t tr_base, uint8_t *data, int max_len)
|
|||
struct uif_transport *tr = (struct uif_transport *)tr_base;
|
||||
int r;
|
||||
|
||||
r = read_with_timeout(tr->serial_fd, data, max_len);
|
||||
r = sport_read(tr->serial_fd, data, max_len);
|
||||
if (r < 0) {
|
||||
pr_error("uif: read error");
|
||||
return -1;
|
||||
|
@ -86,7 +77,7 @@ static void serial_destroy(transport_t tr_base)
|
|||
{
|
||||
struct uif_transport *tr = (struct uif_transport *)tr_base;
|
||||
|
||||
close(tr->serial_fd);
|
||||
sport_close(tr->serial_fd);
|
||||
free(tr);
|
||||
}
|
||||
|
||||
|
@ -108,7 +99,8 @@ static int open_olimex_iso(const char *device)
|
|||
serial_info.flags = ASYNC_SPD_CUST;
|
||||
serial_info.custom_divisor = 120;
|
||||
if (ioctl(fd, TIOCSSERIAL, &serial_info) < 0) {
|
||||
printc_err("open_olimex_iso: can't do ioctl TIOCSSERIAL: %s\n",
|
||||
printc_err("open_olimex_iso: can't do "
|
||||
"ioctl TIOCSSERIAL: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
@ -136,12 +128,12 @@ transport_t uif_open(const char *device, uif_type_t type)
|
|||
switch (type) {
|
||||
case UIF_TYPE_FET:
|
||||
printc("Trying to open UIF on %s...\n", device);
|
||||
tr->serial_fd = open_serial(device, B460800);
|
||||
tr->serial_fd = sport_open(device, B460800, 0);
|
||||
break;
|
||||
|
||||
case UIF_TYPE_OLIMEX:
|
||||
printc("Trying to open Olimex on %s...\n", device);
|
||||
tr->serial_fd = open_serial(device, B500000);
|
||||
tr->serial_fd = sport_open(device, B500000, 0);
|
||||
break;
|
||||
|
||||
case UIF_TYPE_OLIMEX_ISO:
|
||||
|
@ -149,7 +141,8 @@ transport_t uif_open(const char *device, uif_type_t type)
|
|||
printc("Trying to open Olimex (ISO) on %s...\n", device);
|
||||
tr->serial_fd = open_olimex_iso(device);
|
||||
#else
|
||||
printc_err("uif_open: ioctl TIOCSSERIAL not supported on this platform\n");
|
||||
printc_err("uif_open: ioctl TIOCSSERIAL not supported "
|
||||
"on this platform\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
136
util.c
136
util.c
|
@ -21,9 +21,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
@ -63,139 +60,6 @@ int ctrlc_check(void)
|
|||
return ctrlc_flag;
|
||||
}
|
||||
|
||||
int read_with_timeout(int fd, uint8_t *data, int max_len)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
struct timeval tv = {
|
||||
.tv_sec = 5,
|
||||
.tv_usec = 0
|
||||
};
|
||||
|
||||
fd_set set;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(fd, &set);
|
||||
|
||||
r = select(fd + 1, &set, NULL, NULL, &tv);
|
||||
if (r > 0)
|
||||
r = read(fd, data, max_len);
|
||||
|
||||
if (!r)
|
||||
errno = ETIMEDOUT;
|
||||
if (r <= 0 && errno != EINTR)
|
||||
return -1;
|
||||
} while (r <= 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* read_all_with_timeout
|
||||
* read all requested data, or die trying.
|
||||
*
|
||||
* Arguments:
|
||||
* fd: file descriptor from which to read
|
||||
* data: buffer where data will be put
|
||||
* len: total size of data to read
|
||||
*
|
||||
* Return Value:
|
||||
* Zero on success. -1 on failure.
|
||||
*/
|
||||
int read_all_with_timeout(int fd, uint8_t *data, int len)
|
||||
{
|
||||
int r, n_read;
|
||||
|
||||
/* loop until all required data has been read (or we time out) */
|
||||
while (len > 0) {
|
||||
struct timeval tv = {
|
||||
.tv_sec = 5,
|
||||
.tv_usec = 0
|
||||
};
|
||||
|
||||
/* wait (with timeout) for data to become available */
|
||||
fd_set set;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(fd, &set);
|
||||
|
||||
r = select(fd + 1, &set, NULL, NULL, &tv);
|
||||
|
||||
if (r > 0) {
|
||||
/* select( ) succeeded */
|
||||
n_read = read(fd, data, len);
|
||||
if (n_read <= 0) {
|
||||
/* read failed */
|
||||
return -1;
|
||||
} else {
|
||||
data += n_read;
|
||||
len -= n_read;
|
||||
}
|
||||
} else if (!r) {
|
||||
/* select( ) succeeded but timed out */
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
} else if (errno != EINTR) {
|
||||
/* select( ) failed */
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_all(int fd, const uint8_t *data, int len)
|
||||
{
|
||||
while (len) {
|
||||
int result = write(fd, data, len);
|
||||
|
||||
if (result < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += result;
|
||||
len -= result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_serial_and_set_cflags(const char *device,
|
||||
int rate, tcflag_t set)
|
||||
{
|
||||
int fd = open(device, O_RDWR | O_NOCTTY);
|
||||
struct termios attr;
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
tcgetattr(fd, &attr);
|
||||
cfmakeraw(&attr);
|
||||
cfsetispeed(&attr, rate);
|
||||
cfsetospeed(&attr, rate);
|
||||
attr.c_cflag |= set;
|
||||
|
||||
if (tcsetattr(fd, TCSAFLUSH, &attr) < 0)
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
int open_serial(const char *device, int rate)
|
||||
{
|
||||
return open_serial_and_set_cflags(device, rate, 0);
|
||||
}
|
||||
|
||||
int open_serial_even_parity(const char *device, int rate) {
|
||||
return open_serial_and_set_cflags(device, rate, PARENB);
|
||||
}
|
||||
|
||||
|
||||
char *get_arg(char **text)
|
||||
{
|
||||
char *start;
|
||||
|
|
7
util.h
7
util.h
|
@ -31,13 +31,6 @@
|
|||
/* This type fits an MSP430X register value */
|
||||
typedef uint32_t address_t;
|
||||
|
||||
/* Various utility functions for IO */
|
||||
int open_serial(const char *device, int rate);
|
||||
int open_serial_even_parity(const char *device, int rate);
|
||||
int read_with_timeout(int fd, uint8_t *data, int len);
|
||||
int read_all_with_timeout(int fd, uint8_t *data, int len);
|
||||
int write_all(int fd, const uint8_t *data, int len);
|
||||
|
||||
/* Check and catch ^C from the user */
|
||||
void ctrlc_init(void);
|
||||
void ctrlc_reset(void);
|
||||
|
|
Loading…
Reference in New Issue