Skip to content

Commit

Permalink
memwatch - read memory while running
Browse files Browse the repository at this point in the history
  • Loading branch information
koendv committed Oct 20, 2023
1 parent 643106f commit 853b2e8
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ SRC = \
kinetis.c \
main.c \
maths_utils.c \
memwatch.c \
morse.c \
msp432e4.c \
msp432p4.c \
Expand Down
60 changes: 60 additions & 0 deletions src/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "serialno.h"
#include "jtagtap.h"
#include "jtag_scan.h"
#include "memwatch.h"

#ifdef ENABLE_RTT
#include "rtt.h"
Expand All @@ -52,6 +53,8 @@
#include <alloca.h>
#endif

#include <ctype.h>

static bool cmd_version(target_s *t, int argc, const char **argv);
static bool cmd_help(target_s *t, int argc, const char **argv);

Expand All @@ -72,6 +75,7 @@ static bool cmd_target_power(target_s *t, int argc, const char **argv);
static bool cmd_traceswo(target_s *t, int argc, const char **argv);
#endif
static bool cmd_heapinfo(target_s *t, int argc, const char **argv);
static bool cmd_memwatch(target_s *t, int argc, const char **argv);
#ifdef ENABLE_RTT
static bool cmd_rtt(target_s *t, int argc, const char **argv);
#endif
Expand Down Expand Up @@ -112,6 +116,7 @@ const command_s cmd_list[] = {
{"traceswo", cmd_traceswo, "Start trace capture, Manchester mode: [decode [CHANNEL_NR ...]]"},
#endif
#endif
{"memwatch", cmd_memwatch, "Print memory changes: [[NAME] [/d|/u|/x] ADDRESS]..."},
{"heapinfo", cmd_heapinfo, "Set semihosting heapinfo: HEAPINFO HEAP_BASE HEAP_LIMIT STACK_BASE STACK_LIMIT"},
#if defined(PLATFORM_HAS_DEBUG) && PC_HOSTED == 0
{"debug_bmp", cmd_debug_bmp, "Output BMP \"debug\" strings to the second vcom: [enable|disable]"},
Expand Down Expand Up @@ -670,6 +675,61 @@ static bool cmd_shutdown_bmda(target_s *t, int argc, const char **argv)
}
#endif

static bool cmd_memwatch(target_s *t, int argc, const char **argv)
{
memwatch_format_e fmt = MEMWATCH_FMT_HEX;
char name[MEMWATCH_STRLEN] = {0};
(void)t;
memset(memwatch_table, 0, sizeof(memwatch_table));
memwatch_cnt = 0;
for (int32_t i = 1; i < argc; i++) {
if (argv[i][0] == '/') {
/* format follows */
switch (argv[i][1]) {
case 'd':
fmt = MEMWATCH_FMT_SIGNED;
break;
case 'u':
fmt = MEMWATCH_FMT_UNSIGNED;
break;
case 'x':
fmt = MEMWATCH_FMT_HEX;
break;
default:
break;
}
} else if (isalpha(argv[i][0])) {
/* name follows */
strncpy(name, argv[i], sizeof(name));
name[sizeof(name) - 1] = '\0';
} else if (isdigit(argv[i][0])) {
/* address follows */
uint32_t addr = strtoul(argv[i], NULL, 0);
if (name[0] == '\0') {
/* no name given, use address as name */
snprintf(name, MEMWATCH_STRLEN, "0x%08" PRIx32, addr);
name[MEMWATCH_STRLEN - 1] = '\0';
}

/* add new name, format and address to memwatch table */
memwatch_table[memwatch_cnt].addr = addr;
memwatch_table[memwatch_cnt].value = 0xdeadbeef;
memwatch_table[memwatch_cnt].format = fmt;
memcpy(memwatch_table[memwatch_cnt].name, name, MEMWATCH_STRLEN);
memwatch_cnt++;
memset(name, 0, sizeof(name));
gdb_outf("0x%x ", addr);
if (memwatch_cnt == MEMWATCH_NUM)
break;
} else {
gdb_outf("?");
break;
}
}
gdb_outf("\n");
return true;
}

static bool cmd_heapinfo(target_s *t, int argc, const char **argv)
{
if (t == NULL)
Expand Down
29 changes: 29 additions & 0 deletions src/include/memwatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef MEMWATCH_H
#define MEMWATCH_H

#include <stdint.h>
#include <stdbool.h>
#include <target.h>

#define MEMWATCH_NUM 8
/* string length has to be long enough to store an address 0x20000000 */
#define MEMWATCH_STRLEN 12

typedef enum memwatch_format {
MEMWATCH_FMT_SIGNED,
MEMWATCH_FMT_UNSIGNED,
MEMWATCH_FMT_HEX
} memwatch_format_e;

typedef struct {
uint32_t addr;
uint32_t value;
char name[MEMWATCH_STRLEN];
memwatch_format_e format;
} memwatch_s;

extern memwatch_s memwatch_table[MEMWATCH_NUM];
extern uint32_t memwatch_cnt;
extern void poll_memwatch(target_s *cur_target);

#endif
3 changes: 3 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "gdb_packet.h"
#include "morse.h"
#include "command.h"
#include "memwatch.h"
#ifdef ENABLE_RTT
#include "rtt.h"
#endif
Expand Down Expand Up @@ -59,6 +60,8 @@ static void bmp_poll_loop(void)
if (rtt_enabled)
poll_rtt(cur_target);
#endif
if (memwatch_cnt != 0)
poll_memwatch(cur_target);
}

SET_IDLE_STATE(true);
Expand Down
46 changes: 46 additions & 0 deletions src/memwatch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "general.h"
#include "gdb_packet.h"
#include "memwatch.h"
#if PC_HOSTED == 1
#include <unistd.h>
#else
#include "usb_serial.h"
#endif

memwatch_s memwatch_table[MEMWATCH_NUM];
uint32_t memwatch_cnt = 0;

void poll_memwatch(target_s *cur_target)
{
uint32_t val;
char buf[64];
uint32_t len;
if (!cur_target || (memwatch_cnt == 0))
return;

for (uint32_t i = 0; i < memwatch_cnt; i++) {
if (!target_mem_read(cur_target, &val, memwatch_table[i].addr, sizeof(val)) &&
(val != memwatch_table[i].value)) {
switch (memwatch_table[i].format) {
case MEMWATCH_FMT_SIGNED:
len = snprintf(buf, sizeof(buf), "%s: %" PRId32 "\r\n", memwatch_table[i].name, val);
break;
case MEMWATCH_FMT_UNSIGNED:
len = snprintf(buf, sizeof(buf), "%s: %" PRIu32 "\r\n", memwatch_table[i].name, val);
break;
case MEMWATCH_FMT_HEX:
default:
len = snprintf(buf, sizeof(buf), "%s: 0x%" PRIx32 "\r\n", memwatch_table[i].name, val);
break;
}
#if PC_HOSTED == 1
int l = write(1, buf, len);
(void)l;
#else
debug_serial_fifo_send(buf, 0, len);
#endif
memwatch_table[i].value = val;
}
}
return;
}

0 comments on commit 853b2e8

Please sign in to comment.