Abstracted interface to FET driver.
Tested with eZ430-RF2500.
This commit is contained in:
parent
7505ce654d
commit
ce308c5823
|
@ -0,0 +1,54 @@
|
|||
/* MSPDebug - debugging tool for the eZ430
|
||||
* Copyright (C) 2009 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 DEVICE_H_
|
||||
#define DEVICE_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "transport.h"
|
||||
|
||||
#define DEVICE_NUM_REGS 16
|
||||
|
||||
typedef enum {
|
||||
DEVICE_CTL_RESET,
|
||||
DEVICE_CTL_RUN,
|
||||
DEVICE_CTL_HALT,
|
||||
DEVICE_CTL_RUN_BP,
|
||||
DEVICE_CTL_STEP,
|
||||
DEVICE_CTL_ERASE
|
||||
} device_ctl_t;
|
||||
|
||||
struct device {
|
||||
void (*close)(void);
|
||||
int (*control)(device_ctl_t action);
|
||||
int (*wait)(void);
|
||||
int (*breakpoint)(u_int16_t addr);
|
||||
int (*getregs)(u_int16_t *regs);
|
||||
int (*setregs)(const u_int16_t *regs);
|
||||
int (*readmem)(u_int16_t addr, u_int8_t *mem, int len);
|
||||
int (*writemem)(u_int16_t addr, const u_int8_t *mem, int len);
|
||||
};
|
||||
|
||||
/* MSP430 FET protocol implementation. */
|
||||
#define FET_PROTO_SPYBIWIRE 0x01
|
||||
#define FET_PROTO_RF2500 0x02
|
||||
|
||||
const struct device *fet_open(const struct fet_transport *transport,
|
||||
int proto_flags, int vcc_mv);
|
||||
|
||||
#endif
|
392
fet.c
392
fet.c
|
@ -26,7 +26,7 @@
|
|||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fet.h"
|
||||
#include "device.h"
|
||||
|
||||
#define ARRAY_LEN(a) ((sizeof(a)) / sizeof((a)[0]))
|
||||
|
||||
|
@ -77,6 +77,23 @@ static int fet_is_rf2500;
|
|||
#define C_WRITEI2C 35
|
||||
#define C_ENTERBOOTLOADER 36
|
||||
|
||||
/* Constants for parameters of various FET commands */
|
||||
#define FET_RUN_FREE 1
|
||||
#define FET_RUN_STEP 2
|
||||
#define FET_RUN_BREAKPOINT 3
|
||||
|
||||
#define FET_RESET_PUC 0x01
|
||||
#define FET_RESET_RST 0x02
|
||||
#define FET_RESET_VCC 0x04
|
||||
#define FET_RESET_ALL 0x07
|
||||
|
||||
#define FET_ERASE_SEGMENT 0
|
||||
#define FET_ERASE_MAIN 1
|
||||
#define FET_ERASE_ALL 2
|
||||
|
||||
#define FET_POLL_RUNNING 0x01
|
||||
#define FET_POLL_BREAKPOINT 0x02
|
||||
|
||||
/*********************************************************************
|
||||
* Checksum calculation
|
||||
*/
|
||||
|
@ -578,138 +595,158 @@ static int do_identify(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
|
||||
static void fet_close(void)
|
||||
{
|
||||
fet_transport = tr;
|
||||
fet_is_rf2500 = proto_flags & FET_PROTO_RF2500;
|
||||
init_codes();
|
||||
if (xfer(C_RUN, NULL, 0, 2, FET_RUN_FREE, 1) < 0)
|
||||
fprintf(stderr, "fet: failed to restart CPU\n");
|
||||
|
||||
if (xfer(C_INITIALIZE, NULL, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet_open: open failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fet_version = fet_reply.argv[0];
|
||||
printf("FET protocol version is %d\n", fet_version);
|
||||
|
||||
if (xfer(39, NULL, 0, 1, 4) < 0) {
|
||||
fprintf(stderr, "fet_open: init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* configure: Spy-Bi-Wire or JTAG */
|
||||
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;
|
||||
}
|
||||
|
||||
printf("Configured for %s\n",
|
||||
(proto_flags & FET_PROTO_SPYBIWIRE) ? "Spy-Bi-Wire" : "JTAG");
|
||||
|
||||
/* Identify the chip */
|
||||
if (do_identify() < 0) {
|
||||
fprintf(stderr, "fet_open: identify failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set VCC */
|
||||
if (xfer(C_VCC, NULL, 0, 2, vcc_mv, 0) < 0) {
|
||||
fprintf(stderr, "fet_open: set VCC failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Set Vcc: %d mV\n", 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.
|
||||
*/
|
||||
if (fet_is_rf2500 && xfer(0x28, NULL, 0, 2, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet_open: command 0x28 failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Who knows what this is. Without it, register reads don't work.
|
||||
* This is RF2500-specific.
|
||||
*/
|
||||
if (fet_is_rf2500) {
|
||||
static const u_int8_t 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,
|
||||
0x01, 0x00, 0xd7, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x07, 0x10, 0x0e, 0xc4, 0x09, 0x70, 0x17,
|
||||
0x58, 0x1b, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x0f, 0x1f, 0x0f,
|
||||
0xff, 0xff
|
||||
};
|
||||
|
||||
if (xfer(0x29, data, sizeof(data), 4, 0, 0x39, 0x31,
|
||||
sizeof(data)) < 0) {
|
||||
fprintf(stderr, "fet_open: command 0x29 failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_reset(int flags)
|
||||
{
|
||||
int wh = flags & FET_RESET_HALT ? 0 : 1;
|
||||
int wr = flags & FET_RESET_RELEASE ? 1 : 0;
|
||||
|
||||
if (xfer(C_RESET, NULL, 0, 3, flags & FET_RESET_ALL, wh, wr) < 0) {
|
||||
fprintf(stderr, "fet_reset: reset failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_close(void)
|
||||
{
|
||||
if (xfer(C_CLOSE, NULL, 0, 1, 0) < 0) {
|
||||
fprintf(stderr, "fet_shutdown: close command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (xfer(C_CLOSE, NULL, 0, 1, 0) < 0)
|
||||
fprintf(stderr, "fet: close command failed\n");
|
||||
|
||||
fet_transport->close();
|
||||
fet_transport = NULL;
|
||||
}
|
||||
|
||||
static int do_reset(void) {
|
||||
if (xfer(C_RESET, NULL, 0, 3, FET_RESET_ALL, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet: reset failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_get_context(u_int16_t *regs)
|
||||
static int do_run(int type)
|
||||
{
|
||||
if (xfer(C_RUN, NULL, 0, 2, type, 0) < 0) {
|
||||
fprintf(stderr, "fet: failed to restart CPU\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_halt(void)
|
||||
{
|
||||
if (xfer(C_STATE, NULL, 0, 1, 1) < 0) {
|
||||
fprintf(stderr, "fet: failed to halt CPU\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_erase(void)
|
||||
{
|
||||
if (xfer(C_RESET, NULL, 0, 3, FET_RESET_ALL, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet: reset before erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xfer(C_CONFIGURE, NULL, 0, 2, 2, 0x26) < 0) {
|
||||
fprintf(stderr, "fet: config (1) failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xfer(C_CONFIGURE, NULL, 0, 2, 5, 0) < 0) {
|
||||
fprintf(stderr, "fet: config (2) failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xfer(C_ERASE, NULL, 0, 3, FET_ERASE_ALL, 0x1000, 0x100) < 0) {
|
||||
fprintf(stderr, "fet: erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fet_wait(void)
|
||||
{
|
||||
for (;;) {
|
||||
/* Without this delay, breakpoints can get lost. */
|
||||
if (usleep(500000) < 0)
|
||||
break;
|
||||
|
||||
if (xfer(C_STATE, NULL, 0, 1, 0) < 0) {
|
||||
fprintf(stderr, "fet: polling failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(fet_reply.argv[0] & FET_POLL_RUNNING))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fet_control(device_ctl_t action)
|
||||
{
|
||||
switch (action) {
|
||||
case DEVICE_CTL_RESET:
|
||||
return do_reset();
|
||||
|
||||
case DEVICE_CTL_RUN:
|
||||
return do_run(FET_RUN_FREE);
|
||||
|
||||
case DEVICE_CTL_RUN_BP:
|
||||
return do_run(FET_RUN_BREAKPOINT);
|
||||
|
||||
case DEVICE_CTL_HALT:
|
||||
return do_halt();
|
||||
|
||||
case DEVICE_CTL_STEP:
|
||||
if (do_run(FET_RUN_STEP) < 0)
|
||||
return -1;
|
||||
if (fet_wait() < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
case DEVICE_CTL_ERASE:
|
||||
return do_erase();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fet_breakpoint(u_int16_t addr)
|
||||
{
|
||||
if (xfer(C_BREAKPOINT, NULL, 0, 2, 0, addr) < 0) {
|
||||
fprintf(stderr, "fet: set breakpoint failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fet_getregs(u_int16_t *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (xfer(C_READREGISTERS, NULL, 0, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if (fet_reply.datalen < FET_NUM_REGS * 4) {
|
||||
fprintf(stderr, "fet_get_context: short reply (%d bytes)\n",
|
||||
if (fet_reply.datalen < DEVICE_NUM_REGS * 4) {
|
||||
fprintf(stderr, "fet: short reply (%d bytes)\n",
|
||||
fet_reply.datalen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < FET_NUM_REGS; i++)
|
||||
for (i = 0; i < DEVICE_NUM_REGS; i++)
|
||||
regs[i] = BUFFER_WORD(fet_reply.data, i * 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_set_context(u_int16_t *regs)
|
||||
static int fet_setregs(const u_int16_t *regs)
|
||||
{
|
||||
u_int8_t buf[FET_NUM_REGS * 4];;
|
||||
u_int8_t buf[DEVICE_NUM_REGS * 4];;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
for (i = 0; i < FET_NUM_REGS; i++) {
|
||||
for (i = 0; i < DEVICE_NUM_REGS; i++) {
|
||||
buf[i * 4] = regs[i] & 0xff;
|
||||
buf[i * 4 + 1] = regs[i] >> 8;
|
||||
}
|
||||
|
@ -722,14 +759,14 @@ int fet_set_context(u_int16_t *regs)
|
|||
1, 0xffff);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "fet_set_context: context set failed\n");
|
||||
fprintf(stderr, "fet: context set failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_read_mem(u_int16_t addr, u_int8_t *buffer, int count)
|
||||
int fet_readmem(u_int16_t addr, u_int8_t *buffer, int count)
|
||||
{
|
||||
while (count) {
|
||||
int plen = count > 128 ? 128 : count;
|
||||
|
@ -755,7 +792,7 @@ int fet_read_mem(u_int16_t addr, u_int8_t *buffer, int count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count)
|
||||
int fet_writemem(u_int16_t addr, const u_int8_t *buffer, int count)
|
||||
{
|
||||
while (count) {
|
||||
int plen = count > 128 ? 128 : count;
|
||||
|
@ -769,8 +806,8 @@ int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count)
|
|||
1, addr);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "fet_write_mem: failed to write "
|
||||
"to 0x%04x\n", addr);
|
||||
fprintf(stderr, "fet: failed to write to 0x%04x\n",
|
||||
addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -782,69 +819,92 @@ int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fet_erase(int type, u_int16_t addr, int len)
|
||||
const static struct device fet_device = {
|
||||
.close = fet_close,
|
||||
.control = fet_control,
|
||||
.wait = fet_wait,
|
||||
.breakpoint = fet_breakpoint,
|
||||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.readmem = fet_readmem,
|
||||
.writemem = fet_writemem
|
||||
};
|
||||
|
||||
const struct device *fet_open(const struct fet_transport *tr,
|
||||
int proto_flags, int vcc_mv)
|
||||
{
|
||||
if (xfer(C_CONFIGURE, NULL, 0, 2, 2, 0x26) < 0) {
|
||||
fprintf(stderr, "fet_erase: config (1) failed\n");
|
||||
return -1;
|
||||
fet_transport = tr;
|
||||
fet_is_rf2500 = proto_flags & FET_PROTO_RF2500;
|
||||
init_codes();
|
||||
|
||||
if (xfer(C_INITIALIZE, NULL, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet: open failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (xfer(C_CONFIGURE, NULL, 0, 2, 5, 0) < 0) {
|
||||
fprintf(stderr, "fet_erase: config (2) failed\n");
|
||||
return -1;
|
||||
fet_version = fet_reply.argv[0];
|
||||
printf("FET protocol version is %d\n", fet_version);
|
||||
|
||||
if (xfer(39, NULL, 0, 1, 4) < 0) {
|
||||
fprintf(stderr, "fet: init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (xfer(C_ERASE, NULL, 0, 3, type, addr, len) < 0) {
|
||||
fprintf(stderr, "fet_erase: erase command failed\n");
|
||||
return -1;
|
||||
/* configure: Spy-Bi-Wire or JTAG */
|
||||
if (xfer(C_CONFIGURE, NULL, 0,
|
||||
2, 8, (proto_flags & FET_PROTO_SPYBIWIRE) ? 1 : 0) < 0) {
|
||||
fprintf(stderr, "fet: configure failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_poll(void)
|
||||
{
|
||||
/* Without this delay, breakpoints can get lost. */
|
||||
if (usleep(500000) < 0)
|
||||
return -1;
|
||||
|
||||
if (xfer(C_STATE, NULL, 0, 1, 0) < 0) {
|
||||
fprintf(stderr, "fet_poll: polling failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fet_reply.argv[0];
|
||||
}
|
||||
|
||||
int fet_run(int type)
|
||||
{
|
||||
int wr = type & FET_RUN_RELEASE ? 1 : 0;
|
||||
|
||||
type &= ~FET_RUN_RELEASE;
|
||||
if (xfer(C_RUN, NULL, 0, 2, type, wr) < 0) {
|
||||
fprintf(stderr, "fet_run: run failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_stop(void)
|
||||
{
|
||||
if (xfer(C_STATE, NULL, 0, 1, 1) < 0) {
|
||||
fprintf(stderr, "fet_stop: stop failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fet_break(int which, u_int16_t addr)
|
||||
{
|
||||
if (xfer(C_BREAKPOINT, NULL, 0, 2, which, addr) < 0) {
|
||||
fprintf(stderr, "fet_break: set breakpoint failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
printf("Configured for %s\n",
|
||||
(proto_flags & FET_PROTO_SPYBIWIRE) ? "Spy-Bi-Wire" : "JTAG");
|
||||
|
||||
/* Identify the chip */
|
||||
if (do_identify() < 0) {
|
||||
fprintf(stderr, "fet: identify failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set VCC */
|
||||
if (xfer(C_VCC, NULL, 0, 2, vcc_mv, 0) < 0) {
|
||||
fprintf(stderr, "fet: set VCC failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf("Set Vcc: %d mV\n", 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.
|
||||
*/
|
||||
if (fet_is_rf2500 && xfer(0x28, NULL, 0, 2, 0, 0) < 0) {
|
||||
fprintf(stderr, "fet: command 0x28 failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Who knows what this is. Without it, register reads don't work.
|
||||
* This is RF2500-specific.
|
||||
*/
|
||||
if (fet_is_rf2500) {
|
||||
static const u_int8_t 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,
|
||||
0x01, 0x00, 0xd7, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x07, 0x10, 0x0e, 0xc4, 0x09, 0x70, 0x17,
|
||||
0x58, 0x1b, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x0f, 0x1f, 0x0f,
|
||||
0xff, 0xff
|
||||
};
|
||||
|
||||
if (xfer(0x29, data, sizeof(data), 4, 0, 0x39, 0x31,
|
||||
sizeof(data)) < 0) {
|
||||
fprintf(stderr, "fet: command 0x29 failed\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &fet_device;
|
||||
}
|
||||
|
|
98
fet.h
98
fet.h
|
@ -1,98 +0,0 @@
|
|||
/* MSPDebug - debugging tool for the eZ430
|
||||
* Copyright (C) 2009 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 FET_H_
|
||||
#define FET_H_
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
/* Start up the FET controller by specifying a transport, a voltage in
|
||||
* millivolts and a set of protocol mode flags.
|
||||
*/
|
||||
#define FET_PROTO_SPYBIWIRE 0x01
|
||||
#define FET_PROTO_RF2500 0x02
|
||||
|
||||
int fet_open(const struct fet_transport *transport,
|
||||
int proto_flags, int vcc_mv);
|
||||
|
||||
/* Shut down the connection to the FET. This also closes the underlying
|
||||
* transport.
|
||||
*/
|
||||
int fet_close(void);
|
||||
|
||||
/* Issue a reset to the CPU. The CPU can be reset via any combination
|
||||
* of three methods, and you can choose whether or not to leave the CPU
|
||||
* halted after reset.
|
||||
*/
|
||||
#define FET_RESET_PUC 0x01
|
||||
#define FET_RESET_RST 0x02
|
||||
#define FET_RESET_VCC 0x04
|
||||
#define FET_RESET_ALL 0x07
|
||||
#define FET_RESET_HALT 0x10
|
||||
#define FET_RESET_RELEASE 0x20
|
||||
|
||||
int fet_reset(int flags);
|
||||
|
||||
/* Retrieve and store register values. There are 16 16-bit registers in
|
||||
* the MSP430 CPU. regs must always be a pointer to an array of 16
|
||||
* u_int16_t.
|
||||
*/
|
||||
#define FET_NUM_REGS 16
|
||||
|
||||
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_SEGMENT 0
|
||||
#define FET_ERASE_MAIN 1
|
||||
#define FET_ERASE_ALL 2
|
||||
|
||||
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.
|
||||
*/
|
||||
int fet_read_mem(u_int16_t addr, u_int8_t *buffer, int count);
|
||||
int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count);
|
||||
|
||||
/* Fetch the device status. If the device is currently running, then
|
||||
* the FET_POLL_RUNNING flag will be set. FET_POLL_BREAKPOINT is set
|
||||
* when the device hits the preset breakpoint, and then resets on the
|
||||
* next call to fet_poll().
|
||||
*/
|
||||
#define FET_POLL_RUNNING 0x01
|
||||
#define FET_POLL_BREAKPOINT 0x02
|
||||
|
||||
int fet_poll(void);
|
||||
|
||||
/* CPU run/step/stop control. While the CPU is running, memory and
|
||||
* registers are inaccessible (only fet_poll() or fet_stop()) will
|
||||
* work.
|
||||
*/
|
||||
#define FET_RUN_FREE 1
|
||||
#define FET_RUN_STEP 2
|
||||
#define FET_RUN_BREAKPOINT 3
|
||||
#define FET_RUN_RELEASE 0x10
|
||||
|
||||
int fet_run(int type);
|
||||
int fet_stop(void);
|
||||
|
||||
/* Set a breakpoint address */
|
||||
int fet_break(int which, u_int16_t addr);
|
||||
|
||||
#endif
|
64
main.c
64
main.c
|
@ -25,10 +25,12 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "dis.h"
|
||||
#include "fet.h"
|
||||
#include "device.h"
|
||||
#include "binfile.h"
|
||||
#include "stab.h"
|
||||
|
||||
static const struct device *msp430_dev;
|
||||
|
||||
void hexdump(int addr, const u_int8_t *data, int len)
|
||||
{
|
||||
int offset = 0;
|
||||
|
@ -93,7 +95,7 @@ char *get_arg(char **text)
|
|||
}
|
||||
|
||||
#define REG_COLUMNS 4
|
||||
#define REG_ROWS ((FET_NUM_REGS + REG_COLUMNS - 1) / REG_COLUMNS)
|
||||
#define REG_ROWS ((DEVICE_NUM_REGS + REG_COLUMNS - 1) / REG_COLUMNS)
|
||||
|
||||
static void show_regs(u_int16_t *regs)
|
||||
{
|
||||
|
@ -106,7 +108,7 @@ static void show_regs(u_int16_t *regs)
|
|||
for (j = 0; j < REG_COLUMNS; j++) {
|
||||
int k = j * REG_ROWS + i;
|
||||
|
||||
if (k < FET_NUM_REGS)
|
||||
if (k < DEVICE_NUM_REGS)
|
||||
printf("(r%02d: %04x) ", k, regs[k]);
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -154,7 +156,7 @@ static int cmd_md(char **arg)
|
|||
u_int8_t buf[128];
|
||||
int blen = length > sizeof(buf) ? sizeof(buf) : length;
|
||||
|
||||
if (fet_read_mem(offset, buf, blen) < 0)
|
||||
if (msp430_dev->readmem(offset, buf, blen) < 0)
|
||||
return -1;
|
||||
hexdump(offset, buf, blen);
|
||||
|
||||
|
@ -243,7 +245,7 @@ static int cmd_dis(char **arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (fet_read_mem(offset, buf, length) < 0)
|
||||
if (msp430_dev->readmem(offset, buf, length) < 0)
|
||||
return -1;
|
||||
|
||||
disassemble(offset, (u_int8_t *)buf, length);
|
||||
|
@ -252,20 +254,20 @@ static int cmd_dis(char **arg)
|
|||
|
||||
static int cmd_reset(char **arg)
|
||||
{
|
||||
return fet_reset(FET_RESET_ALL | FET_RESET_HALT);
|
||||
return msp430_dev->control(DEVICE_CTL_RESET);
|
||||
}
|
||||
|
||||
static int cmd_regs(char **arg)
|
||||
{
|
||||
u_int16_t regs[FET_NUM_REGS];
|
||||
u_int16_t regs[DEVICE_NUM_REGS];
|
||||
u_int8_t code[16];
|
||||
|
||||
if (fet_get_context(regs) < 0)
|
||||
if (msp430_dev->getregs(regs) < 0)
|
||||
return -1;
|
||||
show_regs(regs);
|
||||
|
||||
/* Try to disassemble the instruction at PC */
|
||||
if (fet_read_mem(regs[0], code, sizeof(code)) < 0)
|
||||
if (msp430_dev->readmem(regs[0], code, sizeof(code)) < 0)
|
||||
return 0;
|
||||
|
||||
disassemble(regs[0], (u_int8_t *)code, sizeof(code));
|
||||
|
@ -285,26 +287,19 @@ static int cmd_run(char **arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
fet_break(0, addr);
|
||||
} else {
|
||||
fet_break(0, 0);
|
||||
msp430_dev->breakpoint(addr);
|
||||
}
|
||||
|
||||
if (fet_run(bp_text ? FET_RUN_BREAKPOINT : FET_RUN_FREE) < 0)
|
||||
if (msp430_dev->control(bp_text ?
|
||||
DEVICE_CTL_RUN_BP : DEVICE_CTL_RUN) < 0)
|
||||
return -1;
|
||||
|
||||
printf("Running. Press Ctrl+C to interrupt...");
|
||||
fflush(stdout);
|
||||
|
||||
for (;;) {
|
||||
int r = fet_poll();
|
||||
|
||||
if (r < 0 || !(r & FET_POLL_RUNNING))
|
||||
break;
|
||||
}
|
||||
|
||||
msp430_dev->wait();
|
||||
printf("\n");
|
||||
if (fet_stop() < 0)
|
||||
|
||||
if (msp430_dev->control(DEVICE_CTL_HALT) < 0)
|
||||
return -1;
|
||||
|
||||
return cmd_regs(NULL);
|
||||
|
@ -316,7 +311,7 @@ static int cmd_set(char **arg)
|
|||
char *val_text = get_arg(arg);
|
||||
int reg;
|
||||
int value = 0;
|
||||
u_int16_t regs[FET_NUM_REGS];
|
||||
u_int16_t regs[DEVICE_NUM_REGS];
|
||||
|
||||
if (!(reg_text && val_text)) {
|
||||
fprintf(stderr, "set: must specify a register and a value\n");
|
||||
|
@ -332,15 +327,15 @@ static int cmd_set(char **arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (reg < 0 || reg >= FET_NUM_REGS) {
|
||||
if (reg < 0 || reg >= DEVICE_NUM_REGS) {
|
||||
fprintf(stderr, "set: register out of range: %d\n", reg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fet_get_context(regs) < 0)
|
||||
if (msp430_dev->getregs(regs) < 0)
|
||||
return -1;
|
||||
regs[reg] = value;
|
||||
if (fet_set_context(regs) < 0)
|
||||
if (msp430_dev->setregs(regs) < 0)
|
||||
return -1;
|
||||
|
||||
show_regs(regs);
|
||||
|
@ -349,9 +344,7 @@ static int cmd_set(char **arg)
|
|||
|
||||
static int cmd_step(char **arg)
|
||||
{
|
||||
if (fet_run(FET_RUN_STEP) < 0)
|
||||
return -1;
|
||||
if (fet_poll() < 0)
|
||||
if (msp430_dev->control(DEVICE_CTL_STEP) < 0)
|
||||
return -1;
|
||||
|
||||
return cmd_regs(NULL);
|
||||
|
@ -383,13 +376,13 @@ static int prog_flush(void)
|
|||
|
||||
if (!prog_have_erased) {
|
||||
printf("Erasing...\n");
|
||||
if (fet_erase(FET_ERASE_ALL, 0x1000, 0x100) < 0)
|
||||
if (msp430_dev->control(DEVICE_CTL_ERASE) < 0)
|
||||
return -1;
|
||||
prog_have_erased = 1;
|
||||
}
|
||||
|
||||
printf("Writing %3d bytes to %04x...\n", wlen, prog_addr);
|
||||
if (fet_write_mem(prog_addr, prog_buf, wlen) < 0)
|
||||
if (msp430_dev->writemem(prog_addr, prog_buf, wlen) < 0)
|
||||
return -1;
|
||||
|
||||
memmove(prog_buf, prog_buf + wlen, prog_len - wlen);
|
||||
|
@ -442,7 +435,7 @@ static int cmd_prog(char **arg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (fet_reset(FET_RESET_ALL | FET_RESET_HALT) < 0) {
|
||||
if (msp430_dev->control(DEVICE_CTL_HALT) < 0) {
|
||||
fclose(in);
|
||||
return -1;
|
||||
}
|
||||
|
@ -711,7 +704,8 @@ int main(int argc, char **argv)
|
|||
/* Then initialize the device */
|
||||
if (!want_jtag)
|
||||
flags |= FET_PROTO_SPYBIWIRE;
|
||||
if (fet_open(trans, flags, 3000) < 0)
|
||||
msp430_dev = fet_open(trans, flags, 3000);
|
||||
if (!msp430_dev)
|
||||
return -1;
|
||||
|
||||
if (optind < argc) {
|
||||
|
@ -721,8 +715,6 @@ int main(int argc, char **argv)
|
|||
reader_loop();
|
||||
}
|
||||
|
||||
fet_run(FET_RUN_FREE | FET_RUN_RELEASE);
|
||||
fet_close();
|
||||
|
||||
msp430_dev->close();
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue