Added mechanism for target driver to add new monitor commands.

This commit is contained in:
Gareth McMullin 2012-06-24 21:37:10 +12:00
parent a16123997b
commit 03fdd23e9c
6 changed files with 89 additions and 32 deletions

View File

@ -20,8 +20,6 @@
/* This file implements a basic command interpreter for GDB 'monitor' /* This file implements a basic command interpreter for GDB 'monitor'
* commands. * commands.
*
* TODO: Add a mechanism for target driver so register new commands.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -37,15 +35,15 @@
#include "adiv5.h" #include "adiv5.h"
static void cmd_version(void); static bool cmd_version(void);
static void cmd_help(void); static bool cmd_help(void);
static void cmd_jtag_scan(void); static bool cmd_jtag_scan(void);
static void cmd_swdp_scan(void); static bool cmd_swdp_scan(void);
static void cmd_targets(void); static bool cmd_targets(void);
static void cmd_morse(void); static bool cmd_morse(void);
#ifdef PLATFORM_HAS_TRACESWO #ifdef PLATFORM_HAS_TRACESWO
static void cmd_traceswo(void); static bool cmd_traceswo(void);
#endif #endif
const struct command_s cmd_list[] = { const struct command_s cmd_list[] = {
@ -64,6 +62,7 @@ const struct command_s cmd_list[] = {
int command_process(char *cmd) int command_process(char *cmd)
{ {
struct target_command_s *tc;
const struct command_s *c; const struct command_s *c;
int argc = 0; int argc = 0;
const char **argv; const char **argv;
@ -83,32 +82,47 @@ int command_process(char *cmd)
/* Accept a partial match as GDB does. /* Accept a partial match as GDB does.
* So 'mon ver' will match 'monitor version' * So 'mon ver' will match 'monitor version'
*/ */
if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) { if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
c->handler(argc, argv); return !c->handler(cur_target, argc, argv);
return 0;
}
} }
for (tc = cur_target->commands; tc; tc = tc->next)
for(c = tc->cmds; c->cmd; c++)
if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
return !c->handler(cur_target, argc, argv);
return -1; return -1;
} }
void cmd_version(void) bool cmd_version(void)
{ {
gdb_out("Black Magic Probe (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")\n"); gdb_out("Black Magic Probe (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")\n");
gdb_out("Copyright (C) 2011 Black Sphere Technologies Ltd.\n"); gdb_out("Copyright (C) 2011 Black Sphere Technologies Ltd.\n");
gdb_out("License GPLv3+: GNU GPL version 3 or later " gdb_out("License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>\n\n"); "<http://gnu.org/licenses/gpl.html>\n\n");
return true;
} }
void cmd_help(void) bool cmd_help(void)
{ {
struct target_command_s *tc;
const struct command_s *c; const struct command_s *c;
gdb_out("General commands:\n");
for(c = cmd_list; c->cmd; c++) for(c = cmd_list; c->cmd; c++)
gdb_outf("%s -- %s\n", c->cmd, c->help); gdb_outf("\t%s -- %s\n", c->cmd, c->help);
for (tc = cur_target->commands; tc; tc = tc->next) {
gdb_outf("%s specific commands:\n", tc->specific_name);
for(c = tc->cmds; c->cmd; c++)
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
}
return true;
} }
void cmd_jtag_scan(void) bool cmd_jtag_scan(void)
{ {
gdb_outf("Target voltage: %s\n", platform_target_voltage()); gdb_outf("Target voltage: %s\n", platform_target_voltage());
@ -116,11 +130,11 @@ void cmd_jtag_scan(void)
if(devs < 0) { if(devs < 0) {
gdb_out("JTAG device scan failed!\n"); gdb_out("JTAG device scan failed!\n");
return; return false;
} }
if(devs == 0) { if(devs == 0) {
gdb_out("JTAG scan found no devices!\n"); gdb_out("JTAG scan found no devices!\n");
return; return false;
} }
gdb_outf("Device IR Len IDCODE Description\n"); gdb_outf("Device IR Len IDCODE Description\n");
for(int i = 0; i < jtag_dev_count; i++) for(int i = 0; i < jtag_dev_count; i++)
@ -129,30 +143,33 @@ void cmd_jtag_scan(void)
jtag_devs[i].descr); jtag_devs[i].descr);
gdb_out("\n"); gdb_out("\n");
cmd_targets(); cmd_targets();
return true;
} }
void cmd_swdp_scan(void) bool cmd_swdp_scan(void)
{ {
gdb_outf("Target voltage: %s\n", platform_target_voltage()); gdb_outf("Target voltage: %s\n", platform_target_voltage());
if(adiv5_swdp_scan() < 0) { if(adiv5_swdp_scan() < 0) {
gdb_out("SW-DP scan failed!\n"); gdb_out("SW-DP scan failed!\n");
return; return false;
} }
gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode); gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode);
cmd_targets(); cmd_targets();
return true;
} }
void cmd_targets(void) bool cmd_targets(void)
{ {
struct target_s *t; struct target_s *t;
int i; int i;
if(!target_list) { if(!target_list) {
gdb_out("No usable targets found.\n"); gdb_out("No usable targets found.\n");
return; return false;
} }
gdb_out("Available Targets:\n"); gdb_out("Available Targets:\n");
@ -160,20 +177,24 @@ void cmd_targets(void)
for(t = target_list, i = 1; t; t = t->next, i++) for(t = target_list, i = 1; t; t = t->next, i++)
gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ', gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ',
t->driver); t->driver);
return true;
} }
void cmd_morse(void) bool cmd_morse(void)
{ {
if(morse_msg) if(morse_msg)
gdb_outf("%s\n", morse_msg); gdb_outf("%s\n", morse_msg);
return true;
} }
#ifdef PLATFORM_HAS_TRACESWO #ifdef PLATFORM_HAS_TRACESWO
static void cmd_traceswo(void) static bool cmd_traceswo(void)
{ {
extern char serial_no[9]; extern char serial_no[9];
traceswo_init(); traceswo_init();
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85); gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
return true;
} }
#endif #endif

View File

@ -330,9 +330,13 @@ handle_q_packet(char *packet, int len)
unhexify(data, packet+6, datalen); unhexify(data, packet+6, datalen);
data[datalen] = 0; /* add terminating null */ data[datalen] = 0; /* add terminating null */
if(command_process(data) < 0) int c = command_process(data);
gdb_putpacket("", 0); if(c < 0)
else gdb_putpacket("OK", 2); gdb_putpacketz("");
else if(c == 0)
gdb_putpacketz("OK");
else
gdb_putpacketz("E");
} else if (!strncmp (packet, "qSupported", 10)) { } else if (!strncmp (packet, "qSupported", 10)) {
/* Query supported protocol features */ /* Query supported protocol features */

View File

@ -22,9 +22,10 @@
#define __COMMAND_H #define __COMMAND_H
#include "general.h" #include "general.h"
#include "target.h"
int command_process(char *cmd); int command_process(char *cmd);
typedef void (*cmd_handler)(int argc, const char **argv); typedef bool (*cmd_handler)(target *t, int argc, const char **argv);
struct command_s { struct command_s {
const char *cmd; const char *cmd;

View File

@ -29,6 +29,7 @@
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#endif #endif

View File

@ -27,9 +27,6 @@
typedef struct target_s target; typedef struct target_s target;
target *target_new(unsigned size);
void target_list_free(void);
/* Halt/resume functions */ /* Halt/resume functions */
#define target_attach(target) \ #define target_attach(target) \
(target)->attach(target) (target)->attach(target)
@ -164,13 +161,25 @@ struct target_s {
const uint8_t *src, int len); const uint8_t *src, int len);
const char *driver; const char *driver;
struct target_command_s *commands;
int size; int size;
struct target_s *next; struct target_s *next;
};
struct target_command_s {
const char *specific_name;
const struct command_s *cmds;
struct target_command_s *next;
}; };
extern target *target_list, *cur_target, *last_target; extern target *target_list, *cur_target, *last_target;
target *target_new(unsigned size);
void target_list_free(void);
void target_add_commands(target *t, const struct command_s *cmds, const char *name);
/* Probe for various targets. /* Probe for various targets.
* Actual functions implemented in their respective drivers. * Actual functions implemented in their respective drivers.
*/ */

View File

@ -38,11 +38,32 @@ target *target_new(unsigned size)
void target_list_free(void) void target_list_free(void)
{ {
struct target_command_s *tc;
while(target_list) { while(target_list) {
target *t = target_list->next; target *t = target_list->next;
while (target_list->commands) {
tc = target_list->commands->next;
free(target_list->commands);
target_list->commands = tc;
}
free(target_list); free(target_list);
target_list = t; target_list = t;
} }
last_target = cur_target = NULL; last_target = cur_target = NULL;
} }
void target_add_commands(target *t, const struct command_s *cmds, const char *name)
{
struct target_command_s *tc;
if (t->commands) {
for (tc = t->commands; tc->next; tc = tc->next);
tc = tc->next = malloc(sizeof(*tc));
} else {
t->commands = tc = malloc(sizeof(*tc));
}
tc->specific_name = name;
tc->cmds = cmds;
tc->next = NULL;
}