2011-02-04 07:23:52 +00:00
|
|
|
/*
|
|
|
|
* 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 "general.h"
|
2015-03-01 04:56:03 +00:00
|
|
|
#include "exception.h"
|
2011-02-04 07:23:52 +00:00
|
|
|
#include "command.h"
|
|
|
|
#include "gdb_packet.h"
|
|
|
|
#include "target.h"
|
2015-03-01 06:05:10 +00:00
|
|
|
#include "morse.h"
|
2015-04-04 03:21:33 +00:00
|
|
|
#include "version.h"
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2013-04-16 19:36:19 +00:00
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
|
|
|
# include "traceswo.h"
|
|
|
|
#endif
|
|
|
|
|
2016-06-30 02:18:05 +00:00
|
|
|
typedef bool (*cmd_handler)(target *t, int argc, const char **argv);
|
|
|
|
|
|
|
|
struct command_s {
|
|
|
|
const char *cmd;
|
|
|
|
cmd_handler handler;
|
|
|
|
|
|
|
|
const char *help;
|
|
|
|
};
|
|
|
|
|
2018-06-13 10:13:16 +00:00
|
|
|
enum assert_srst_t{
|
|
|
|
ASSERT_NEVER = 0,
|
|
|
|
ASSERT_UNTIL_SCAN,
|
|
|
|
ASSERT_UNTIL_ATTACH
|
|
|
|
};
|
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
static bool cmd_version(void);
|
2012-06-27 09:26:08 +00:00
|
|
|
static bool cmd_help(target *t);
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2012-06-30 04:47:23 +00:00
|
|
|
static bool cmd_jtag_scan(target *t, int argc, char **argv);
|
2012-06-24 09:37:10 +00:00
|
|
|
static bool cmd_swdp_scan(void);
|
2016-06-30 00:04:39 +00:00
|
|
|
static bool cmd_targets(void);
|
2012-06-24 09:37:10 +00:00
|
|
|
static bool cmd_morse(void);
|
2018-06-13 10:13:16 +00:00
|
|
|
static bool cmd_assert_srst(target *t, int argc, const char **argv);
|
2016-06-09 21:51:31 +00:00
|
|
|
static bool cmd_hard_srst(void);
|
2014-08-08 08:22:33 +00:00
|
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
2014-04-11 17:35:55 +00:00
|
|
|
static bool cmd_target_power(target *t, int argc, const char **argv);
|
2014-08-08 08:22:33 +00:00
|
|
|
#endif
|
2012-05-26 03:05:37 +00:00
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
2017-10-26 13:11:55 +00:00
|
|
|
static bool cmd_traceswo(target *t, int argc, const char **argv);
|
2012-05-26 03:05:37 +00:00
|
|
|
#endif
|
2016-06-18 08:26:56 +00:00
|
|
|
#ifdef PLATFORM_HAS_DEBUG
|
|
|
|
static bool cmd_debug_bmp(target *t, int argc, const char **argv);
|
|
|
|
#endif
|
2012-04-17 09:40:39 +00:00
|
|
|
|
2011-02-04 07:23:52 +00:00
|
|
|
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" },
|
2018-06-13 10:13:16 +00:00
|
|
|
{"assert_srst", (cmd_handler)cmd_assert_srst, "Assert SRST until:(never(default)| scan | attach)" },
|
2016-06-09 21:51:31 +00:00
|
|
|
{"hard_srst", (cmd_handler)cmd_hard_srst, "Force a pulse on the hard SRST line - disconnects target" },
|
2014-08-08 08:22:33 +00:00
|
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
2014-04-11 17:35:55 +00:00
|
|
|
{"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"},
|
2014-08-08 08:22:33 +00:00
|
|
|
#endif
|
2012-05-26 03:05:37 +00:00
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
2017-10-26 13:11:55 +00:00
|
|
|
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture [(baudrate) for async swo]" },
|
2016-06-18 08:26:56 +00:00
|
|
|
#endif
|
|
|
|
#ifdef PLATFORM_HAS_DEBUG
|
|
|
|
{"debug_bmp", (cmd_handler)cmd_debug_bmp, "Output BMP \"debug\" strings to the second vcom: (enable|disable)"},
|
2012-05-26 03:05:37 +00:00
|
|
|
#endif
|
2011-02-04 07:23:52 +00:00
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2018-06-13 10:13:16 +00:00
|
|
|
static enum assert_srst_t assert_srst;
|
2016-06-18 08:26:56 +00:00
|
|
|
#ifdef PLATFORM_HAS_DEBUG
|
|
|
|
bool debug_bmp;
|
|
|
|
#endif
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2012-06-27 09:26:08 +00:00
|
|
|
int command_process(target *t, char *cmd)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
|
|
|
const struct command_s *c;
|
|
|
|
int argc = 0;
|
|
|
|
const char **argv;
|
|
|
|
|
|
|
|
/* Initial estimate for argc */
|
2013-06-17 03:53:32 +00:00
|
|
|
for(char *s = cmd; *s; s++)
|
2011-02-04 07:23:52 +00:00
|
|
|
if((*s == ' ') || (*s == '\t')) argc++;
|
|
|
|
|
|
|
|
argv = alloca(sizeof(const char *) * argc);
|
|
|
|
|
|
|
|
/* Tokenize cmd to find argv */
|
2013-06-17 03:53:32 +00:00
|
|
|
for(argc = 0, argv[argc] = strtok(cmd, " \t");
|
2011-02-04 07:23:52 +00:00
|
|
|
argv[argc]; argv[++argc] = strtok(NULL, " \t"));
|
|
|
|
|
|
|
|
/* Look for match and call handler */
|
|
|
|
for(c = cmd_list; c->cmd; c++) {
|
2012-02-11 23:02:50 +00:00
|
|
|
/* Accept a partial match as GDB does.
|
2013-06-17 03:53:32 +00:00
|
|
|
* So 'mon ver' will match 'monitor version'
|
2012-02-11 23:02:50 +00:00
|
|
|
*/
|
2016-06-30 02:18:05 +00:00
|
|
|
if ((argc == 0) || !strncmp(argv[0], c->cmd, strlen(argv[0])))
|
2012-06-27 09:26:08 +00:00
|
|
|
return !c->handler(t, argc, argv);
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-27 09:26:08 +00:00
|
|
|
if (!t)
|
2012-06-26 07:48:50 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-06-30 02:18:05 +00:00
|
|
|
return target_command(t, argc, argv);
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
bool cmd_version(void)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
2016-02-15 06:41:51 +00:00
|
|
|
gdb_outf("Black Magic Probe (Firmware " FIRMWARE_VERSION ") (Hardware Version %d)\n", platform_hwversion());
|
2015-04-04 03:21:33 +00:00
|
|
|
gdb_out("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
|
2011-02-05 02:12:24 +00:00
|
|
|
gdb_out("License GPLv3+: GNU GPL version 3 or later "
|
|
|
|
"<http://gnu.org/licenses/gpl.html>\n\n");
|
2012-06-24 09:37:10 +00:00
|
|
|
|
|
|
|
return true;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-27 09:26:08 +00:00
|
|
|
bool cmd_help(target *t)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
|
|
|
const struct command_s *c;
|
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
gdb_out("General commands:\n");
|
2013-06-17 03:53:32 +00:00
|
|
|
for(c = cmd_list; c->cmd; c++)
|
2012-06-24 09:37:10 +00:00
|
|
|
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
|
|
|
|
|
2012-06-27 09:26:08 +00:00
|
|
|
if (!t)
|
2012-06-26 07:48:50 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-06-30 02:18:05 +00:00
|
|
|
target_command_help(t);
|
2012-06-24 09:37:10 +00:00
|
|
|
|
|
|
|
return true;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-30 04:47:23 +00:00
|
|
|
static bool cmd_jtag_scan(target *t, int argc, char **argv)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
2012-06-30 04:47:23 +00:00
|
|
|
(void)t;
|
2015-03-01 04:56:03 +00:00
|
|
|
uint8_t irlens[argc];
|
2012-06-30 04:47:23 +00:00
|
|
|
|
2012-05-23 09:44:39 +00:00
|
|
|
gdb_outf("Target voltage: %s\n", platform_target_voltage());
|
|
|
|
|
2012-06-30 04:47:23 +00:00
|
|
|
if (argc > 1) {
|
|
|
|
/* Accept a list of IR lengths on command line */
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
irlens[i-1] = atoi(argv[i]);
|
|
|
|
irlens[argc-1] = 0;
|
|
|
|
}
|
|
|
|
|
2018-06-13 10:13:16 +00:00
|
|
|
if(assert_srst != ASSERT_NEVER)
|
|
|
|
platform_srst_set_val(true);
|
|
|
|
if(assert_srst == ASSERT_UNTIL_SCAN)
|
|
|
|
platform_srst_set_val(false);
|
2016-04-19 19:44:57 +00:00
|
|
|
|
2015-03-01 04:56:03 +00:00
|
|
|
int devs = -1;
|
|
|
|
volatile struct exception e;
|
|
|
|
TRY_CATCH (e, EXCEPTION_ALL) {
|
|
|
|
devs = jtag_scan(argc > 1 ? irlens : NULL);
|
|
|
|
}
|
|
|
|
switch (e.type) {
|
|
|
|
case EXCEPTION_TIMEOUT:
|
|
|
|
gdb_outf("Timeout during scan. Is target stuck in WFI?\n");
|
|
|
|
break;
|
|
|
|
case EXCEPTION_ERROR:
|
|
|
|
gdb_outf("Exception: %s\n", e.msg);
|
|
|
|
break;
|
|
|
|
}
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2016-04-19 19:44:57 +00:00
|
|
|
if(devs <= 0) {
|
|
|
|
platform_srst_set_val(false);
|
2011-02-04 07:23:52 +00:00
|
|
|
gdb_out("JTAG device scan failed!\n");
|
2012-06-24 09:37:10 +00:00
|
|
|
return false;
|
2013-06-17 03:53:32 +00:00
|
|
|
}
|
2016-06-30 00:04:39 +00:00
|
|
|
cmd_targets();
|
2016-09-29 05:15:15 +00:00
|
|
|
morse(NULL, false);
|
2012-06-24 09:37:10 +00:00
|
|
|
return true;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
bool cmd_swdp_scan(void)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
2012-05-23 09:44:39 +00:00
|
|
|
gdb_outf("Target voltage: %s\n", platform_target_voltage());
|
|
|
|
|
2018-06-13 10:13:16 +00:00
|
|
|
if(assert_srst != ASSERT_NEVER)
|
|
|
|
platform_srst_set_val(true);
|
|
|
|
if(assert_srst == ASSERT_UNTIL_SCAN)
|
|
|
|
platform_srst_set_val(false);
|
2016-04-19 19:44:57 +00:00
|
|
|
|
2015-03-01 04:56:03 +00:00
|
|
|
int devs = -1;
|
|
|
|
volatile struct exception e;
|
|
|
|
TRY_CATCH (e, EXCEPTION_ALL) {
|
|
|
|
devs = adiv5_swdp_scan();
|
|
|
|
}
|
|
|
|
switch (e.type) {
|
|
|
|
case EXCEPTION_TIMEOUT:
|
|
|
|
gdb_outf("Timeout during scan. Is target stuck in WFI?\n");
|
|
|
|
break;
|
|
|
|
case EXCEPTION_ERROR:
|
|
|
|
gdb_outf("Exception: %s\n", e.msg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-04-19 19:44:57 +00:00
|
|
|
if(devs <= 0) {
|
|
|
|
platform_srst_set_val(false);
|
2011-02-04 07:23:52 +00:00
|
|
|
gdb_out("SW-DP scan failed!\n");
|
2012-06-24 09:37:10 +00:00
|
|
|
return false;
|
2013-06-17 03:53:32 +00:00
|
|
|
}
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2016-06-30 00:04:39 +00:00
|
|
|
cmd_targets();
|
2016-09-29 05:15:15 +00:00
|
|
|
morse(NULL, false);
|
2012-06-24 09:37:10 +00:00
|
|
|
return true;
|
2013-06-17 03:53:32 +00:00
|
|
|
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 00:04:39 +00:00
|
|
|
static void display_target(int i, target *t, void *context)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
2016-06-30 00:04:39 +00:00
|
|
|
(void)context;
|
|
|
|
gdb_outf("%2d %c %s\n", i, target_attached(t)?'*':' ', target_driver_name(t));
|
|
|
|
}
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2016-06-30 00:04:39 +00:00
|
|
|
bool cmd_targets(void)
|
|
|
|
{
|
|
|
|
gdb_out("Available Targets:\n");
|
|
|
|
gdb_out("No. Att Driver\n");
|
|
|
|
if (!target_foreach(display_target, NULL)) {
|
2011-02-04 07:23:52 +00:00
|
|
|
gdb_out("No usable targets found.\n");
|
2012-06-24 09:37:10 +00:00
|
|
|
return false;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
2013-06-17 03:53:32 +00:00
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
return true;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2012-06-24 09:37:10 +00:00
|
|
|
bool cmd_morse(void)
|
2011-02-04 07:23:52 +00:00
|
|
|
{
|
2013-06-17 03:53:32 +00:00
|
|
|
if(morse_msg)
|
2011-02-04 07:23:52 +00:00
|
|
|
gdb_outf("%s\n", morse_msg);
|
2012-06-24 09:37:10 +00:00
|
|
|
return true;
|
2011-02-04 07:23:52 +00:00
|
|
|
}
|
|
|
|
|
2018-06-13 10:13:16 +00:00
|
|
|
static bool cmd_assert_srst(target *t, int argc, const char **argv)
|
2013-05-04 20:46:47 +00:00
|
|
|
{
|
|
|
|
(void)t;
|
2018-06-13 10:13:16 +00:00
|
|
|
if (argc > 1) {
|
|
|
|
if (!strcmp(argv[1], "attach"))
|
|
|
|
assert_srst = ASSERT_UNTIL_ATTACH;
|
|
|
|
else if (!strcmp(argv[1], "scan"))
|
|
|
|
assert_srst = ASSERT_UNTIL_SCAN;
|
|
|
|
else
|
|
|
|
assert_srst = ASSERT_NEVER;
|
|
|
|
}
|
|
|
|
gdb_outf("Assert SRST %s\n",
|
|
|
|
(assert_srst == ASSERT_UNTIL_ATTACH) ? "until attach" :
|
|
|
|
(assert_srst == ASSERT_UNTIL_SCAN) ? "until scan" : "never");
|
2013-05-04 20:46:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
2014-08-08 08:22:33 +00:00
|
|
|
|
2016-06-09 21:51:31 +00:00
|
|
|
static bool cmd_hard_srst(void)
|
|
|
|
{
|
|
|
|
target_list_free();
|
|
|
|
platform_srst_set_val(true);
|
|
|
|
platform_srst_set_val(false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-08 08:22:33 +00:00
|
|
|
#ifdef PLATFORM_HAS_POWER_SWITCH
|
2014-04-11 17:35:55 +00:00
|
|
|
static bool cmd_target_power(target *t, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
(void)t;
|
|
|
|
if (argc == 1)
|
|
|
|
gdb_outf("Target Power: %s\n",
|
2015-03-01 05:23:24 +00:00
|
|
|
platform_target_get_power() ? "enabled" : "disabled");
|
2014-04-11 17:35:55 +00:00
|
|
|
else
|
|
|
|
platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1])));
|
|
|
|
return true;
|
|
|
|
}
|
2014-08-08 08:22:33 +00:00
|
|
|
#endif
|
2013-05-04 20:46:47 +00:00
|
|
|
|
2012-05-26 03:05:37 +00:00
|
|
|
#ifdef PLATFORM_HAS_TRACESWO
|
2017-10-26 13:11:55 +00:00
|
|
|
static bool cmd_traceswo(target *t, int argc, const char **argv)
|
2012-04-17 09:40:39 +00:00
|
|
|
{
|
2017-10-26 13:11:55 +00:00
|
|
|
#if defined(STM32L0) || defined(STM32F3) || defined(STM32F4)
|
|
|
|
extern char serial_no[13];
|
|
|
|
#else
|
2012-04-22 00:22:08 +00:00
|
|
|
extern char serial_no[9];
|
2017-10-26 13:11:55 +00:00
|
|
|
#endif
|
|
|
|
uint32_t baudrate = 0;
|
|
|
|
(void)t;
|
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
baudrate = atoi(argv[1]);
|
|
|
|
|
|
|
|
traceswo_init(baudrate);
|
2012-04-22 00:22:08 +00:00
|
|
|
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
|
2012-06-24 09:37:10 +00:00
|
|
|
return true;
|
2012-04-17 09:40:39 +00:00
|
|
|
}
|
2012-05-26 03:05:37 +00:00
|
|
|
#endif
|
2011-02-04 07:23:52 +00:00
|
|
|
|
2016-06-18 08:26:56 +00:00
|
|
|
#ifdef PLATFORM_HAS_DEBUG
|
|
|
|
static bool cmd_debug_bmp(target *t, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
(void)t;
|
|
|
|
if (argc > 1) {
|
|
|
|
debug_bmp = !strcmp(argv[1], "enable");
|
|
|
|
}
|
|
|
|
gdb_outf("Debug mode is %s\n",
|
|
|
|
debug_bmp ? "enabled" : "disabled");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|