Skip to content
This repository was archived by the owner on Oct 18, 2025. It is now read-only.

Commit 3cd8fdf

Browse files
author
Thiadmer Riemersma
committed
BMDebug: bug fix in initialization of CTF stream/severity settings from the variables in the target device; more robust parsing of "serial" command (when CTF options are involved).
decodectf: fix CTF decoding when trace messages are filtered out on the host. Nuklear: bug fix in row colouring. tracegen: bug fix in parsing command line option for stream filtering (with named streams). Signed-off-by: Thiadmer Riemersma <thiadmer@compuphase.com>
1 parent 5f583f5 commit 3cd8fdf

File tree

11 files changed

+739
-672
lines changed

11 files changed

+739
-672
lines changed

‎source/bmdebug.c‎

Lines changed: 114 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ typedef struct tagCTFSETTINGS {
164164
unsigned long streammask; /**< mask with enabled streams */
165165
unsigned long severity_addr;
166166
unsigned long streammask_addr;
167-
bool initvars; /**< variables must be (re-)initialized from the target */
167+
int initvars; /**< 1=filter variables must be initialized from the target; 2=target must be initialized from the debugger */
168168
} CTFSETTINGS;
169169

170170
typedef struct tagSWOSETTINGS {
@@ -896,8 +896,8 @@ static bool console_autocomplete(char *text, size_t textsize, const DWARF_SYMBOL
896896
{ "frame", "f", NULL },
897897
{ "help", NULL, "assembly break breakpoints data files find keyboard monitor "
898898
"running serial stack status support svd trace user-defined" },
899-
{ "info", NULL, "args breakpoints frame functions locals scope set sources "
900-
"stack svd variables vtbl %var" },
899+
{ "info", NULL, "args breakpoints frame functions locals scope set serial "
900+
"sources stack svd trace variables vtbl %var" },
901901
{ "list", NULL, "%func %var %source" },
902902
{ "load", NULL, NULL },
903903
{ "monitor", "mon", "auto_scan connect_srst frequency halt_timeout hard_srst "
@@ -4427,13 +4427,22 @@ static bool handle_help_cmd(char *command, STRINGLIST *textroot, int *active,
44274427
stringlist_append(textroot, "Configure the serial monitor.", 0);
44284428
stringlist_append(textroot, "", 0);
44294429
stringlist_append(textroot, "serial [port] [bitrate] -- open the port at the bitrate. If no port is specified,"
4430-
" the secondary UART of the Black Magic Probe is used.", 0);
4430+
" the secondary UART of the Black Magic Probe is used.", 0);
44314431
stringlist_append(textroot, "serial enable -- open the serial monitor with the previously confugured settings.", 0);
44324432
stringlist_append(textroot, "serial disable -- close the virtual monitor.", 0);
44334433
stringlist_append(textroot, "serial info -- show current status and configuration.", 0);
44344434
stringlist_append(textroot, "", 0);
44354435
stringlist_append(textroot, "serial [filename] -- configure CTF decoding using the given TSDL file.", 0);
44364436
stringlist_append(textroot, "serial plain -- disable CTF decoding, display received data as text.", 0);
4437+
stringlist_append(textroot, "serial severity [level] -- set level for filtering on severity; level may be 'debug',"
4438+
" 'info', 'notice', 'warning', 'error' or 'critical'. This is only relevant for CTF"
4439+
" decoding.", 0);
4440+
stringlist_append(textroot, "serial stream [name] enable -- enable a CTF stream for tracing. If the name is '*',"
4441+
" all streams are enabled.", 0);
4442+
stringlist_append(textroot, "serial stream [name] disable -- disable a CTF stream for tracing. If the name is '*',"
4443+
" all streams are disabled.", 0);
4444+
stringlist_append(textroot, "serial stream [name] exclusive -- enable the specified CTF stream for tracing, while"
4445+
" disabling all other streams.", 0);
44374446
stringlist_append(textroot, "", 0);
44384447
stringlist_append(textroot, "serial clear -- clear the serial monitor view (delete contents).", 0);
44394448
stringlist_append(textroot, "serial save [filename] -- save the contents in the serial monitor to a file.", 0);
@@ -4462,6 +4471,9 @@ static bool handle_help_cmd(char *command, STRINGLIST *textroot, int *active,
44624471
stringlist_append(textroot, "", 0);
44634472
stringlist_append(textroot, "trace [filename] -- configure CTF decoding using the given TSDL file.", 0);
44644473
stringlist_append(textroot, "trace plain -- disable CTF decoding, trace plain input data.", 0);
4474+
stringlist_append(textroot, "trace severity [level] -- set level for filtering on severity; level may be 'debug',"
4475+
" 'info', 'notice', 'warning', 'error' or 'critical'. This is only relevant for CTF"
4476+
" decoding.", 0);
44654477
stringlist_append(textroot, "", 0);
44664478
stringlist_append(textroot, "trace channel [index] enable -- enable a channel (0..31).", 0);
44674479
stringlist_append(textroot, "trace channel [index] disable -- disable a channel (0..31).", 0);
@@ -5625,67 +5637,71 @@ static int handle_serial_cmd(const char *command, SERIALSETTINGS *serial, CTFSET
56255637

56265638
char *opt_clear;
56275639
if ((opt_clear = strstr(cmdcopy, "clear")) != NULL && IS_TOKEN(cmdcopy, opt_clear, 5)) {
5628-
tracestring_clear();
5640+
sermon_clear();
56295641
memset(opt_clear, ' ', 5); /* erase the "clear" parameter from the string */
56305642
}
56315643

56325644
char *opt_stream;
56335645
if ((opt_stream = strstr(cmdcopy, "stream")) != NULL && IS_TOKEN(cmdcopy, opt_stream, 6)) {
5646+
/* get the stream name & operation */
5647+
char *name = NULL;
5648+
char *oper = NULL;
5649+
const char *head = skipwhite(opt_stream + 6);
5650+
for (int param = 0; param < 2; param++) {
5651+
const char *tail = head;
5652+
while (*tail > ' ')
5653+
tail++;
5654+
if (tail != head) {
5655+
char *word = alloca((tail - head + 1) * sizeof(char));
5656+
strncpy(word, head, tail - head);
5657+
word[tail - head] = '\0';
5658+
if (strcmp(word, "enable") == 0 || strcmp(word, "disable") == 0 || strcmp(word, "exclusive") == 0)
5659+
oper = word;
5660+
else
5661+
name = word;
5662+
}
5663+
head = skipwhite(tail);
5664+
}
5665+
/* test fields, make mask for given stream */
56345666
bool ok = true;
5667+
if (name == NULL) {
5668+
console_add("Missing stream name\n", STRFLG_ERROR);
5669+
ok = false;
5670+
}
5671+
if (oper == NULL) {
5672+
console_add("Missing or invalid operation (enable / disable / exclusive)\n", STRFLG_ERROR);
5673+
ok = false;
5674+
}
56355675
unsigned long mask = ~0Lu;
5636-
/* get the name, and make the mask */
5637-
const char *ptr_name = skipwhite(opt_stream + 6);
5638-
const char *tail = ptr_name;
5639-
while (*tail > ' ')
5640-
tail++;
5641-
if (tail != ptr_name) {
5642-
char *name = alloca((tail - ptr_name + 1) * sizeof(char));
5643-
strncpy(name, ptr_name, tail - ptr_name);
5644-
name[tail - ptr_name] = '\0';
5645-
if (strcmp(name, "*") != 0) {
5646-
const CTF_STREAM *s = stream_by_name(name);
5647-
if (s != NULL) {
5648-
if (s->stream_id >= 0 && s->stream_id < NUM_CHANNELS) {
5649-
mask = 1Lu << s->stream_id;
5650-
} else {
5651-
console_add("Stream ID is out of range\n", STRFLG_ERROR);
5652-
ok = false;
5653-
}
5676+
if (ok && strcmp(name, "*") != 0) {
5677+
const CTF_STREAM *s = stream_by_name(name);
5678+
if (s != NULL) {
5679+
if (s->stream_id >= 0 && s->stream_id < NUM_CHANNELS) {
5680+
mask = 1Lu << s->stream_id;
56545681
} else {
5655-
console_add("Unknown stream name\n", STRFLG_ERROR);
5682+
console_add("Stream ID is out of range\n", STRFLG_ERROR);
56565683
ok = false;
56575684
}
5658-
}
5659-
} else {
5660-
console_add("Missing stream name\n", STRFLG_ERROR);
5661-
ok = false;
5662-
}
5663-
/* get the operation */
5664-
if (ok) {
5665-
const char *ptr_op = skipwhite(tail);
5666-
assert(ctf != NULL);
5667-
if (TOKEN_EQU(ptr_op, "enable", 6)) {
5668-
mask |= ctf->streammask;
5669-
tail = ptr_op + 6;
5670-
} else if (TOKEN_EQU(ptr_op, "disable", 7)) {
5671-
mask = ctf->streammask & ~mask;
5672-
tail = ptr_op + 7;
5673-
} else if (TOKEN_EQU(ptr_op, "exclusive", 9)) {
5674-
tail = ptr_op + 9;
56755685
} else {
5676-
console_add("Missing or invalid operation (enable / disable / exclusive)\n", STRFLG_ERROR);
5686+
console_add("Unknown stream name\n", STRFLG_ERROR);
56775687
ok = false;
56785688
}
56795689
}
5690+
/* set the mask, depending on the operation */
56805691
if (ok) {
56815692
assert(ctf != NULL);
5682-
ctf->streammask = mask;
5683-
if (ctf->streammask_addr != 0)
5684-
return ACTION_CTFSETTINGS; /* if the variable isn't found, we do not need to try to set it */
5693+
if (strcmp(oper, "enable") == 0)
5694+
ctf->streammask |= mask;
5695+
else if (strcmp(oper, "disable") == 0)
5696+
ctf->streammask &= ~mask;
56855697
else
5698+
ctf->streammask = mask;
5699+
if (ctf->streammask_addr == 0)
56865700
console_add("Note: no firmware support for \"stream\" filtering\n", STRFLG_STATUS);
5701+
if (default_action == ACTION_NOP)
5702+
default_action = ACTION_CTFSETTINGS;
56875703
}
5688-
memset(opt_stream, ' ', tail - opt_stream);
5704+
memset(opt_stream, ' ', head - opt_stream);
56895705
}
56905706

56915707
char *opt_severity;
@@ -5703,10 +5719,10 @@ static int handle_serial_cmd(const char *command, SERIALSETTINGS *serial, CTFSET
57035719
if (level >= 0) {
57045720
assert(ctf != NULL);
57055721
ctf->severity = level;
5706-
if (ctf->severity_addr != 0)
5707-
return ACTION_CTFSETTINGS; /* if the variable isn't found, we do not need to try to set it */
5708-
else
5722+
if (ctf->severity_addr == 0)
57095723
console_add("Note: no firmware support for \"severity\" level filtering\n", STRFLG_STATUS);
5724+
if (default_action == ACTION_NOP)
5725+
default_action = ACTION_CTFSETTINGS;
57105726
} else {
57115727
console_add("Invalid parameter for \"severity\" option\n", STRFLG_ERROR);
57125728
}
@@ -6136,8 +6152,8 @@ static bool load_targetoptions(const char *filename, APPSTATE *state)
61366152
ini_gets("CTF", "stream-mask", "ffffffff", mask, sizearray(mask), filename);
61376153
state->ctf.streammask = strtoul(mask, NULL, 16);
61386154
state->ctf.severity = (int)ini_getl("CTF", "severity-level", 1, filename);
6139-
if (strlen(state->ctf.metadata) > 0)
6140-
state->ctf.initvars = true;
6155+
if (strlen(state->ctf.metadata) > 0 && state->ctf.initvars == 0)
6156+
state->ctf.initvars = 1;
61416157

61426158
state->swo.mode = (unsigned)ini_getl("SWO trace", "mode", SWOMODE_NONE, filename);
61436159
state->swo.bitrate = (unsigned)ini_getl("SWO trace", "bitrate", 100000, filename);
@@ -6271,6 +6287,7 @@ static void button_bar(struct nk_context *ctx, APPSTATE *state, float panel_widt
62716287
"Reload and restart the program (Ctrl+F2)")) {
62726288
if (strlen(state->ELFfile) > 0 && access(state->ELFfile, 0) == 0)
62736289
save_targetoptions(state->ParamFile, state);
6290+
state->ctf.initvars = 2; /* do not initialize stream/severity variables, contrariwise: initialize the target */
62746291
RESETSTATE(state, STATE_FILE);
62756292
}
62766293
nk_layout_row_push(ctx, BUTTON_WIDTH);
@@ -7537,6 +7554,42 @@ static void handle_kbdinput_main(struct nk_context *ctx, APPSTATE *state)
75377554
}
75387555
}
75397556

7557+
static int getbytestream(unsigned char *target, const char *source, size_t sourcelength)
7558+
{
7559+
assert(target != NULL);
7560+
assert(source != NULL);
7561+
int count = 0;
7562+
while (sourcelength >= 2 && isxdigit(source[0]) && isxdigit(source[1])) {
7563+
char hex[3];
7564+
hex[0] = source[0];
7565+
hex[1] = source[1];
7566+
hex[2] = '\0';
7567+
*target = (unsigned char)strtoul(hex, NULL, 16);
7568+
source += 2;
7569+
target += 1;
7570+
sourcelength -= 2;
7571+
count += 1;
7572+
}
7573+
return count;
7574+
}
7575+
7576+
static int makebytestream(char *target, const unsigned char *source, size_t sourcelength)
7577+
{
7578+
assert(target != NULL);
7579+
assert(source != NULL);
7580+
int count = 0;
7581+
while (sourcelength > 0) {
7582+
unsigned char digit = (*source >> 4) & 0x0f;
7583+
*target++ = (digit < 10) ? (char)(digit + '0') : (char)(digit - 10 + 'A');
7584+
digit = *source & 0x0f;
7585+
*target++ = (digit < 10) ? (char)(digit + '0') : (char)(digit - 10 + 'A');
7586+
source += 1;
7587+
sourcelength -= 1;
7588+
count += 1;
7589+
}
7590+
return count;
7591+
}
7592+
75407593
static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states tab_states[TAB_COUNT])
75417594
{
75427595
assert(state != NULL);
@@ -8364,8 +8417,10 @@ static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states ta
83648417
if (state->swo.enabled && state->swo.mode != SWOMODE_NONE && !state->swo.init_status) {
83658418
state->monitor_cmd_active = true; /* to silence output of scripts */
83668419
RESETSTATE(state, STATE_SWOTRACE); /* initialize SWO tracing */
8367-
} else if (state->ctf.initvars) {
8420+
} else if (state->ctf.initvars == 1) {
83688421
RESETSTATE(state, STATE_CTF_GETSTREAMS);/* get trace filter variables from the target */
8422+
} else if (state->ctf.initvars == 2) {
8423+
RESETSTATE(state, STATE_CTF_SETSTREAMS);/* set the target's trace filter variables */
83698424
} else if (state->refreshflags & REFRESH_BREAKPOINTS) {
83708425
RESETSTATE(state, STATE_LIST_BREAKPOINTS);
83718426
} else if (state->refreshflags & REFRESH_LOCALS) {
@@ -8770,6 +8825,7 @@ static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states ta
87708825
break;
87718826
case STATE_CTF_SETSTREAMS:
87728827
case STATE_CTF_SETSEVERITY:
8828+
state->ctf.initvars = 0;
87738829
if (state->curstate == STATE_CTF_SETSTREAMS && state->ctf.streammask_addr == 0)
87748830
MOVESTATE(state, STATE_CTF_SETSEVERITY);
87758831
if (state->curstate == STATE_CTF_SETSEVERITY && state->ctf.severity_addr == 0)
@@ -8778,8 +8834,10 @@ static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states ta
87788834
break;
87798835
if (STATESWITCH(state)) {
87808836
if (state->curstate == STATE_CTF_SETSTREAMS) {
8781-
snprintf(state->cmdline, CMD_BUFSIZE, "-data-write-memory-bytes 0x%lX %08lX 4\n",
8782-
state->ctf.streammask_addr, state->ctf.streammask);
8837+
snprintf(state->cmdline, CMD_BUFSIZE, "-data-write-memory-bytes 0x%lX ", state->ctf.streammask_addr);
8838+
size_t len = strlen(state->cmdline);
8839+
makebytestream(state->cmdline + len, (const unsigned char*)&state->ctf.streammask, 4);
8840+
strcpy(state->cmdline + len + 8, " 4\n");
87838841
} else
87848842
snprintf(state->cmdline, CMD_BUFSIZE, "-data-write-memory-bytes 0x%lX %02X 1\n",
87858843
state->ctf.severity_addr, state->ctf.severity);
@@ -8800,7 +8858,7 @@ static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states ta
88008858
break;
88018859
case STATE_CTF_GETSTREAMS:
88028860
case STATE_CTF_GETSEVERITY:
8803-
state->ctf.initvars = false;
8861+
state->ctf.initvars = 0;
88048862
if (state->curstate == STATE_CTF_GETSTREAMS && state->ctf.streammask_addr == 0)
88058863
MOVESTATE(state, STATE_CTF_GETSEVERITY);
88068864
if (state->curstate == STATE_CTF_GETSEVERITY && state->ctf.severity_addr == 0)
@@ -8826,7 +8884,7 @@ static void handle_stateaction(APPSTATE *state, const enum nk_collapse_states ta
88268884
if (*data == '"')
88278885
data += 1;
88288886
if (state->curstate == STATE_CTF_GETSTREAMS)
8829-
state->ctf.streammask = strtoul(data, NULL, 16);
8887+
getbytestream((unsigned char*)&state->ctf.streammask, data, 8);
88308888
else
88318889
state->ctf.severity = (unsigned char)strtoul(data,NULL,16);
88328890
}

0 commit comments

Comments
 (0)