X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=ab094f96775b5441e0b8374f60017b44584931f8;hp=abe1b43ae03e01f5d79a464f5281d2cf93b23545;hb=61f3d4b7e42897fb1570bd4307137833cce0f7ba;hpb=b69119668ed8d9633280f8b596fe9af60f51644b diff --git a/src/target/target.c b/src/target/target.c index abe1b43ae0..ab094f9677 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -17,6 +17,9 @@ * Copyright (C) 2011 by Broadcom Corporation * * Evan Hunter - ehunter@broadcom.com * * * + * Copyright (C) ST-Ericsson SA 2011 * + * michel.jaouen@stericsson.com : smp minimum support * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -78,8 +81,10 @@ extern struct target_type arm11_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; extern struct target_type dsp563xx_target; +extern struct target_type dsp5680xx_target; extern struct target_type testee_target; extern struct target_type avr32_ap7k_target; +extern struct target_type stm32_stlink_target; static struct target_type *target_types[] = { @@ -100,8 +105,10 @@ static struct target_type *target_types[] = &mips_m4k_target, &avr_target, &dsp563xx_target, + &dsp5680xx_target, &testee_target, &avr32_ap7k_target, + &stm32_stlink_target, NULL, }; @@ -343,6 +350,38 @@ static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t *buffer = value; } +/* write a uint32_t array to a buffer in target memory endianness */ +void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + dstbuf[i] = target_buffer_get_u32(target,&buffer[i*4]); +} + +/* write a uint16_t array to a buffer in target memory endianness */ +void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + dstbuf[i] = target_buffer_get_u16(target,&buffer[i*2]); +} + +/* write a uint32_t array to a buffer in target memory endianness */ +void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, uint32_t *srcbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + target_buffer_set_u32(target,&buffer[i*4],srcbuf[i]); +} + +/* write a uint16_t array to a buffer in target memory endianness */ +void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, uint16_t *srcbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + target_buffer_set_u16(target,&buffer[i*2],srcbuf[i]); +} + /* return a pointer to a configured target; id is name or number */ struct target *get_target(const char *id) { @@ -695,6 +734,81 @@ done: return retval; } +/** + * Downloads a target-specific native code algorithm to the target, + * executes and leaves it running. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t entry_point, uint32_t exit_point, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target_was_examined(target)) + { + LOG_ERROR("Target not examined yet"); + goto done; + } + if (!target->type->start_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (target->running_alg) { + LOG_ERROR("Target is already running an algorithm"); + goto done; + } + + target->running_alg = true; + retval = target->type->start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, arch_info); + +done: + return retval; +} + +/** + * Waits for an algorithm started with target_start_algorithm() to complete. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t exit_point, int timeout_ms, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target->type->wait_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (!target->running_alg) { + LOG_ERROR("Target is not running an algorithm"); + goto done; + } + + retval = target->type->wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, arch_info); + if (retval != ERROR_TARGET_TIMEOUT) + target->running_alg = false; + +done: + return retval; +} + int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -729,12 +843,33 @@ int target_bulk_write_memory(struct target *target, int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { - if (target->state != TARGET_HALTED) { + if ((target->state != TARGET_HALTED)&&(breakpoint->type!=BKPT_HARD)) { LOG_WARNING("target %s is not halted", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->add_breakpoint(target, breakpoint); } + +int target_add_context_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_context_breakpoint(target, breakpoint); +} + +int target_add_hybrid_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_hybrid_breakpoint(target, breakpoint); +} + int target_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -807,6 +942,8 @@ static int target_init_one(struct command_context *cmd_ctx, if (type->check_reset== NULL) type->check_reset = default_check_reset; + assert(type->init_target != NULL); + int retval = type->init_target(cmd_ctx, target); if (ERROR_OK != retval) { @@ -910,6 +1047,8 @@ static int target_init(struct command_context *cmd_ctx) COMMAND_HANDLER(handle_target_init_command) { + int retval; + if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; @@ -921,6 +1060,10 @@ COMMAND_HANDLER(handle_target_init_command) } target_initialized = true; + retval = command_run_line(CMD_CTX, "init_targets"); + if (ERROR_OK != retval) + return retval; + LOG_DEBUG("Initializing targets..."); return target_init(CMD_CTX); } @@ -931,7 +1074,7 @@ int target_register_event_callback(int (*callback)(struct target *target, enum t if (callback == NULL) { - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } if (*callbacks_p) @@ -956,7 +1099,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int if (callback == NULL) { - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } if (*callbacks_p) @@ -994,7 +1137,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target, enum if (callback == NULL) { - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } while (c) @@ -1021,7 +1164,7 @@ static int target_unregister_timer_callback(int (*callback)(void *priv), void *p if (callback == NULL) { - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } while (c) @@ -1538,7 +1681,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz if (buffer == NULL) { LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size); - return ERROR_INVALID_ARGUMENTS; + return ERROR_COMMAND_SYNTAX_ERROR; } retval = target_read_buffer(target, address, size, buffer); if (retval != ERROR_OK) @@ -1728,30 +1871,38 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return retval; } -COMMAND_HANDLER(handle_targets_command) +static int find_target(struct command_context *cmd_ctx, const char *name) { - struct target *target = all_targets; + struct target *target = get_target(name); + if (target == NULL) { + LOG_ERROR("Target: %s is unknown, try one of:\n", name); + return ERROR_FAIL; + } + if (!target->tap->enabled) { + LOG_USER("Target: TAP %s is disabled, " + "can't be the current target\n", + target->tap->dotted_name); + return ERROR_FAIL; + } + + cmd_ctx->current_target = target->target_number; + return ERROR_OK; +} + +COMMAND_HANDLER(handle_targets_command) +{ + int retval = ERROR_OK; if (CMD_ARGC == 1) { - target = get_target(CMD_ARGV[0]); - if (target == NULL) { - command_print(CMD_CTX,"Target: %s is unknown, try one of:\n", CMD_ARGV[0]); - goto DumpTargets; - } - if (!target->tap->enabled) { - command_print(CMD_CTX,"Target: TAP %s is disabled, " - "can't be the current target\n", - target->tap->dotted_name); - return ERROR_FAIL; + retval = find_target(CMD_CTX, CMD_ARGV[0]); + if (retval == ERROR_OK) { + /* we're done! */ + return retval; } - - CMD_CTX->current_target = target->target_number; - return ERROR_OK; } -DumpTargets: - target = all_targets; + struct target *target = all_targets; command_print(CMD_CTX, " TargetName Type Endian TapName State "); command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); while (target) @@ -1768,19 +1919,20 @@ DumpTargets: marker = '*'; /* keep columns lined up to match the headers above */ - command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s", - target->target_number, - marker, - target_name(target), - target_type_name(target), - Jim_Nvp_value2name_simple(nvp_target_endian, - target->endianness)->name, - target->tap->dotted_name, - state); + command_print(CMD_CTX, + "%2d%c %-18s %-10s %-6s %-18s %s", + target->target_number, + marker, + target_name(target), + target_type_name(target), + Jim_Nvp_value2name_simple(nvp_target_endian, + target->endianness)->name, + target->tap->dotted_name, + state); target = target->next; } - return ERROR_OK; + return retval; } /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ @@ -2057,6 +2209,8 @@ COMMAND_HANDLER(handle_reg_command) } } + assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { @@ -2077,6 +2231,8 @@ COMMAND_HANDLER(handle_reg_command) if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); + if (buf == NULL) + return ERROR_FAIL; str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); reg->type->set(reg, buf); @@ -2090,9 +2246,7 @@ COMMAND_HANDLER(handle_reg_command) return ERROR_OK; } - command_print(CMD_CTX, "usage: reg <#|name> [value]"); - - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(handle_poll_command) @@ -2139,7 +2293,6 @@ COMMAND_HANDLER(handle_wait_halt_command) int retval = parse_uint(CMD_ARGV[0], &ms); if (ERROR_OK != retval) { - command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME); return ERROR_COMMAND_SYNTAX_ERROR; } // convert seconds (given) to milliseconds (needed) @@ -2644,7 +2797,7 @@ COMMAND_HANDLER(handle_load_image_command) COMMAND_HANDLER(handle_dump_image_command) { struct fileio fileio; - uint8_t buffer[560]; + uint8_t *buffer; int retval, retvaltemp; uint32_t address, size; struct duration bench; @@ -2656,17 +2809,23 @@ COMMAND_HANDLER(handle_dump_image_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); + uint32_t buf_size = (size > 4096) ? 4096 : size; + buffer = malloc(buf_size); + if (!buffer) + return ERROR_FAIL; + retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + free(buffer); return retval; + } duration_start(&bench); - retval = ERROR_OK; while (size > 0) { size_t size_written; - uint32_t this_run_size = (size > 560) ? 560 : size; + uint32_t this_run_size = (size > buf_size) ? buf_size : size; retval = target_read_buffer(target, address, this_run_size, buffer); if (retval != ERROR_OK) { @@ -2683,6 +2842,8 @@ COMMAND_HANDLER(handle_dump_image_command) address += this_run_size; } + free(buffer); + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { int filesize; @@ -2882,7 +3043,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) { char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16); - command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", + command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); @@ -2890,9 +3051,22 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } else { - command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i", - breakpoint->address, - breakpoint->length, breakpoint->set); + if ((breakpoint->address == 0) && (breakpoint->asid != 0)) + command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->asid, + breakpoint->length, breakpoint->set); + else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) + { + command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); + command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, + breakpoint->asid); + } + else + command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); } breakpoint = breakpoint->next; @@ -2901,43 +3075,93 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } static int handle_bp_command_set(struct command_context *cmd_ctx, - uint32_t addr, uint32_t length, int hw) + uint32_t addr, uint32_t asid, uint32_t length, int hw) { struct target *target = get_current_target(cmd_ctx); - int retval = breakpoint_add(target, addr, length, hw); - if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + + if (asid == 0) + { + int retval = breakpoint_add(target, addr, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + else + { + LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); + return retval; + } + } + else if (addr == 0) + { + int retval = context_breakpoint_add(target, asid, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); + else + { + LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); + return retval; + } + } else - LOG_ERROR("Failure setting breakpoint"); - return retval; + { + int retval = hybrid_breakpoint_add(target, addr, asid, length, hw); + if(ERROR_OK == retval) + command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); + else + { + LOG_ERROR("Failure setting breakpoint, the same address is already used"); + return retval; + } + } + return ERROR_OK; } COMMAND_HANDLER(handle_bp_command) { - if (CMD_ARGC == 0) - return handle_bp_command_list(CMD_CTX); - - if (CMD_ARGC < 2 || CMD_ARGC > 3) - { - command_print(CMD_CTX, "usage: bp