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