diff --git a/src/Makefile b/src/Makefile index 64615b5b620..8d174adcc73 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,7 @@ ifeq ($(ENABLE_DEBUG), 1) CFLAGS += -DENABLE_DEBUG endif + SRC = \ adiv5.c \ adiv5_jtag.c \ @@ -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 diff --git a/src/include/memwatch.h b/src/include/memwatch.h index 7bfc1d304f8..ad04107e1ce 100644 --- a/src/include/memwatch.h +++ b/src/include/memwatch.h @@ -12,6 +12,7 @@ typedef enum memwatch_format { MEMWATCH_FMT_SIGNED, MEMWATCH_FMT_UNSIGNED, + MEMWATCH_FMT_FLOAT, MEMWATCH_FMT_HEX } memwatch_format_e; diff --git a/src/memwatch.c b/src/memwatch.c index 7dbb902a9ef..e1f2873c658 100644 --- a/src/memwatch.c +++ b/src/memwatch.c @@ -30,9 +30,89 @@ 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; @@ -40,27 +120,37 @@ void poll_memwatch(target_s *cur_target) 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; diff --git a/src/target/cortexm.c b/src/target/cortexm.c index c484f4a41dc..fa7611720f1 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -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"}, @@ -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;