255 lines
6.2 KiB
C
255 lines
6.2 KiB
C
/*
|
|
* This file is part of the Black Magic Debug project.
|
|
*
|
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* This file implements a basic command interpreter for GDB 'monitor'
|
|
* commands.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "general.h"
|
|
|
|
#include "command.h"
|
|
#include "gdb_packet.h"
|
|
|
|
#include "jtag_scan.h"
|
|
#include "target.h"
|
|
#include "morse.h"
|
|
|
|
#include "adiv5.h"
|
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
|
# include "traceswo.h"
|
|
#endif
|
|
|
|
static bool cmd_version(void);
|
|
static bool cmd_help(target *t);
|
|
|
|
static bool cmd_jtag_scan(target *t, int argc, char **argv);
|
|
static bool cmd_swdp_scan(void);
|
|
static bool cmd_targets(target *t);
|
|
static bool cmd_morse(void);
|
|
static bool cmd_connect_srst(target *t, int argc, const char **argv);
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
|
static bool cmd_target_power(target *t, int argc, const char **argv);
|
|
#endif
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
|
static bool cmd_traceswo(void);
|
|
#endif
|
|
|
|
const struct command_s cmd_list[] = {
|
|
{"version", (cmd_handler)cmd_version, "Display firmware version info"},
|
|
{"help", (cmd_handler)cmd_help, "Display help for monitor commands"},
|
|
{"jtag_scan", (cmd_handler)cmd_jtag_scan, "Scan JTAG chain for devices" },
|
|
{"swdp_scan", (cmd_handler)cmd_swdp_scan, "Scan SW-DP for devices" },
|
|
{"targets", (cmd_handler)cmd_targets, "Display list of available targets" },
|
|
{"morse", (cmd_handler)cmd_morse, "Display morse error message" },
|
|
{"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" },
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
|
{"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"},
|
|
#endif
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
|
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" },
|
|
#endif
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
int command_process(target *t, char *cmd)
|
|
{
|
|
struct target_command_s *tc;
|
|
const struct command_s *c;
|
|
int argc = 0;
|
|
const char **argv;
|
|
|
|
/* Initial estimate for argc */
|
|
for(char *s = cmd; *s; s++)
|
|
if((*s == ' ') || (*s == '\t')) argc++;
|
|
|
|
argv = alloca(sizeof(const char *) * argc);
|
|
|
|
/* Tokenize cmd to find argv */
|
|
for(argc = 0, argv[argc] = strtok(cmd, " \t");
|
|
argv[argc]; argv[++argc] = strtok(NULL, " \t"));
|
|
|
|
/* Look for match and call handler */
|
|
for(c = cmd_list; c->cmd; c++) {
|
|
/* Accept a partial match as GDB does.
|
|
* So 'mon ver' will match 'monitor version'
|
|
*/
|
|
if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
|
|
return !c->handler(t, argc, argv);
|
|
}
|
|
|
|
if (!t)
|
|
return -1;
|
|
|
|
for (tc = t->commands; tc; tc = tc->next)
|
|
for(c = tc->cmds; c->cmd; c++)
|
|
if(!strncmp(argv[0], c->cmd, strlen(argv[0])))
|
|
return !c->handler(t, argc, argv);
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool cmd_version(void)
|
|
{
|
|
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("License GPLv3+: GNU GPL version 3 or later "
|
|
"<http://gnu.org/licenses/gpl.html>\n\n");
|
|
|
|
return true;
|
|
}
|
|
|
|
bool cmd_help(target *t)
|
|
{
|
|
struct target_command_s *tc;
|
|
const struct command_s *c;
|
|
|
|
gdb_out("General commands:\n");
|
|
for(c = cmd_list; c->cmd; c++)
|
|
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
|
|
|
|
if (!t)
|
|
return -1;
|
|
|
|
for (tc = t->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;
|
|
}
|
|
|
|
static bool cmd_jtag_scan(target *t, int argc, char **argv)
|
|
{
|
|
(void)t;
|
|
uint8_t *irlens = NULL;
|
|
|
|
gdb_outf("Target voltage: %s\n", platform_target_voltage());
|
|
|
|
if (argc > 1) {
|
|
/* Accept a list of IR lengths on command line */
|
|
irlens = alloca(argc);
|
|
for (int i = 1; i < argc; i++)
|
|
irlens[i-1] = atoi(argv[i]);
|
|
irlens[argc-1] = 0;
|
|
}
|
|
|
|
int devs = jtag_scan(irlens);
|
|
|
|
if(devs < 0) {
|
|
gdb_out("JTAG device scan failed!\n");
|
|
return false;
|
|
}
|
|
if(devs == 0) {
|
|
gdb_out("JTAG scan found no devices!\n");
|
|
return false;
|
|
}
|
|
gdb_outf("Device IR Len IDCODE Description\n");
|
|
for(int i = 0; i < jtag_dev_count; i++)
|
|
gdb_outf("%d\t%d\t0x%08lX %s\n", i,
|
|
jtag_devs[i].ir_len, jtag_devs[i].idcode,
|
|
jtag_devs[i].descr);
|
|
gdb_out("\n");
|
|
cmd_targets(NULL);
|
|
return true;
|
|
}
|
|
|
|
bool cmd_swdp_scan(void)
|
|
{
|
|
gdb_outf("Target voltage: %s\n", platform_target_voltage());
|
|
|
|
if(adiv5_swdp_scan() < 0) {
|
|
gdb_out("SW-DP scan failed!\n");
|
|
return false;
|
|
}
|
|
|
|
//gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode);
|
|
|
|
cmd_targets(NULL);
|
|
return true;
|
|
|
|
}
|
|
|
|
bool cmd_targets(target *cur_target)
|
|
{
|
|
struct target_s *t;
|
|
int i;
|
|
|
|
if(!target_list) {
|
|
gdb_out("No usable targets found.\n");
|
|
return false;
|
|
}
|
|
|
|
gdb_out("Available Targets:\n");
|
|
gdb_out("No. Att Driver\n");
|
|
for(t = target_list, i = 1; t; t = t->next, i++)
|
|
gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ',
|
|
t->driver);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool cmd_morse(void)
|
|
{
|
|
if(morse_msg)
|
|
gdb_outf("%s\n", morse_msg);
|
|
return true;
|
|
}
|
|
|
|
static bool cmd_connect_srst(target *t, int argc, const char **argv)
|
|
{
|
|
(void)t;
|
|
if (argc == 1)
|
|
gdb_outf("Assert SRST during connect: %s\n",
|
|
connect_assert_srst ? "enabled" : "disabled");
|
|
else
|
|
connect_assert_srst = !strcmp(argv[1], "enable");
|
|
return true;
|
|
}
|
|
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
|
static bool cmd_target_power(target *t, int argc, const char **argv)
|
|
{
|
|
(void)t;
|
|
if (argc == 1)
|
|
gdb_outf("Target Power: %s\n",
|
|
platform_target_get_power() ? "enabled" : "disabled");
|
|
else
|
|
platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1])));
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
|
static bool cmd_traceswo(void)
|
|
{
|
|
extern char serial_no[9];
|
|
traceswo_init();
|
|
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
|
|
return true;
|
|
}
|
|
#endif
|
|
|