Skip to content

Commit

Permalink
feature: memwatch: float support
Browse files Browse the repository at this point in the history
  • Loading branch information
koendv committed Nov 9, 2023
1 parent 327c867 commit 84a8c6a
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 10 deletions.
5 changes: 3 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ifeq ($(ENABLE_DEBUG), 1)
CFLAGS += -DENABLE_DEBUG
endif


SRC = \
adiv5.c \
adiv5_jtag.c \
Expand Down Expand Up @@ -132,8 +133,8 @@ CFLAGS += -DPC_HOSTED=0
include platforms/common/Makefile.inc
endif

ifeq ($(ENABLE_MEMWATCH), 1)
CFLAGS += -DENABLE_MEMWATCH
ifdef ENABLE_MEMWATCH
CFLAGS += -DENABLE_MEMWATCH=$(ENABLE_MEMWATCH)
SRC += memwatch.c
endif

Expand Down
1 change: 1 addition & 0 deletions src/include/memwatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
typedef enum memwatch_format {
MEMWATCH_FMT_SIGNED,
MEMWATCH_FMT_UNSIGNED,
MEMWATCH_FMT_FLOAT,
MEMWATCH_FMT_HEX
} memwatch_format_e;

Expand Down
104 changes: 97 additions & 7 deletions src/memwatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,127 @@ static uint32_t rtt_write(const char *buf, uint32_t len)
}
#endif

#if PC_HOSTED == 0
/* printing floats */
#if (ENABLE_MEMWATCH == 3)
/* do not print float. smallest footprint. uses 1k flash */
static void ftoa(char *buf, float f, uint32_t bufsiz)
{
(void)f;
strncpy(buf, "?", bufsiz);
return;
}

#else
#if (ENABLE_MEMWATCH == 2) || ((ENABLE_MEMWATCH == 1) && (defined(STM32F4) || defined(STM32F7)))
/* use newlib to print float. uses 20k flash */

#ifdef gcvtf
#undef gcvtf
#endif

extern char *gcvtf(float, int, char *);

static void ftoa(char *buf, float f, uint32_t bufsiz)
{
(void)bufsiz;
gcvtf(f, 6, buf);
return;
}
#else
/* small but limited. uses 2k flash */
static void ftoa(char *buf, float f, uint32_t bufsiz)
{
char *s = NULL;

union val32_u {
uint32_t i;
volatile float f;
} fval;

if (f < 0) {
f = -f;
if (bufsiz) {
*buf++ = '-';
--bufsiz;
}
}

fval.f = f;

/* fpclassifyf */
uint32_t w = fval.i & 0x7fffffffU;
if (w == 0)
s = "0";
else if (w >= 0x7f800000U)
s = w > 0x7f800000U ? "nan" : "inf";
else if (f > 2144967168U)
s = "ovf";

if (s) {
strncpy(buf, s, bufsiz);
return;
}

/* print */
uint32_t int_part = f;
f = (f - int_part) * 10000.0F;
uint32_t frac_part = f;
if (frac_part == 0)
snprintf(buf, bufsiz, "%" PRId32, int_part);
else
snprintf(buf, bufsiz, "%" PRId32 ".%04" PRId32, int_part, frac_part);
return;
}
#endif
#endif
#endif

void poll_memwatch(target_s *cur_target)
{
uint32_t val;
union val32_u {
uint32_t i;
volatile float f;
} val;

char buf[64];
char timestamp[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)) {
if (!target_mem_read(cur_target, &val.i, memwatch_table[i].addr, sizeof(val.i)) &&
(val.i != memwatch_table[i].value)) {
if (memwatch_timestamp)
snprintf(timestamp, sizeof(timestamp), "%" PRIu32 " ", platform_time_ms());
else
timestamp[0] = '\0';
switch (memwatch_table[i].format) {
case MEMWATCH_FMT_SIGNED:
len = snprintf(buf, sizeof(buf), "%s%s %" PRId32 "\r\n", timestamp, memwatch_table[i].name, val);
len = snprintf(buf, sizeof(buf), "%s%s %" PRId32 "\r\n", timestamp, memwatch_table[i].name, val.i);
break;
case MEMWATCH_FMT_UNSIGNED:
len = snprintf(buf, sizeof(buf), "%s%s %" PRIu32 "\r\n", timestamp, memwatch_table[i].name, val);
len = snprintf(buf, sizeof(buf), "%s%s %" PRIu32 "\r\n", timestamp, memwatch_table[i].name, val.i);
break;
case MEMWATCH_FMT_FLOAT:
#if PC_HOSTED == 1
len = snprintf(buf, sizeof(buf), "%s%s %g\r\n", timestamp, memwatch_table[i].name, val.f);
#else
char fbuf[32];
ftoa(fbuf, val.f, sizeof(fbuf));
fbuf[sizeof(fbuf) - 1] = '\0';
len = snprintf(buf, sizeof(buf), "%s%s %s\r\n", timestamp, memwatch_table[i].name, fbuf);
#endif
break;
case MEMWATCH_FMT_HEX:
default:
len = snprintf(buf, sizeof(buf), "%s%s 0x%" PRIx32 "\r\n", timestamp, memwatch_table[i].name, val);
len = snprintf(buf, sizeof(buf), "%s%s 0x%" PRIx32 "\r\n", timestamp, memwatch_table[i].name, val.i);
break;
}
buf[sizeof(buf) - 1] = '\0';
rtt_write(buf, len);
memwatch_table[i].value = val;
memwatch_table[i].value = val.i;
}
}
return;
Expand Down
5 changes: 4 additions & 1 deletion src/target/cortexm.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ static bool cortexm_redirect_stdout(target_s *target, int argc, const char **arg
const command_s cortexm_cmd_list[] = {
{"vector_catch", cortexm_vector_catch, "Catch exception vectors"},
#ifdef ENABLE_MEMWATCH
{"memwatch", cortexm_memwatch, "Read memory while target running: [/t] [[NAME] [/d|/u|/x] ADDRESS]..."},
{"memwatch", cortexm_memwatch, "Read memory while target running: [/t] [[NAME] [/d|/u|/f|/x] ADDRESS]..."},
#endif
#if PC_HOSTED == 0
{"redirect_stdout", cortexm_redirect_stdout, "Redirect semihosting stdout to USB UART"},
Expand Down Expand Up @@ -1418,6 +1418,9 @@ static bool cortexm_memwatch(target_s *target, int argc, const char **argv)
case 'u':
fmt = MEMWATCH_FMT_UNSIGNED;
break;
case 'f':
fmt = MEMWATCH_FMT_FLOAT;
break;
case 'x':
fmt = MEMWATCH_FMT_HEX;
break;
Expand Down

0 comments on commit 84a8c6a

Please sign in to comment.