Variadic xfer, plus other protocol tidy-ups.

This commit is contained in:
Daniel Beer 2010-01-04 14:02:31 +13:00
parent eb444b9957
commit f069ff7322
3 changed files with 76 additions and 137 deletions

181
fet.c
View File

@ -17,6 +17,7 @@
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
@ -25,7 +26,6 @@
static const struct fet_transport *fet_transport;
static int fet_is_rf2500;
static int fet_breakpoint_enable;
/**********************************************************************
* FET command codes.
@ -162,7 +162,7 @@ static int send_rf2500_data(const char *data, int len)
static char fet_buf[65538];
static int fet_len;
#define MAX_REPLY_PARAMS 16
#define MAX_PARAMS 16
/* Recieved packet is parsed into this struct */
static struct {
@ -170,7 +170,7 @@ static struct {
int state;
int argc;
u_int32_t argv[MAX_REPLY_PARAMS];
u_int32_t argv[MAX_PARAMS];
char *data;
int datalen;
@ -226,7 +226,7 @@ static int parse_packet(int plen)
fet_reply.argc = BUFFER_WORD(fet_buf, i);
i += 2;
if (fet_reply.argc >= MAX_REPLY_PARAMS) {
if (fet_reply.argc >= MAX_PARAMS) {
fprintf(stderr, "parse_packet: too many params: %d\n",
fet_reply.argc);
return -1;
@ -366,9 +366,20 @@ static int send_command(int command_code,
return fet_transport->send(buf, i);
}
static int xfer(int command_code, const u_int32_t *params, int nparams,
const char *data, int datalen)
static int xfer(int command_code, const char *data, int datalen,
int nparams, ...)
{
u_int32_t params[MAX_PARAMS];
int i;
va_list ap;
assert (nparams <= MAX_PARAMS);
va_start(ap, nparams);
for (i = 0; i < nparams; i++)
params[i] = va_arg(ap, unsigned int);
va_end(ap);
if (data && fet_is_rf2500) {
if (send_rf2500_data(data, datalen) < 0)
return -1;
@ -395,41 +406,34 @@ static int xfer(int command_code, const u_int32_t *params, int nparams,
int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
{
static u_int32_t parm[4];
fet_transport = tr;
fet_is_rf2500 = proto_flags & FET_PROTO_RF2500;
init_codes();
if (xfer(C_INITIALIZE, NULL, 0, NULL, 0) < 0) {
if (xfer(C_INITIALIZE, NULL, 0, 0) < 0) {
fprintf(stderr, "fet_open: open failed\n");
return -1;
}
parm[0] = 4;
if (xfer(39, parm, 1, NULL, 0) < 0) {
if (xfer(39, NULL, 0, 1, 4) < 0) {
fprintf(stderr, "fet_open: init failed\n");
return -1;
}
/* configure: Spy-Bi-Wire or JTAG */
parm[0] = 8;
parm[1] = (proto_flags & FET_PROTO_SPYBIWIRE) ? 1 : 0;
if (xfer(C_CONFIGURE, parm, 2, NULL, 0) < 0) {
if (xfer(C_CONFIGURE, NULL, 0,
2, 8, (proto_flags & FET_PROTO_SPYBIWIRE) ? 1 : 0) < 0) {
fprintf(stderr, "fet_open: configure failed\n");
return -1;
}
parm[0] = 0x50;
parm[1] = 0;
if (!fet_is_rf2500 && xfer(C_IDENTIFY, parm, 2, NULL, 0) < 0) {
if (!fet_is_rf2500 && xfer(C_IDENTIFY, NULL, 0, 2, 0x50, 0) < 0) {
fprintf(stderr, "fet_open: identify failed\n");
return -1;
}
/* set VCC */
parm[0] = vcc_mv;
if (xfer(C_VCC, parm, 2, NULL, 0) < 0) {
if (xfer(C_VCC, NULL, 0, 2, vcc_mv, 0) < 0) {
fprintf(stderr, "fet_open: set VCC failed\n");
return -1;
}
@ -437,9 +441,7 @@ int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
/* I don't know what this is, but it appears to halt the MSP. Without
* it, memory reads return garbage. This is RF2500-specific.
*/
parm[0] = 0;
parm[1] = 0;
if (fet_is_rf2500 && xfer(0x28, parm, 2, NULL, 0) < 0) {
if (fet_is_rf2500 && xfer(0x28, NULL, 0, 2, 0, 0) < 0) {
fprintf(stderr, "fet_open: command 0x28 failed\n");
return -1;
}
@ -448,7 +450,7 @@ int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
* This is RF2500-specific.
*/
if (fet_is_rf2500) {
static char data[] = {
static const char data[] = {
0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10,
0xff, 0x10, 0x40, 0x00, 0x00, 0x02, 0xff, 0x05,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
@ -461,12 +463,8 @@ int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
0xff, 0xff
};
parm[0] = 0;
parm[1] = 0x39;
parm[2] = 0x31;
parm[3] = sizeof(data);
if (xfer(0x29, parm, 4, data, sizeof(data)) < 0) {
if (xfer(0x29, data, sizeof(data), 4, 0, 0x39, 0x31,
sizeof(data)) < 0) {
fprintf(stderr, "fet_open: command 0x29 failed\n");
return -1;
}
@ -480,13 +478,9 @@ int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
int fet_reset(int flags)
{
u_int32_t parm[3] = {
flags & FET_RESET_ALL,
flags & FET_RESET_HALT ? 1 : 0,
flags & FET_RESET_HALT ? 1 : 0
};
int wh = flags & FET_RESET_HALT ? 1 : 0;
if (xfer(C_RESET, parm, 3, NULL, 0) < 0) {
if (xfer(C_RESET, NULL, 3, flags & FET_RESET_ALL, wh, wh) < 0) {
fprintf(stderr, "fet_reset: reset failed\n");
return -1;
}
@ -496,9 +490,7 @@ int fet_reset(int flags)
int fet_close(void)
{
u_int32_t parm = 0;
if (xfer(C_CLOSE, &parm, 1, NULL, 0) < 0) {
if (xfer(C_CLOSE, NULL, 0, 1, 0) < 0) {
fprintf(stderr, "fet_shutdown: close command failed\n");
return -1;
}
@ -513,7 +505,7 @@ int fet_get_context(u_int16_t *regs)
{
int i;
if (xfer(C_READREGISTERS, NULL, 0, NULL, 0) < 0)
if (xfer(C_READREGISTERS, NULL, 0, 0) < 0)
return -1;
if (fet_reply.datalen < FET_NUM_REGS * 4) {
@ -531,11 +523,8 @@ int fet_get_context(u_int16_t *regs)
int fet_set_context(u_int16_t *regs)
{
char buf[FET_NUM_REGS * 4];
u_int32_t parm[4] = {
0xffff,
sizeof(buf)
};
int i;
int ret;
memset(buf, 0, sizeof(buf));
@ -544,8 +533,14 @@ int fet_set_context(u_int16_t *regs)
buf[i * 4 + 1] = regs[i] >> 8;
}
if (xfer(C_WRITEREGISTERS, parm, fet_is_rf2500 ? 2 : 1,
buf, sizeof(buf)) < 0) {
if (fet_is_rf2500)
ret = xfer(C_WRITEREGISTERS, buf, sizeof(buf),
2, 0xffff, sizeof(buf));
else
ret = xfer(C_WRITEREGISTERS, buf, sizeof(buf),
1, 0xffff);
if (ret < 0) {
fprintf(stderr, "fet_set_context: context set failed\n");
return -1;
}
@ -555,14 +550,10 @@ int fet_set_context(u_int16_t *regs)
int fet_read_mem(u_int16_t addr, char *buffer, int count)
{
u_int32_t parm[2];
while (count) {
int plen = count > 128 ? 128 : count;
parm[0] = addr;
parm[1] = plen;
if (xfer(C_READMEMORY, parm, 2, NULL, 0) < 0) {
if (xfer(C_READMEMORY, NULL, 0, 2, addr, plen) < 0) {
fprintf(stderr, "fet_read_mem: failed to read "
"from 0x%04x\n", addr);
return -1;
@ -585,15 +576,18 @@ int fet_read_mem(u_int16_t addr, char *buffer, int count)
int fet_write_mem(u_int16_t addr, char *buffer, int count)
{
u_int32_t parm[2];
while (count) {
int plen = count > 128 ? 128 : count;
int ret;
parm[0] = addr;
parm[1] = plen;
if (xfer(C_WRITEMEMORY, parm, fet_is_rf2500 ? 2 : 1,
buffer, plen) < 0) {
if (fet_is_rf2500)
ret = xfer(C_WRITEMEMORY, buffer, plen,
2, addr, plen);
else
ret = xfer(C_WRITEMEMORY, buffer, plen,
1, addr);
if (ret < 0) {
fprintf(stderr, "fet_write_mem: failed to write "
"to 0x%04x\n", addr);
return -1;
@ -607,49 +601,19 @@ int fet_write_mem(u_int16_t addr, char *buffer, int count)
return 0;
}
int fet_erase(int type, u_int16_t addr)
int fet_erase(int type, u_int16_t addr, int len)
{
u_int32_t parm[3];
parm[0] = 2;
parm[1] = 0x26;
if (xfer(C_CONFIGURE, parm, 2, NULL, 0) < 0) {
if (xfer(C_CONFIGURE, NULL, 0, 2, 2, 0x26) < 0) {
fprintf(stderr, "fet_erase: config (1) failed\n");
return -1;
}
parm[0] = 5;
parm[1] = 0;
if (xfer(C_CONFIGURE, parm, 2, NULL, 0) < 0) {
if (xfer(C_CONFIGURE, NULL, 0, 2, 5, 0) < 0) {
fprintf(stderr, "fet_erase: config (2) failed\n");
return -1;
}
switch (type) {
case FET_ERASE_MAIN:
parm[0] = 1;
parm[2] = 2;
break;
case FET_ERASE_ADDR:
parm[0] = 0;
parm[2] = 2;
break;
case FET_ERASE_INFO:
parm[0] = 0;
parm[2] = 1;
break;
case FET_ERASE_ALL:
default:
parm[0] = 2;
parm[2] = 0x100;
break;
}
parm[1] = addr;
if (xfer(C_ERASE, parm, 2, NULL, 0) < 0) {
if (xfer(C_ERASE, NULL, 0, 3, type, addr, len) < 0) {
fprintf(stderr, "fet_erase: erase command failed\n");
return -1;
}
@ -659,13 +623,11 @@ int fet_erase(int type, u_int16_t addr)
int fet_poll(void)
{
u_int32_t parm = 0;
/* Without this delay, breakpoints can get lost. */
if (usleep(500000) < 0)
return -1;
if (xfer(C_STATE, &parm, 1, NULL, 0) < 0) {
if (xfer(C_STATE, NULL, 0, 1, 0) < 0) {
fprintf(stderr, "fet_poll: polling failed\n");
return -1;
}
@ -673,27 +635,9 @@ int fet_poll(void)
return fet_reply.argv[0];
}
int fet_step(void)
int fet_run(int type)
{
static const u_int32_t parm[2] = {
2, 0
};
if (xfer(C_RUN, parm, 2, NULL, 0) < 0) {
fprintf(stderr, "fet_step: failed to single-step\n");
return -1;
}
return 0;
}
int fet_run(void)
{
u_int32_t parm[2] = {
fet_breakpoint_enable ? 3 : 1, 0
};
if (xfer(C_RUN, parm, 2, NULL, 0) < 0) {
if (xfer(C_RUN, NULL, 0, 2, type, 0) < 0) {
fprintf(stderr, "fet_run: run failed\n");
return -1;
}
@ -703,9 +647,7 @@ int fet_run(void)
int fet_stop(void)
{
u_int32_t parm = 1;
if (xfer(C_STATE, &parm, 1, NULL, 0) < 0) {
if (xfer(C_STATE, NULL, 0, 1, 1) < 0) {
fprintf(stderr, "fet_stop: stop failed\n");
return -1;
}
@ -713,12 +655,9 @@ int fet_stop(void)
return 0;
}
int fet_break(int enable, u_int16_t addr)
int fet_break(int which, u_int16_t addr)
{
u_int32_t parm[2] = { 0, addr };
fet_breakpoint_enable = enable;
if (xfer(C_BREAKPOINT, parm, 2, NULL, 0) < 0) {
if (xfer(C_BREAKPOINT, NULL, 0, 2, which, addr) < 0) {
fprintf(stderr, "fet_break: set breakpoint failed\n");
return -1;
}

22
fet.h
View File

@ -68,12 +68,11 @@ int fet_get_context(u_int16_t *regs);
int fet_set_context(u_int16_t *regs);
/* Erase the CPU's internal flash. */
#define FET_ERASE_ALL 0x01
#define FET_ERASE_MAIN 0x02
#define FET_ERASE_ADDR 0x03
#define FET_ERASE_INFO 0x04
#define FET_ERASE_SEGMENT 0
#define FET_ERASE_MAIN 1
#define FET_ERASE_ALL 2
int fet_erase(int type, u_int16_t addr);
int fet_erase(int type, u_int16_t addr, int len);
/* Read and write memory. fet_write_mem can be used to reflash the
* device, but only after an erase.
@ -95,13 +94,14 @@ int fet_poll(void);
* registers are inaccessible (only fet_poll() or fet_stop()) will
* work. fet_step() is used to single-step the CPU.
*/
int fet_step(void);
int fet_run(void);
#define FET_RUN_FREE 1
#define FET_RUN_STEP 2
#define FET_RUN_BREAKPOINT 3
int fet_run(int type);
int fet_stop(void);
/* Set or clear the breakpoint address. Only one breakpoint can be set
* at a time.
*/
int fet_break(int enable, u_int16_t addr);
/* Set a breakpoint address */
int fet_break(int which, u_int16_t addr);
#endif

10
main.c
View File

@ -259,12 +259,12 @@ static int cmd_run(char **arg)
unsigned int addr = 0;
sscanf(bp_text, "%x", &addr);
fet_break(1, addr);
fet_break(0, addr);
} else {
fet_break(0, 0);
}
if (fet_run() < 0)
if (fet_run(bp_text ? FET_RUN_BREAKPOINT : FET_RUN_FREE) < 0)
return -1;
printf("Running. Press Ctrl+C to interrupt...");
@ -319,7 +319,7 @@ static int cmd_set(char **arg)
static int cmd_step(char **arg)
{
if (fet_step() < 0)
if (fet_run(FET_RUN_STEP) < 0)
return -1;
if (fet_poll() < 0)
return -1;
@ -445,7 +445,7 @@ static int cmd_prog(char **arg)
}
printf("Erasing...\n");
if (fet_erase(FET_ERASE_ALL, 0) < 0) {
if (fet_erase(FET_ERASE_ALL, 0, 0) < 0) {
fclose(in);
return -1;
}
@ -646,7 +646,7 @@ int main(int argc, char **argv)
reader_loop();
}
fet_run();
fet_run(FET_RUN_FREE);
fet_close();
return 0;