struct gdb_fileio_info *fileio_info);
static int target_gdb_fileio_end_default(struct target *target, int retcode,
int fileio_errno, bool ctrl_c);
-static int target_profiling_default(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
/* targets */
extern struct target_type arm7tdmi_target;
struct target *all_targets;
static struct target_event_callback *target_event_callbacks;
static struct target_timer_callback *target_timer_callbacks;
-LIST_HEAD(target_reset_callback_list);
-LIST_HEAD(target_trace_callback_list);
+static LIST_HEAD(target_reset_callback_list);
+static LIST_HEAD(target_trace_callback_list);
static const int polling_interval = 100;
static const Jim_Nvp nvp_assert[] = {
{ .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
{ .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
{ .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
- { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" },
- { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
- { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
- { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" },
+ { .value = ERROR_TARGET_UNALIGNED_ACCESS, .name = "err-unaligned-access" },
+ { .value = ERROR_TARGET_DATA_ABORT, .name = "err-data-abort" },
+ { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE, .name = "err-resource-not-available" },
+ { .value = ERROR_TARGET_TRANSLATION_FAULT, .name = "err-translation-fault" },
{ .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
{ .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
{ .value = -1, .name = NULL }
{ .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },
{ .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
- { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" },
+ { .value = TARGET_EVENT_GDB_FLASH_WRITE_END, .name = "gdb-flash-write-end" },
{ .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
- { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" },
+ { .value = TARGET_EVENT_GDB_FLASH_ERASE_END, .name = "gdb-flash-erase-end" },
{ .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
};
static const Jim_Nvp nvp_target_debug_reason[] = {
- { .name = "debug-request" , .value = DBG_REASON_DBGRQ },
- { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT },
- { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT },
+ { .name = "debug-request", .value = DBG_REASON_DBGRQ },
+ { .name = "breakpoint", .value = DBG_REASON_BREAKPOINT },
+ { .name = "watchpoint", .value = DBG_REASON_WATCHPOINT },
{ .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
- { .name = "single-step" , .value = DBG_REASON_SINGLESTEP },
- { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED },
- { .name = "program-exit" , .value = DBG_REASON_EXIT },
- { .name = "exception-catch" , .value = DBG_REASON_EXC_CATCH },
- { .name = "undefined" , .value = DBG_REASON_UNDEFINED },
+ { .name = "single-step", .value = DBG_REASON_SINGLESTEP },
+ { .name = "target-not-halted", .value = DBG_REASON_NOTHALTED },
+ { .name = "program-exit", .value = DBG_REASON_EXIT },
+ { .name = "exception-catch", .value = DBG_REASON_EXC_CATCH },
+ { .name = "undefined", .value = DBG_REASON_UNDEFINED },
{ .name = NULL, .value = -1 },
};
static const Jim_Nvp nvp_reset_modes[] = {
{ .name = "unknown", .value = RESET_UNKNOWN },
- { .name = "run" , .value = RESET_RUN },
- { .name = "halt" , .value = RESET_HALT },
- { .name = "init" , .value = RESET_INIT },
- { .name = NULL , .value = -1 },
+ { .name = "run", .value = RESET_RUN },
+ { .name = "halt", .value = RESET_HALT },
+ { .name = "init", .value = RESET_INIT },
+ { .name = NULL, .value = -1 },
};
const char *debug_reason_name(struct target *t)
return x + 1;
}
+static void append_to_list_all_targets(struct target *target)
+{
+ struct target **t = &all_targets;
+
+ while (*t)
+ t = &((*t)->next);
+ *t = target;
+}
+
/* read a uint64_t from a buffer in target memory endianness */
uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
{
* @param address Optionally used as the program counter.
* @param handle_breakpoints True iff breakpoints at the resumption PC
* should be skipped. (For example, maybe execution was stopped by
- * such a breakpoint, in which case it would be counterprodutive to
+ * such a breakpoint, in which case it would be counterproductive to
* let it re-trigger.
* @param debug_execution False if all working areas allocated by OpenOCD
* should be released and/or restored to their original contents.
return ERROR_OK;
}
-/* Equvivalent Tcl code arp_examine_one is in src/target/startup.tcl
+/* Equivalent Tcl code arp_examine_one is in src/target/startup.tcl
* Keep in sync */
int target_examine_one(struct target *target)
{
if (target->defer_examine)
continue;
- retval = target_examine_one(target);
- if (retval != ERROR_OK)
- return retval;
+ int retval2 = target_examine_one(target);
+ if (retval2 != ERROR_OK) {
+ LOG_WARNING("target %s examination failed", target_name(target));
+ retval = retval2;
+ }
}
return retval;
}
* programming. The exact delay shouldn't matter as long as it's
* less than buffer size / flash speed. This is very unlikely to
* run when using high latency connections such as USB. */
- alive_sleep(10);
+ alive_sleep(2);
/* to stop an infinite loop on some targets check and increment a timeout
* this issue was observed on a stellaris using the new ICDI interface */
- if (timeout++ >= 500) {
+ if (timeout++ >= 2500) {
LOG_ERROR("timeout waiting for algorithm, a target reset is recommended");
return ERROR_FLASH_OPERATION_FAILED;
}
if (thisrun_bytes > count * block_size)
thisrun_bytes = count * block_size;
+ /* Force end of large blocks to be word aligned */
+ if (thisrun_bytes >= 16)
+ thisrun_bytes -= (rp + thisrun_bytes) & 0x03;
+
/* Write data to fifo */
retval = target_write_buffer(target, wp, thisrun_bytes, buffer);
if (retval != ERROR_OK)
return retval;
}
+int target_run_read_async_algorithm(struct target *target,
+ uint8_t *buffer, uint32_t count, int block_size,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ uint32_t buffer_start, uint32_t buffer_size,
+ uint32_t entry_point, uint32_t exit_point, void *arch_info)
+{
+ int retval;
+ int timeout = 0;
+
+ const uint8_t *buffer_orig = buffer;
+
+ /* Set up working area. First word is write pointer, second word is read pointer,
+ * rest is fifo data area. */
+ uint32_t wp_addr = buffer_start;
+ uint32_t rp_addr = buffer_start + 4;
+ uint32_t fifo_start_addr = buffer_start + 8;
+ uint32_t fifo_end_addr = buffer_start + buffer_size;
+
+ uint32_t wp = fifo_start_addr;
+ uint32_t rp = fifo_start_addr;
+
+ /* validate block_size is 2^n */
+ assert(!block_size || !(block_size & (block_size - 1)));
+
+ retval = target_write_u32(target, wp_addr, wp);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target_write_u32(target, rp_addr, rp);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Start up algorithm on target */
+ retval = target_start_algorithm(target, num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ entry_point,
+ exit_point,
+ arch_info);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("error starting target flash read algorithm");
+ return retval;
+ }
+
+ while (count > 0) {
+ retval = target_read_u32(target, wp_addr, &wp);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("failed to get write pointer");
+ break;
+ }
+
+ LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32,
+ (size_t) (buffer - buffer_orig), count, wp, rp);
+
+ if (wp == 0) {
+ LOG_ERROR("flash read algorithm aborted by target");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ }
+
+ if (((wp - fifo_start_addr) & (block_size - 1)) || wp < fifo_start_addr || wp >= fifo_end_addr) {
+ LOG_ERROR("corrupted fifo write pointer 0x%" PRIx32, wp);
+ break;
+ }
+
+ /* Count the number of bytes available in the fifo without
+ * crossing the wrap around. */
+ uint32_t thisrun_bytes;
+ if (wp >= rp)
+ thisrun_bytes = wp - rp;
+ else
+ thisrun_bytes = fifo_end_addr - rp;
+
+ if (thisrun_bytes == 0) {
+ /* Throttle polling a bit if transfer is (much) faster than flash
+ * reading. The exact delay shouldn't matter as long as it's
+ * less than buffer size / flash speed. This is very unlikely to
+ * run when using high latency connections such as USB. */
+ alive_sleep(2);
+
+ /* to stop an infinite loop on some targets check and increment a timeout
+ * this issue was observed on a stellaris using the new ICDI interface */
+ if (timeout++ >= 2500) {
+ LOG_ERROR("timeout waiting for algorithm, a target reset is recommended");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ continue;
+ }
+
+ /* Reset our timeout */
+ timeout = 0;
+
+ /* Limit to the amount of data we actually want to read */
+ if (thisrun_bytes > count * block_size)
+ thisrun_bytes = count * block_size;
+
+ /* Force end of large blocks to be word aligned */
+ if (thisrun_bytes >= 16)
+ thisrun_bytes -= (rp + thisrun_bytes) & 0x03;
+
+ /* Read data from fifo */
+ retval = target_read_buffer(target, rp, thisrun_bytes, buffer);
+ if (retval != ERROR_OK)
+ break;
+
+ /* Update counters and wrap write pointer */
+ buffer += thisrun_bytes;
+ count -= thisrun_bytes / block_size;
+ rp += thisrun_bytes;
+ if (rp >= fifo_end_addr)
+ rp = fifo_start_addr;
+
+ /* Store updated write pointer to target */
+ retval = target_write_u32(target, rp_addr, rp);
+ if (retval != ERROR_OK)
+ break;
+
+ /* Avoid GDB timeouts */
+ keep_alive();
+
+ }
+
+ if (retval != ERROR_OK) {
+ /* abort flash write algorithm on target */
+ target_write_u32(target, rp_addr, 0);
+ }
+
+ int retval2 = target_wait_algorithm(target, num_mem_params, mem_params,
+ num_reg_params, reg_params,
+ exit_point,
+ 10000,
+ arch_info);
+
+ if (retval2 != ERROR_OK) {
+ LOG_ERROR("error waiting for target flash write algorithm");
+ retval = retval2;
+ }
+
+ if (retval == ERROR_OK) {
+ /* check if algorithm set wp = 0 after fifo writer loop finished */
+ retval = target_read_u32(target, wp_addr, &wp);
+ if (retval == ERROR_OK && wp == 0) {
+ LOG_ERROR("flash read algorithm aborted by target");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ }
+ }
+
+ return retval;
+}
+
int target_read_memory(struct target *target,
target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class)
{
- int result = target->type->get_gdb_reg_list(target, reg_list,
+ int result = ERROR_FAIL;
+
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ goto done;
+ }
+
+ result = target->type->get_gdb_reg_list(target, reg_list,
reg_list_size, reg_class);
+
+done:
if (result != ERROR_OK) {
*reg_list = NULL;
*reg_list_size = 0;
bool target_supports_gdb_connection(struct target *target)
{
/*
- * based on current code, we can simply exclude all the targets that
- * don't provide get_gdb_reg_list; this could change with new targets.
+ * exclude all the targets that don't provide get_gdb_reg_list
+ * or that have explicit gdb_max_connection == 0
*/
- return !!target->type->get_gdb_reg_list;
+ return !!target->type->get_gdb_reg_list && !!target->gdb_max_connections;
}
int target_step(struct target *target,
return 32;
}
-int target_profiling(struct target *target, uint32_t *samples,
+static int target_profiling(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted (profiling)", target->cmd_name);
- return ERROR_TARGET_NOT_HALTED;
- }
return target->type->profiling(target, samples, max_num_samples,
num_samples, seconds);
}
/* If backup memory was allocated to this area, it has the wrong size
* now so free it and it will be reallocated if/when needed */
- if (area->backup) {
- free(area->backup);
- area->backup = NULL;
- }
+ free(area->backup);
+ area->backup = NULL;
}
}
/* Remove the last */
struct working_area *to_be_freed = c->next;
c->next = c->next->next;
- if (to_be_freed->backup)
- free(to_be_freed->backup);
+ free(to_be_freed->backup);
free(to_be_freed);
/* If backup memory was allocated to the remaining area, it's has
* the wrong size now */
- if (c->backup) {
- free(c->backup);
- c->backup = NULL;
- }
+ free(c->backup);
+ c->backup = NULL;
} else {
c = c->next;
}
if (target->type->deinit_target)
target->type->deinit_target(target);
- if (target->semihosting)
- free(target->semihosting);
+ free(target->semihosting);
jtag_unregister_event_callback(jtag_enable_callback, target);
return ERROR_OK;
}
-static int target_profiling_default(struct target *target, uint32_t *samples,
+int target_profiling_default(struct target *target, uint32_t *samples,
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
{
struct timeval timeout, now;
*/
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
{
- LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
+ LOG_DEBUG("writing buffer of %" PRIu32 " byte at " TARGET_ADDR_FMT,
size, address);
if (!target_was_examined(target)) {
*/
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
{
- LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
+ LOG_DEBUG("reading buffer of %" PRIu32 " byte at " TARGET_ADDR_FMT,
size, address);
if (!target_was_examined(target)) {
if (retval != ERROR_OK) {
buffer = malloc(size);
if (buffer == NULL) {
- LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size);
+ LOG_ERROR("error allocating buffer for section (%" PRIu32 " bytes)", size);
return ERROR_COMMAND_SYNTAX_ERROR;
}
retval = target_read_buffer(target, address, size, buffer);
continue;
/* only print cached values if they are valid */
if (reg->valid) {
- value = buf_to_str(reg->value,
- reg->size, 16);
+ value = buf_to_hex_str(reg->value,
+ reg->size);
command_print(CMD,
"(%i) %s (/%" PRIu32 "): 0x%s%s",
count, reg->name,
} else {
command_print(CMD, "(%i) %s (/%" PRIu32 ")",
count, reg->name,
- reg->size) ;
+ reg->size);
}
}
cache = cache->next;
if (reg->valid == 0)
reg->type->get(reg);
- value = buf_to_str(reg->value, reg->size, 16);
+ value = buf_to_hex_str(reg->value, reg->size);
command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
free(value);
return ERROR_OK;
reg->type->set(reg, buf);
- value = buf_to_str(reg->value, reg->size, 16);
+ value = buf_to_hex_str(reg->value, reg->size);
command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
free(value);
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
image->base_address = addr;
- image->base_address_set = 1;
+ image->base_address_set = true;
} else
- image->base_address_set = 0;
+ image->base_address_set = false;
- image->start_address_set = 0;
+ image->start_address_set = false;
if (CMD_ARGC >= 4)
COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address);
uint32_t image_size;
target_addr_t min_address = 0;
target_addr_t max_address = -1;
- int i;
struct image image;
int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
image_size = 0x0;
retval = ERROR_OK;
- for (i = 0; i < image.num_sections; i++) {
+ for (unsigned int i = 0; i < image.num_sections; i++) {
buffer = malloc(image.sections[i].size);
if (buffer == NULL) {
command_print(CMD,
uint32_t offset = 0;
uint32_t length = buf_cnt;
- /* DANGER!!! beware of unsigned comparision here!!! */
+ /* DANGER!!! beware of unsigned comparison here!!! */
if ((image.sections[i].base_address + buf_cnt >= min_address) &&
(image.sections[i].base_address < max_address)) {
uint8_t *buffer;
size_t buf_cnt;
uint32_t image_size;
- int i;
int retval;
uint32_t checksum = 0;
uint32_t mem_checksum = 0;
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
image.base_address = addr;
- image.base_address_set = 1;
+ image.base_address_set = true;
} else {
- image.base_address_set = 0;
+ image.base_address_set = false;
image.base_address = 0x0;
}
- image.start_address_set = 0;
+ image.start_address_set = false;
retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
if (retval != ERROR_OK)
image_size = 0x0;
int diffs = 0;
retval = ERROR_OK;
- for (i = 0; i < image.num_sections; i++) {
+ for (unsigned int i = 0; i < image.num_sections; i++) {
buffer = malloc(image.sections[i].size);
if (buffer == NULL) {
command_print(CMD,
- "error allocating buffer for section (%d bytes)",
- (int)(image.sections[i].size));
+ "error allocating buffer for section (%" PRIu32 " bytes)",
+ image.sections[i].size);
break;
}
retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
struct breakpoint *breakpoint = target->breakpoints;
while (breakpoint) {
if (breakpoint->type == BKPT_SOFT) {
- char *buf = buf_to_str(breakpoint->orig_instr,
- breakpoint->length, 16);
+ char *buf = buf_to_hex_str(breakpoint->orig_instr,
+ breakpoint->length);
command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s",
breakpoint->address,
breakpoint->length,
uint32_t offset;
uint32_t num_of_samples;
int retval = ERROR_OK;
+ bool halted_before_profiling = target->state == TARGET_HALTED;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
free(samples);
return retval;
}
- if (target->state == TARGET_RUNNING) {
+
+ if (target->state == TARGET_RUNNING && halted_before_profiling) {
+ /* The target was halted before we started and is running now. Halt it,
+ * for consistency. */
retval = target_halt(target);
if (retval != ERROR_OK) {
free(samples);
return retval;
}
+ } else if (target->state == TARGET_HALTED && !halted_before_profiling) {
+ /* The target was running before we started and is halted now. Resume
+ * it, for consistency. */
+ retval = target_resume(target, 1, 0, 0, 0);
+ if (retval != ERROR_OK) {
+ free(samples);
+ return retval;
+ }
}
retval = target_poll(target);
} else {
char buf[100];
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads",
+ sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRIu32 " byte reads",
addr,
width);
Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL);
retval = target_read_memory(target, addr, width, count, buffer);
if (retval != ERROR_OK) {
/* BOO !*/
- LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed",
+ LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRIu32 ", cnt=%" PRIu32 ", failed",
addr,
width,
count);
} else {
char buf[100];
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads",
+ sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRIu32 " byte reads",
addr,
width);
Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL);
retval = target_write_memory(target, addr, width, count, buffer);
if (retval != ERROR_OK) {
/* BOO !*/
- LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed",
+ LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRIu32 ", cnt=%" PRIu32 ", failed",
addr,
width,
count);
struct command_context *cmd_ctx = current_command_context(teap->interp);
struct target *saved_target_override = cmd_ctx->current_target_override;
cmd_ctx->current_target_override = target;
+
retval = Jim_EvalObj(teap->interp, teap->body);
+ cmd_ctx->current_target_override = saved_target_override;
+
+ if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
+ return;
+
if (retval == JIM_RETURN)
retval = teap->interp->returnCode;
/* clean both error code and stacktrace before return */
Jim_Eval(teap->interp, "error \"\" \"\"");
}
-
- cmd_ctx->current_target_override = saved_target_override;
}
}
}
TCFG_RTOS,
TCFG_DEFER_EXAMINE,
TCFG_GDB_PORT,
+ TCFG_GDB_MAX_CONNECTIONS,
};
static Jim_Nvp nvp_config_opts[] = {
{ .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS },
{ .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE },
{ .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
- { .name = "-endian" , .value = TCFG_ENDIAN },
+ { .name = "-endian", .value = TCFG_ENDIAN },
{ .name = "-coreid", .value = TCFG_COREID },
{ .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
{ .name = "-dbgbase", .value = TCFG_DBGBASE },
{ .name = "-rtos", .value = TCFG_RTOS },
{ .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE },
{ .name = "-gdb-port", .value = TCFG_GDB_PORT },
+ { .name = "-gdb-max-connections", .value = TCFG_GDB_MAX_CONNECTIONS },
{ .name = NULL, .value = -1 }
};
}
switch (n->value) {
case TCFG_TYPE:
- /* not setable */
+ /* not settable */
if (goi->isconfigure) {
Jim_SetResultFormatted(goi->interp,
"not settable: %s", n->name);
Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1);
/* loop for more */
break;
+
+ case TCFG_GDB_MAX_CONNECTIONS:
+ if (goi->isconfigure) {
+ struct command_context *cmd_ctx = current_command_context(goi->interp);
+ if (cmd_ctx->mode != COMMAND_CONFIG) {
+ Jim_SetResultString(goi->interp, "-gdb-max-conenctions must be configured before 'init'", -1);
+ return JIM_ERR;
+ }
+
+ e = Jim_GetOpt_Wide(goi, &w);
+ if (e != JIM_OK)
+ return e;
+ target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w;
+ } else {
+ if (goi->argc != 0)
+ goto no_params;
+ }
+ Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections));
+ break;
}
} /* while (goi->argc) */
/* Create it */
target = calloc(1, sizeof(struct target));
+ if (!target) {
+ LOG_ERROR("Out of memory");
+ return JIM_ERR;
+ }
+
/* set target number */
target->target_number = new_target_number();
- cmd_ctx->current_target = target;
/* allocate memory for each unique target type */
- target->type = calloc(1, sizeof(struct target_type));
+ target->type = malloc(sizeof(struct target_type));
+ if (!target->type) {
+ LOG_ERROR("Out of memory");
+ free(target);
+ return JIM_ERR;
+ }
memcpy(target->type, target_types[x], sizeof(struct target_type));
/* initialize trace information */
target->trace_info = calloc(1, sizeof(struct trace));
+ if (!target->trace_info) {
+ LOG_ERROR("Out of memory");
+ free(target->type);
+ free(target);
+ return JIM_ERR;
+ }
target->dbgmsg = NULL;
target->dbg_msg_enabled = 0;
target->rtos_auto_detect = false;
target->gdb_port_override = NULL;
+ target->gdb_max_connections = 1;
/* Do the rest as "configure" options */
goi->isconfigure = 1;
}
if (e != JIM_OK) {
+ rtos_destroy(target);
free(target->gdb_port_override);
+ free(target->trace_info);
free(target->type);
free(target);
return e;
cp = Jim_GetString(new_cmd, NULL);
target->cmd_name = strdup(cp);
+ if (!target->cmd_name) {
+ LOG_ERROR("Out of memory");
+ rtos_destroy(target);
+ free(target->gdb_port_override);
+ free(target->trace_info);
+ free(target->type);
+ free(target);
+ return JIM_ERR;
+ }
if (target->type->target_create) {
e = (*(target->type->target_create))(target, goi->interp);
if (e != ERROR_OK) {
LOG_DEBUG("target_create failed");
+ free(target->cmd_name);
+ rtos_destroy(target);
free(target->gdb_port_override);
+ free(target->trace_info);
free(target->type);
- free(target->cmd_name);
free(target);
return JIM_ERR;
}
LOG_ERROR("unable to register '%s' commands", cp);
}
- /* append to end of list */
- {
- struct target **tpp;
- tpp = &(all_targets);
- while (*tpp)
- tpp = &((*tpp)->next);
- *tpp = target;
- }
-
/* now - create the new target name command */
const struct command_registration target_subcommands[] = {
{
COMMAND_REGISTRATION_DONE
};
e = register_commands(cmd_ctx, NULL, target_commands);
- if (ERROR_OK != e)
+ if (e != ERROR_OK) {
+ if (target->type->deinit_target)
+ target->type->deinit_target(target);
+ free(target->cmd_name);
+ rtos_destroy(target);
+ free(target->gdb_port_override);
+ free(target->trace_info);
+ free(target->type);
+ free(target);
return JIM_ERR;
+ }
struct command *c = command_find_in_context(cmd_ctx, cp);
assert(c);
command_set_handler_data(c, target);
- return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
+ /* append to end of list */
+ append_to_list_all_targets(target);
+
+ cmd_ctx->current_target = target;
+ return JIM_OK;
}
static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx != NULL);
- Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1);
+ struct target *target = get_current_target_or_null(cmd_ctx);
+ if (target)
+ Jim_SetResultString(interp, target_name(target), -1);
return JIM_OK;
}
retval = 0;
LOG_DEBUG("%d", argc);
/* argv[1] = target to associate in smp
- * argv[2] = target to assoicate in smp
+ * argv[2] = target to associate in smp
* argv[3] ...
*/
static void free_fastload(void)
{
if (fastload != NULL) {
- int i;
- for (i = 0; i < fastload_num; i++) {
- if (fastload[i].data)
- free(fastload[i].data);
- }
+ for (int i = 0; i < fastload_num; i++)
+ free(fastload[i].data);
free(fastload);
fastload = NULL;
}
uint32_t image_size;
target_addr_t min_address = 0;
target_addr_t max_address = -1;
- int i;
struct image image;
return ERROR_FAIL;
}
memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
- for (i = 0; i < image.num_sections; i++) {
+ for (unsigned int i = 0; i < image.num_sections; i++) {
buffer = malloc(image.sections[i].size);
if (buffer == NULL) {
command_print(CMD, "error allocating buffer for section (%d bytes)",
uint32_t offset = 0;
uint32_t length = buf_cnt;
- /* DANGER!!! beware of unsigned comparision here!!! */
+ /* DANGER!!! beware of unsigned comparison here!!! */
if ((image.sections[i].base_address + buf_cnt >= min_address) &&
(image.sections[i].base_address < max_address)) {