Added mechanism for target driver to add new monitor commands.
This commit is contained in:
parent
a16123997b
commit
03fdd23e9c
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
21
src/target.c
21
src/target.c
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue