Extracted general IO routines from UIF.
This commit is contained in:
parent
5a84cbf7f5
commit
8ce134c04c
81
bsl.c
81
bsl.c
|
@ -28,22 +28,7 @@
|
|||
#include "device.h"
|
||||
#include "util.h"
|
||||
|
||||
static const struct fet_transport *trans;
|
||||
|
||||
static int bufio_get_bytes(u_int8_t *data, int len)
|
||||
{
|
||||
while (len) {
|
||||
int r = trans->recv(data, len);
|
||||
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
data += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int serial_fd;
|
||||
|
||||
#define DATA_HDR 0x80
|
||||
#define DATA_ACK 0x90
|
||||
|
@ -53,7 +38,7 @@ static int bsl_ack(void)
|
|||
{
|
||||
u_int8_t reply;
|
||||
|
||||
if (trans->recv(&reply, 1) < 0) {
|
||||
if (read_with_timeout(serial_fd, &reply, 1) < 0) {
|
||||
fprintf(stderr, "bsl: failed to receive reply\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -76,10 +61,13 @@ static int bsl_sync(void)
|
|||
static const u_int8_t c = DATA_HDR;
|
||||
int tries = 2;
|
||||
|
||||
trans->flush();
|
||||
if (tcflush(serial_fd, TCIFLUSH) < 0) {
|
||||
perror("bsl: tcflush");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (tries--)
|
||||
if (!trans->send(&c, 1) && !bsl_ack())
|
||||
if (!(write_all(serial_fd, &c, 1) || bsl_ack()))
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, "bsl: sync failed\n");
|
||||
|
@ -120,7 +108,7 @@ static int send_command(int code, u_int16_t addr,
|
|||
pktbuf[pktlen + 4] = cklow;
|
||||
pktbuf[pktlen + 5] = ckhigh;
|
||||
|
||||
return trans->send(pktbuf, pktlen + 6);
|
||||
return write_all(serial_fd, pktbuf, pktlen + 6);
|
||||
}
|
||||
|
||||
static u_int8_t reply_buf[256];
|
||||
|
@ -152,7 +140,7 @@ static int fetch_reply(void)
|
|||
reply_len = 0;
|
||||
|
||||
for (;;) {
|
||||
int r = trans->recv(reply_buf + reply_len,
|
||||
int r = read_with_timeout(serial_fd, reply_buf + reply_len,
|
||||
sizeof(reply_buf) - reply_len);
|
||||
|
||||
if (r < 0)
|
||||
|
@ -204,11 +192,8 @@ static int bsl_xfer(int command_code, u_int16_t addr, const u_int8_t *txdata,
|
|||
|
||||
static void bsl_close(void)
|
||||
{
|
||||
if (trans) {
|
||||
bsl_xfer(CMD_RESET, 0, NULL, 0);
|
||||
trans->close();
|
||||
trans = NULL;
|
||||
}
|
||||
close(serial_fd);
|
||||
}
|
||||
|
||||
static int bsl_control(device_ctl_t type)
|
||||
|
@ -281,25 +266,57 @@ const static struct device bsl_device = {
|
|||
.readmem = bsl_readmem
|
||||
};
|
||||
|
||||
const struct device *fet_open_bl(const struct fet_transport *tr)
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static int enter_via_fet(void)
|
||||
{
|
||||
u_int8_t buf[16];
|
||||
|
||||
trans = tr;
|
||||
u_int8_t *data = buf;
|
||||
int len = 8;
|
||||
|
||||
/* Enter bootloader command */
|
||||
if (trans->send((u_int8_t *)"\x7e\x24\x01\x9d\x5a\x7e", 6) < 0 ||
|
||||
bufio_get_bytes(buf, 8) < 0) {
|
||||
fprintf(stderr, "bsl: failed to init bootloader\n");
|
||||
return NULL;
|
||||
if (write_all(serial_fd, (u_int8_t *)"\x7e\x24\x01\x9d\x5a\x7e", 6)) {
|
||||
fprintf(stderr, "bsl: couldn't write bootloader transition "
|
||||
"command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait for reply */
|
||||
while (len) {
|
||||
int r = read_with_timeout(serial_fd, data, len);
|
||||
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "bsl: couldn't read bootloader "
|
||||
"transition acknowledgement\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
/* Check that it's what we expect */
|
||||
if (memcmp(buf, "\x06\x00\x24\x00\x00\x00\x61\x01", 8)) {
|
||||
fprintf(stderr, "bsl: bootloader start returned error %d\n",
|
||||
buf[5]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct device *bsl_open(const char *device)
|
||||
{
|
||||
serial_fd = open_serial(device, B460800);
|
||||
if (serial_fd < 0) {
|
||||
fprintf(stderr, "bsl: can't open %s: %s\n",
|
||||
device, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (enter_via_fet() < 0)
|
||||
return NULL;
|
||||
|
||||
usleep(500000);
|
||||
|
||||
/* Show chip info */
|
||||
|
|
2
device.h
2
device.h
|
@ -52,7 +52,7 @@ const struct device *fet_open(const struct fet_transport *transport,
|
|||
int proto_flags, int vcc_mv);
|
||||
|
||||
/* MSP430 FET Bootloader implementation. */
|
||||
const struct device *fet_open_bl(const struct fet_transport *transport);
|
||||
const struct device *bsl_open(const char *device);
|
||||
|
||||
/* Dummy/simulation implementation. */
|
||||
const struct device *sim_open(void);
|
||||
|
|
17
main.c
17
main.c
|
@ -624,7 +624,7 @@ static void usage(const char *progname)
|
|||
" Use JTAG, rather than spy-bi-wire (UIF devices only).\n"
|
||||
" -v voltage\n"
|
||||
" Set the supply voltage, in millivolts.\n"
|
||||
" -B\n"
|
||||
" -B device\n"
|
||||
" Debug the FET itself through the bootloader.\n"
|
||||
" -s\n"
|
||||
" Start in simulation mode (only memory IO is allowed).\n"
|
||||
|
@ -640,10 +640,10 @@ int main(int argc, char **argv)
|
|||
{
|
||||
const struct fet_transport *trans;
|
||||
const char *uif_device = NULL;
|
||||
const char *bsl_device = NULL;
|
||||
int opt;
|
||||
int flags = 0;
|
||||
int want_jtag = 0;
|
||||
int want_bootloader = 0;
|
||||
int want_sim = 0;
|
||||
int vcc_mv = 3000;
|
||||
|
||||
|
@ -654,7 +654,7 @@ int main(int argc, char **argv)
|
|||
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
|
||||
|
||||
/* Parse arguments */
|
||||
while ((opt = getopt(argc, argv, "u:jv:Bs")) >= 0)
|
||||
while ((opt = getopt(argc, argv, "u:jv:B:s")) >= 0)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
uif_device = optarg;
|
||||
|
@ -669,7 +669,7 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
|
||||
case 'B':
|
||||
want_bootloader = 1;
|
||||
bsl_device = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
@ -684,22 +684,23 @@ int main(int argc, char **argv)
|
|||
/* Open a device */
|
||||
if (want_sim) {
|
||||
msp430_dev = sim_open();
|
||||
} else if (bsl_device) {
|
||||
msp430_dev = bsl_open(bsl_device);
|
||||
} else {
|
||||
/* Open the appropriate transport */
|
||||
if (uif_device)
|
||||
if (uif_device) {
|
||||
trans = uif_open(uif_device);
|
||||
else {
|
||||
} else {
|
||||
trans = rf2500_open();
|
||||
flags |= FET_PROTO_RF2500;
|
||||
}
|
||||
|
||||
if (!trans)
|
||||
return -1;
|
||||
|
||||
/* Then initialize the device */
|
||||
if (!want_jtag)
|
||||
flags |= FET_PROTO_SPYBIWIRE;
|
||||
if (want_bootloader)
|
||||
msp430_dev = fet_open_bl(trans);
|
||||
else
|
||||
msp430_dev = fet_open(trans, flags, vcc_mv);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,11 @@ struct fet_transport {
|
|||
*/
|
||||
const struct fet_transport *uif_open(const char *device);
|
||||
|
||||
/* This function opens the bootstrap loader on a FET430UIF by using
|
||||
* the TIUSB's modem control pins to generate the BSL entry sequence.
|
||||
*/
|
||||
const struct fet_transport *uif_open_bsl(const char *device);
|
||||
|
||||
/* Search the USB bus for the first eZ430-RF2500, and initialize it. If
|
||||
* successful, 0 is returned and the fet_* functions are ready for use.
|
||||
* If an error occurs, -1 is returned.
|
||||
|
|
58
uif.c
58
uif.c
|
@ -21,10 +21,8 @@
|
|||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "transport.h"
|
||||
#include "util.h"
|
||||
|
@ -33,8 +31,6 @@ static int serial_fd = -1;
|
|||
|
||||
static int serial_send(const u_int8_t *data, int len)
|
||||
{
|
||||
int result;
|
||||
|
||||
assert (serial_fd >= 0);
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
|
@ -42,20 +38,11 @@ static int serial_send(const u_int8_t *data, int len)
|
|||
hexdump(0, data, len);
|
||||
#endif
|
||||
|
||||
while (len) {
|
||||
result = write(serial_fd, data, len);
|
||||
if (result < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
perror("serial_send");
|
||||
if (write_all(serial_fd, data, len) < 0) {
|
||||
perror("uif: write error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += result;
|
||||
len -= result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -65,32 +52,12 @@ static int serial_recv(u_int8_t *data, int max_len)
|
|||
|
||||
assert (serial_fd >= 0);
|
||||
|
||||
do {
|
||||
struct timeval tv = {
|
||||
.tv_sec = 5,
|
||||
.tv_usec = 0
|
||||
};
|
||||
|
||||
fd_set set;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(serial_fd, &set);
|
||||
|
||||
r = select(serial_fd + 1, &set, NULL, NULL, &tv);
|
||||
if (r > 0)
|
||||
r = read(serial_fd, data, max_len);
|
||||
|
||||
if (r < 0 && errno != EINTR) {
|
||||
r = read_with_timeout(serial_fd, data, max_len);
|
||||
if (r < 0) {
|
||||
perror("uif: read error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
fprintf(stderr, "uif: read timeout\n");
|
||||
return -1;
|
||||
}
|
||||
} while (r <= 0);
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
puts("Serial transfer in:");
|
||||
hexdump(0, data, r);
|
||||
|
@ -124,22 +91,11 @@ static const struct fet_transport serial_transport = {
|
|||
|
||||
const struct fet_transport *uif_open(const char *device)
|
||||
{
|
||||
struct termios attr;
|
||||
|
||||
printf("Trying to open UIF on %s...\n", device);
|
||||
|
||||
serial_fd = open(device, O_RDWR | O_NOCTTY);
|
||||
serial_fd = open_serial(device, B460800);
|
||||
if (serial_fd < 0) {
|
||||
fprintf(stderr, "uif: open: %s: %s\n",
|
||||
device, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcgetattr(serial_fd, &attr);
|
||||
cfmakeraw(&attr);
|
||||
cfsetspeed(&attr, B460800);
|
||||
if (tcsetattr(serial_fd, TCSAFLUSH, &attr) < 0) {
|
||||
fprintf(stderr, "uif: tcsetattr: %s: %s\n",
|
||||
fprintf(stderr, "uif: can't open serial device: %s: %s\n",
|
||||
device, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
|
66
util.c
66
util.c
|
@ -17,6 +17,11 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "util.h"
|
||||
|
||||
void hexdump(int addr, const u_int8_t *data, int len)
|
||||
|
@ -74,3 +79,64 @@ void print_devid(u_int16_t id)
|
|||
else
|
||||
printf("Unknown device ID: 0x%04x\n", id);
|
||||
}
|
||||
|
||||
int read_with_timeout(int fd, u_int8_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;
|
||||
}
|
||||
|
||||
int write_all(int fd, const u_int8_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;
|
||||
}
|
||||
|
||||
int open_serial(const char *device, int rate)
|
||||
{
|
||||
int fd = open(device, O_RDWR | O_NOCTTY);
|
||||
struct termios attr;
|
||||
|
||||
tcgetattr(fd, &attr);
|
||||
cfmakeraw(&attr);
|
||||
cfsetspeed(&attr, rate);
|
||||
|
||||
if (tcsetattr(fd, TCSAFLUSH, &attr) < 0)
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue