diff --git a/src/command.c b/src/command.c index bd6701d7..646c9f30 100644 --- a/src/command.c +++ b/src/command.c @@ -60,6 +60,7 @@ static bool cmd_target_power(target *t, int argc, const char **argv); #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(target *t, int argc, const char **argv); #endif +static bool cmd_heapinfo(target *t, int argc, const char **argv); #if defined(PLATFORM_HAS_DEBUG) && !defined(PC_HOSTED) static bool cmd_debug_bmp(target *t, int argc, const char **argv); #endif @@ -94,6 +95,7 @@ const struct command_s cmd_list[] = { {"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, Manchester mode" }, #endif #endif + {"heapinfo", (cmd_handler)cmd_heapinfo, "Set semihosting heapinfo" }, #if defined(PLATFORM_HAS_DEBUG) && !defined(PC_HOSTED) {"debug_bmp", (cmd_handler)cmd_debug_bmp, "Output BMP \"debug\" strings to the second vcom: (enable|disable)"}, #endif @@ -479,3 +481,18 @@ bool cmd_serial(target *t, int argc, char **argv) return true; } #endif + +static bool cmd_heapinfo(target *t, int argc, const char **argv) +{ + if (t == NULL) gdb_out("not attached\n"); + else if (argc == 5) { + target_addr heap_base = strtoul(argv[1], NULL, 16); + target_addr heap_limit = strtoul(argv[2], NULL, 16); + target_addr stack_base = strtoul(argv[3], NULL, 16); + target_addr stack_limit = strtoul(argv[4], NULL, 16); + gdb_outf("heapinfo heap_base: %p heap_limit: %p stack_base: %p stack_limit: %p\n", + heap_base, heap_limit, stack_base, stack_limit); + target_set_heapinfo(t, heap_base, heap_limit, stack_base, stack_limit); + } else gdb_outf("heapinfo heap_base heap_limit stack_base stack_limit\n"); + return true; +} diff --git a/src/include/target.h b/src/include/target.h index 35102505..cc6131ef 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -81,6 +81,8 @@ void target_halt_request(target *t); enum target_halt_reason target_halt_poll(target *t, target_addr *watch); void target_halt_resume(target *t, bool step); void target_set_cmdline(target *t, char *cmdline); +void target_set_heapinfo(target *t, target_addr heap_base, target_addr heap_limit, + target_addr stack_base, target_addr stack_limit); /* Break-/watchpoint functions */ enum target_breakwatch { @@ -97,11 +99,12 @@ int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size void target_command_help(target *t); int target_command(target *t, int argc, const char *argv[]); - +/* keep target_errno in sync with errno values in gdb/include/gdb/fileio.h */ enum target_errno { TARGET_EPERM = 1, TARGET_ENOENT = 2, TARGET_EINTR = 4, + TARGET_EIO = 5, TARGET_EBADF = 9, TARGET_EACCES = 13, TARGET_EFAULT = 14, @@ -111,13 +114,15 @@ enum target_errno { TARGET_ENOTDIR = 20, TARGET_EISDIR = 21, TARGET_EINVAL = 22, - TARGET_EMFILE = 24, TARGET_ENFILE = 23, + TARGET_EMFILE = 24, TARGET_EFBIG = 27, TARGET_ENOSPC = 28, TARGET_ESPIPE = 29, TARGET_EROFS = 30, - TARGET_ENAMETOOLONG = 36, + TARGET_ENOSYS = 88, + TARGET_ENAMETOOLONG = 91, + TARGET_EUNKNOWN = 9999, }; enum target_open_flags { diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 971ebc28..cb41f9ab 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -153,11 +153,37 @@ static inline int platform_hwversion(void) return 0; } -/* Use newlib provided integer only stdio functions */ -#define sscanf siscanf -#define sprintf siprintf -#define vasprintf vasiprintf -#define snprintf sniprintf +/* + * Use newlib provided integer only stdio functions + */ +/* sscanf */ +#ifdef sscanf +#undef sscanf +#define sscanf siscanf +#else +#define sscanf siscanf +#endif +/* sprintf */ +#ifdef sprintf +#undef sprintf +#define sprintf siprintf +#else +#define sprintf siprintf +#endif +/* vasprintf */ +#ifdef vasprintf +#undef vasprintf +#define vasprintf vasiprintf +#else +#define vasprintf vasiprintf +#endif +/* snprintf */ +#ifdef snprintf +#undef snprintf +#define snprintf sniprintf +#else +#define snprintf sniprintf #endif +#endif diff --git a/src/platforms/hydrabus/platform.h b/src/platforms/hydrabus/platform.h index d0ba61aa..792cfba8 100644 --- a/src/platforms/hydrabus/platform.h +++ b/src/platforms/hydrabus/platform.h @@ -153,11 +153,38 @@ static inline int platform_hwversion(void) return 0; } -/* Use newlib provided integer only stdio functions */ +/* + * Use newlib provided integer only stdio functions + */ + +/* sscanf */ +#ifdef sscanf +#undef sscanf #define sscanf siscanf +#else +#define sscanf siscanf +#endif +/* sprintf */ +#ifdef sprintf +#undef sprintf #define sprintf siprintf +#else +#define sprintf siprintf +#endif +/* vasprintf */ +#ifdef vasprintf +#undef vasprintf #define vasprintf vasiprintf +#else +#define vasprintf vasiprintf +#endif +/* snprintf */ +#ifdef snprintf +#undef snprintf #define snprintf sniprintf +#else +#define snprintf sniprintf +#endif #endif diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 59d69085..00043acd 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -178,10 +178,37 @@ int usbuart_debug_write(const char *buf, size_t len); #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} -/* Use newlib provided integer only stdio functions */ +/* + * Use newlib provided integer only stdio functions + */ + +/* sscanf */ +#ifdef sscanf +#undef sscanf #define sscanf siscanf +#else +#define sscanf siscanf +#endif +/* sprintf */ +#ifdef sprintf +#undef sprintf #define sprintf siprintf -#define snprintf sniprintf +#else +#define sprintf siprintf +#endif +/* vasprintf */ +#ifdef vasprintf +#undef vasprintf #define vasprintf vasiprintf +#else +#define vasprintf vasiprintf +#endif +/* snprintf */ +#ifdef snprintf +#undef snprintf +#define snprintf sniprintf +#else +#define snprintf sniprintf +#endif #endif diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 0ac91bb3..1b572231 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -148,11 +148,39 @@ extern uint16_t led_idle_run; extern uint32_t detect_rev(void); -/* Use newlib provided integer only stdio functions */ +/* + * Use newlib provided integer only stdio functions + */ + +/* sscanf */ +#ifdef sscanf +#undef sscanf #define sscanf siscanf +#else +#define sscanf siscanf +#endif +/* sprintf */ +#ifdef sprintf +#undef sprintf #define sprintf siprintf +#else +#define sprintf siprintf +#endif +/* vasprintf */ +#ifdef vasprintf +#undef vasprintf #define vasprintf vasiprintf +#else +#define vasprintf vasiprintf +#endif +/* snprintf */ +#ifdef snprintf +#undef snprintf #define snprintf sniprintf +#else +#define snprintf sniprintf +#endif + #endif diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 78bc4498..74f1d434 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -154,11 +154,38 @@ extern void set_idle_state(int state); extern uint8_t detect_rev(void); -/* Use newlib provided integer only stdio functions */ +/* + * Use newlib provided integer only stdio functions + */ + +/* sscanf */ +#ifdef sscanf +#undef sscanf #define sscanf siscanf +#else +#define sscanf siscanf +#endif +/* sprintf */ +#ifdef sprintf +#undef sprintf #define sprintf siprintf +#else +#define sprintf siprintf +#endif +/* vasprintf */ +#ifdef vasprintf +#undef vasprintf #define vasprintf vasiprintf +#else +#define vasprintf vasiprintf +#endif +/* snprintf */ +#ifdef snprintf +#undef snprintf #define snprintf sniprintf +#else +#define snprintf sniprintf +#endif #endif diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 70e38d06..c95b52ab 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -1110,12 +1110,12 @@ static int cortexm_hostio_request(target *t) break; case SYS_READ: /* read */ ret = tc_read(t, params[0] - 1, params[1], params[2]); - if (ret > 0) + if (ret >= 0) ret = params[2] - ret; break; case SYS_WRITE: /* write */ ret = tc_write(t, params[0] - 1, params[1], params[2]); - if (ret > 0) + if (ret >= 0) ret = params[2] - ret; break; case SYS_WRITEC: /* writec */ @@ -1141,17 +1141,19 @@ static int cortexm_hostio_request(target *t) ret = tc_isatty(t, params[0] - 1); break; case SYS_SEEK: /* lseek */ - ret = tc_lseek(t, params[0] - 1, params[1], TARGET_SEEK_SET); + if (tc_lseek(t, params[0] - 1, params[1], TARGET_SEEK_SET) == (long)params[1]) ret = 0; + else ret = -1; break; case SYS_RENAME:/* rename */ - ret = tc_rename(t, params[0] - 1, params[1] + 1, + ret = tc_rename(t, params[0], params[1] + 1, params[2], params[3] + 1); break; case SYS_REMOVE:/* unlink */ - ret = tc_unlink(t, params[0] - 1, params[1] + 1); + ret = tc_unlink(t, params[0], params[1] + 1); break; case SYS_SYSTEM:/* system */ - ret = tc_system(t, params[0] - 1, params[1] + 1); + /* before use first enable system calls with the following gdb command: 'set remote system-call-allowed 1' */ + ret = tc_system(t, params[0], params[1] + 1); break; case SYS_FLEN: @@ -1180,27 +1182,39 @@ static int cortexm_hostio_request(target *t) break; } - case SYS_TIME: { /* gettimeofday */ + case SYS_CLOCK: /* clock */ + case SYS_TIME: { /* time */ + /* use same code for SYS_CLOCK and SYS_TIME, more compact */ ret = -1; - uint32_t fio_timeval[3]; /* same size as fio_timeval in gdb/include/gdb/fileio.h */ - //DEBUG("SYS_TIME fio_timeval addr %p\n", fio_timeval); + struct __attribute__((packed, aligned(4))) { + uint32_t ftv_sec; + uint64_t ftv_usec; + } fio_timeval; + //DEBUG("SYS_TIME fio_timeval addr %p\n", &fio_timeval); void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len); void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len); saved_mem_read = t->mem_read; saved_mem_write = t->mem_write; t->mem_read = probe_mem_read; t->mem_write = probe_mem_write; - int rc = tc_gettimeofday(t, (target_addr) fio_timeval, (target_addr) NULL); /* write gettimeofday() result in fio_timeval[] */ + int rc = tc_gettimeofday(t, (target_addr) &fio_timeval, (target_addr) NULL); /* write gettimeofday() result in fio_timeval[] */ t->mem_read = saved_mem_read; t->mem_write = saved_mem_write; if (rc) break; /* tc_gettimeofday() failed */ - uint32_t ftv_sec = fio_timeval[0]; /* time in seconds, first field in fio_timeval */ - ret = __builtin_bswap32(ftv_sec); /* convert from bigendian to target order */ + uint32_t sec = __builtin_bswap32(fio_timeval.ftv_sec); /* convert from bigendian to target order */ + uint64_t usec = __builtin_bswap64(fio_timeval.ftv_usec); + if (syscall == SYS_TIME) { /* SYS_TIME: time in seconds */ + ret = sec; + } else { /* SYS_CLOCK: time in hundredths of seconds */ + uint64_t csec64 = (sec * 1000000ull + usec)/10000ull; + uint32_t csec = csec64 & 0x7fffffff; + ret = csec; + } break; } case SYS_READC: { /* readc */ - uint8_t ch; + uint8_t ch='?'; //DEBUG("SYS_READC ch addr %p\n", &ch); void (*saved_mem_read)(target *t, void *dest, target_addr src, size_t len); void (*saved_mem_write)(target *t, target_addr dest, const void *src, size_t len); @@ -1208,7 +1222,7 @@ static int cortexm_hostio_request(target *t) saved_mem_write = t->mem_write; t->mem_read = probe_mem_read; t->mem_write = probe_mem_write; - int rc = tc_read(t, params[0] - 1, (target_addr) &ch, 1); /* read a character in ch */ + int rc = tc_read(t, STDIN_FILENO, (target_addr) &ch, 1); /* read a character in ch */ t->mem_read = saved_mem_read; t->mem_write = saved_mem_write; if (rc == 1) ret = ch; @@ -1223,7 +1237,11 @@ static int cortexm_hostio_request(target *t) case SYS_EXIT: /* _exit() */ tc_printf(t, "_exit(0x%x)\n", params[0]); target_halt_resume(t, 1); - ret = 0; + break; + + case SYS_EXIT_EXTENDED: /* _exit() */ + tc_printf(t, "_exit(0x%x%08x)\n", params[1], params[0]); /* exit() with 64bit exit value */ + target_halt_resume(t, 1); break; case SYS_GET_CMDLINE: { /* get_cmdline */ @@ -1240,13 +1258,59 @@ static int cortexm_hostio_request(target *t) break; } - // not implemented yet: + case SYS_ISERROR: { /* iserror */ + int errorNo = params[0]; + ret = (errorNo == TARGET_EPERM) || + (errorNo == TARGET_ENOENT) || + (errorNo == TARGET_EINTR) || + (errorNo == TARGET_EIO) || + (errorNo == TARGET_EBADF) || + (errorNo == TARGET_EACCES) || + (errorNo == TARGET_EFAULT) || + (errorNo == TARGET_EBUSY) || + (errorNo == TARGET_EEXIST) || + (errorNo == TARGET_ENODEV) || + (errorNo == TARGET_ENOTDIR) || + (errorNo == TARGET_EISDIR) || + (errorNo == TARGET_EINVAL) || + (errorNo == TARGET_ENFILE) || + (errorNo == TARGET_EMFILE) || + (errorNo == TARGET_EFBIG) || + (errorNo == TARGET_ENOSPC) || + (errorNo == TARGET_ESPIPE) || + (errorNo == TARGET_EROFS) || + (errorNo == TARGET_ENOSYS) || + (errorNo == TARGET_ENAMETOOLONG) || + (errorNo == TARGET_EUNKNOWN); + break; + } + case SYS_HEAPINFO: /* heapinfo */ - case SYS_CLOCK: /* clock */ + target_mem_write(t, arm_regs[1], &t->heapinfo, sizeof(t->heapinfo)); /* See newlib/libc/sys/arm/crt0.S */ + break; + + case SYS_TMPNAM: { /* tmpnam */ + /* Given a target identifier between 0 and 255, returns a temporary name. + * FIXME: add directory prefix */ + target_addr buf_ptr = params[0]; + int target_id = params[1]; + int buf_size = params[2]; + char fnam[]="tempXX.tmp"; + ret = -1; + if (buf_ptr == 0) break; + if (buf_size <= 0) break; + if ((target_id < 0) || (target_id > 255)) break; /* target id out of range */ + fnam[5]='A'+(target_id&0xF); /* create filename */ + fnam[4]='A'+(target_id>>4&0xF); + if (strlen(fnam)+1>(uint32_t)buf_size) break; /* target buffer too small */ + if(target_mem_write(t, buf_ptr, fnam, strlen(fnam)+1)) break; /* copy filename to target */ + ret = 0; + break; + } + + // not implemented yet: case SYS_ELAPSED: /* elapsed */ - case SYS_ISERROR: /* iserror */ case SYS_TICKFREQ: /* tickfreq */ - case SYS_TMPNAM: /* tmpnam */ ret = -1; break; diff --git a/src/target/efm32.c b/src/target/efm32.c index f1cfc0df..ba40b430 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -584,7 +584,7 @@ static efm32_device_t const * efm32_get_device(size_t index) /** * Probe */ -char variant_string[60]; +static char efm32_variant_string[60]; bool efm32_probe(target *t) { uint8_t di_version = 1; @@ -636,13 +636,13 @@ bool efm32_probe(target *t) uint32_t ram_size = ram_kib * 0x400; uint32_t flash_page_size = device->flash_page_size; - snprintf(variant_string, sizeof(variant_string), "%c\b%c\b%s %d F%d %s", + snprintf(efm32_variant_string, sizeof(efm32_variant_string), "%c\b%c\b%s %d F%d %s", di_version + 48, (uint8_t)device_index + 32, device->name, part_number, flash_kib, device->description); /* Setup Target */ t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; - t->driver = variant_string; + t->driver = efm32_variant_string; tc_printf(t, "flash size %d page size %d\n", flash_size, flash_page_size); target_add_ram (t, SRAM_BASE, ram_size); efm32_add_flash(t, 0x00000000, flash_size, flash_page_size); diff --git a/src/target/samd.c b/src/target/samd.c index 18da3bc4..e66a85f8 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -380,6 +380,7 @@ struct samd_descr samd_parse_device_id(uint32_t did) } break; case 3: samd.series = 11; break; + default: samd.series = 0; break; } /* Revision */ samd.revision = 'A' + revision; @@ -440,7 +441,7 @@ static void samd_add_flash(target *t, uint32_t addr, size_t length) target_add_flash(t, f); } -char variant_string[60]; +static char samd_variant_string[60]; bool samd_probe(target *t) { ADIv5_AP_t *ap = cortexm_ap(t); @@ -467,14 +468,14 @@ bool samd_probe(target *t) /* Part String */ if (protected) { - sprintf(variant_string, + sprintf(samd_variant_string, "Atmel SAM%c%d%c%d%c%s (rev %c) (PROT=1)", samd.family, samd.series, samd.pin, samd.mem, samd.variant, samd.package, samd.revision); } else { - sprintf(variant_string, + sprintf(samd_variant_string, "Atmel SAM%c%d%c%d%c%s (rev %c)", samd.family, samd.series, samd.pin, samd.mem, @@ -483,7 +484,7 @@ bool samd_probe(target *t) } /* Setup Target */ - t->driver = variant_string; + t->driver = samd_variant_string; t->reset = samd_reset; if (samd.series == 20 && samd.revision == 'B') { diff --git a/src/target/samx5x.c b/src/target/samx5x.c index f8067bc3..b7152f3a 100644 --- a/src/target/samx5x.c +++ b/src/target/samx5x.c @@ -344,7 +344,7 @@ static void samx5x_add_flash(target *t, uint32_t addr, size_t length, target_add_flash(t, f); } -char variant_string[60]; +static char samx5x_variant_string[60]; bool samx5x_probe(target *t) { ADIv5_AP_t *ap = cortexm_ap(t); @@ -371,19 +371,19 @@ bool samx5x_probe(target *t) /* Part String */ if (protected) { - snprintf(variant_string, sizeof(variant_string), + snprintf(samx5x_variant_string, sizeof(samx5x_variant_string), "Microchip SAM%c%d%c%dA (rev %c) (PROT=1)", samx5x.series_letter, samx5x.series_number, samx5x.pin, samx5x.mem, samx5x.revision); } else { - snprintf(variant_string, sizeof(variant_string), + snprintf(samx5x_variant_string, sizeof(samx5x_variant_string), "Microchip SAM%c%d%c%dA (rev %c)", samx5x.series_letter, samx5x.series_number, samx5x.pin, samx5x.mem, samx5x.revision); } /* Setup Target */ - t->driver = variant_string; + t->driver = samx5x_variant_string; t->reset = samx5x_reset; if (protected) { diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index ff432682..08d38eb3 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -83,9 +83,14 @@ static int stm32f4_flash_write(struct target_flash *f, #define FLASH_OPTCR_OPTLOCK (1 << 0) #define FLASH_OPTCR_OPTSTRT (1 << 1) +#define FLASH_OPTCR_WDG_SW (1 << 5) #define FLASH_OPTCR_nDBANK (1 << 29) #define FLASH_OPTCR_DB1M (1 << 30) +#define FLASH_OPTCR_PROT_MASK 0xff00 +#define FLASH_OPTCR_PROT_L0 0xaa00 +#define FLASH_OPTCR_PROT_L1 0xbb00 + #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -561,6 +566,19 @@ static bool optcr_mask(target *t, uint32_t *val) static bool stm32f4_option_write(target *t, uint32_t *val, int count) { + val[0] &= ~(FLASH_OPTCR_OPTSTRT | FLASH_OPTCR_OPTLOCK); + uint32_t optcr = target_mem_read32(t, FLASH_OPTCR); + /* Check if watchdog and read protection is active. + * When both are active, watchdog will trigger when erasing + * to get back to level 0 protection and operation aborts! + */ + if (!(optcr & FLASH_OPTCR_WDG_SW) && + ((optcr & FLASH_OPTCR_PROT_MASK) != FLASH_OPTCR_PROT_L0) && + ((val[0] & FLASH_OPTCR_PROT_MASK) != FLASH_OPTCR_PROT_L1)) { + val[0] &= ~FLASH_OPTCR_PROT_MASK; + val[0] |= FLASH_OPTCR_PROT_L1; + tc_printf(t, "Keeping L1 protection while HW Watchdog fuse is set!\n"); + } target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) @@ -578,11 +596,22 @@ static bool stm32f4_option_write(target *t, uint32_t *val, int count) target_mem_write32(t, FLASH_OPTCR, val[0]); target_mem_write32(t, FLASH_OPTCR, val[0] | FLASH_OPTCR_OPTSTRT); + const char spinner[] = "|/-\\"; + int spinindex = 0; + tc_printf(t, "Erasing flash... This may take a few seconds. "); /* Read FLASH_SR to poll for BSY bit */ - while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) - if(target_check_error(t)) + while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { + platform_delay(100); + tc_printf(t, "\b%c", spinner[spinindex++ % 4]); + if(target_check_error(t)) { + tc_printf(t, " failed\n"); return false; + } + } + tc_printf(t, "\n"); target_mem_write32(t, FLASH_OPTCR, FLASH_OPTCR_OPTLOCK); + /* Reset target to reload option bits.*/ + target_reset(t); return true; } @@ -619,7 +648,7 @@ static bool stm32f4_option_write_default(target *t) static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { - uint32_t start = 0x1FFFC000, val[3]; + uint32_t val[3]; int count = 0, readcount = 1; switch (t->idcode) { @@ -628,8 +657,6 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) /* fall through.*/ case ID_STM32F74X: case ID_STM32F76X: - /* F7 Devices have option bytes at 0x1FFF0000. */ - start = 0x1FFF0000; readcount++; break; case ID_STM32F42X: @@ -637,17 +664,17 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) readcount++; } - if ((argc == 2) && !strcmp(argv[1], "erase")) { + if ((argc == 2) && !strncasecmp(argv[1], "erase", 1)) { stm32f4_option_write_default(t); } - else if ((argc > 1) && !strcmp(argv[1], "write")) { + else if ((argc > 2) && !strncasecmp(argv[1], "write", 1)) { val[0] = strtoul(argv[2], NULL, 0); count++; - if (argc > 2) { + if (argc > 3) { val[1] = strtoul(argv[3], NULL, 0); count ++; } - if (argc > 3) { + if (argc > 4) { val[2] = strtoul(argv[4], NULL, 0); count ++; } @@ -665,22 +692,11 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) tc_printf(t, "\n"); } - val[0] = (target_mem_read32(t, start + 8) & 0xffff) << 16; - val[0] |= (target_mem_read32(t, start ) & 0xffff); - if (readcount > 1) { - if (start == 0x1FFFC000) /* F4 */ { - val[1] = target_mem_read32(t, 0x1ffec008); - val[1] &= 0xffff; - val[1] <<= 16; - } else { - val[1] = (target_mem_read32(t, start + 0x18) & 0xffff) << 16; - val[1] |= (target_mem_read32(t, start + 0x10) & 0xffff); - } - } - if (readcount > 2) { - val[2] = (target_mem_read32(t, start + 0x28) & 0xffff) << 16; - val[2] |= (target_mem_read32(t, start + 0x20) & 0xffff); - } + val[0] = target_mem_read32(t, FLASH_OPTCR); + if (readcount > 1) + val[1] = target_mem_read32(t, FLASH_OPTCR + 4); + if (readcount > 2) + val[2] = target_mem_read32(t, FLASH_OPTCR + 8); optcr_mask(t, val); tc_printf(t, "OPTCR: 0x%08X ", val[0]); if (readcount > 1) diff --git a/src/target/target.c b/src/target/target.c index 5c0ca574..7171da8e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -410,6 +410,16 @@ void target_set_cmdline(target *t, char *cmdline) { DEBUG("cmdline: >%s<\n", t->cmdline); } +/* Set heapinfo for semihosting */ +void target_set_heapinfo(target *t, target_addr heap_base, target_addr heap_limit, + target_addr stack_base, target_addr stack_limit) { + if (t == NULL) return; + t->heapinfo[0] = heap_base; + t->heapinfo[1] = heap_limit; + t->heapinfo[2] = stack_base; + t->heapinfo[3] = stack_limit; +} + /* Break-/watchpoint functions */ int target_breakwatch_set(target *t, enum target_breakwatch type, target_addr addr, size_t len) diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 7be19ed2..7aa2c8ac 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -121,6 +121,7 @@ struct target_s { const char *driver; const char *core; char cmdline[MAX_CMDLINE]; + target_addr heapinfo[4]; struct target_command_s *commands; struct target_s *next;