* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "image.h"
#include "rtos/rtos.h"
+/* default halt wait timeout (ms) */
+#define DEFAULT_HALT_TIMEOUT 5000
+
static int target_read_buffer_default(struct target *target, uint32_t address,
uint32_t size, uint8_t *buffer);
static int target_write_buffer_default(struct target *target, uint32_t address,
extern struct target_type xscale_target;
extern struct target_type cortexm3_target;
extern struct target_type cortexa8_target;
+extern struct target_type cortexr4_target;
extern struct target_type arm11_target;
extern struct target_type mips_m4k_target;
extern struct target_type avr_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;
+extern struct target_type hla_target;
+extern struct target_type nds32_v2_target;
+extern struct target_type nds32_v3_target;
+extern struct target_type nds32_v3m_target;
static struct target_type *target_types[] = {
&arm7tdmi_target,
&xscale_target,
&cortexm3_target,
&cortexa8_target,
+ &cortexr4_target,
&arm11_target,
&mips_m4k_target,
&avr_target,
&dsp5680xx_target,
&testee_target,
&avr32_ap7k_target,
- &stm32_stlink_target,
+ &hla_target,
+ &nds32_v2_target,
+ &nds32_v3_target,
+ &nds32_v3m_target,
NULL,
};
/* try as tcltarget name */
for (target = all_targets; target; target = target->next) {
- if (target->cmd_name == NULL)
+ if (target_name(target) == NULL)
continue;
- if (strcmp(id, target->cmd_name) == 0)
+ if (strcmp(id, target_name(target)) == 0)
return target;
}
for (target = all_targets; target; target = target->next) {
if (target->target_number == (int)num) {
LOG_WARNING("use '%s' as target identifier, not '%u'",
- target->cmd_name, num);
+ target_name(target), num);
return target;
}
}
target->halt_issued = false;
else {
long long t = timeval_ms() - target->halt_issued_time;
- if (t > 1000) {
+ if (t > DEFAULT_HALT_TIMEOUT) {
target->halt_issued = false;
LOG_INFO("Halt timed out, wake up GDB.");
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
return target->type->name;
}
-static int target_write_memory_imp(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- return target->type->write_memory_imp(target, address, size, count, buffer);
-}
-
-static int target_read_memory_imp(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- return target->type->read_memory_imp(target, address, size, count, buffer);
-}
-
-static int target_soft_reset_halt_imp(struct target *target)
+static int target_soft_reset_halt(struct target *target)
{
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
- if (!target->type->soft_reset_halt_imp) {
+ if (!target->type->soft_reset_halt) {
LOG_ERROR("Target %s does not support soft_reset_halt",
target_name(target));
return ERROR_FAIL;
}
- return target->type->soft_reset_halt_imp(target);
+ return target->type->soft_reset_halt(target);
}
/**
uint32_t entry_point, uint32_t exit_point, void *arch_info)
{
int retval;
+ int timeout = 0;
/* Set up working area. First word is write pointer, second word is read pointer,
* rest is fifo data area. */
* less than buffer size / flash speed. This is very unlikely to
* run when using high latency connections such as USB. */
alive_sleep(10);
+
+ /* 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) {
+ 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 write */
if (thisrun_bytes > count * block_size)
thisrun_bytes = count * block_size;
int target_read_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_FAIL;
+ }
return target->type->read_memory(target, address, size, count, buffer);
}
-static int target_read_phys_memory(struct target *target,
+int target_read_phys_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_FAIL;
+ }
return target->type->read_phys_memory(target, address, size, count, buffer);
}
int target_write_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
{
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_FAIL;
+ }
return target->type->write_memory(target, address, size, count, buffer);
}
-static int target_write_phys_memory(struct target *target,
+int target_write_phys_memory(struct target *target,
uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
{
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_FAIL;
+ }
return target->type->write_phys_memory(target, address, size, count, buffer);
}
-int target_bulk_write_memory(struct target *target,
+static int target_bulk_write_memory_default(struct target *target,
uint32_t address, uint32_t count, const uint8_t *buffer)
{
- return target->type->bulk_write_memory(target, address, count, buffer);
+ return target_write_memory(target, address, 4, count, buffer);
}
int target_add_breakpoint(struct target *target,
struct breakpoint *breakpoint)
{
if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
+ LOG_WARNING("target %s is not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
return target->type->add_breakpoint(target, breakpoint);
struct breakpoint *breakpoint)
{
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
+ LOG_WARNING("target %s is not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
return target->type->add_context_breakpoint(target, breakpoint);
struct breakpoint *breakpoint)
{
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
+ LOG_WARNING("target %s is not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
return target->type->add_hybrid_breakpoint(target, breakpoint);
struct watchpoint *watchpoint)
{
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
+ LOG_WARNING("target %s is not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
return target->type->add_watchpoint(target, watchpoint);
return retval;
}
- /**
- * @todo get rid of those *memory_imp() methods, now that all
- * callers are using target_*_memory() accessors ... and make
- * sure the "physical" paths handle the same issues.
- */
- /* a non-invasive way(in terms of patches) to add some code that
- * runs before the type->write/read_memory implementation
- */
- type->write_memory_imp = target->type->write_memory;
- type->write_memory = target_write_memory_imp;
-
- type->read_memory_imp = target->type->read_memory;
- type->read_memory = target_read_memory_imp;
-
- type->soft_reset_halt_imp = target->type->soft_reset_halt;
- type->soft_reset_halt = target_soft_reset_halt_imp;
-
/* Sanity-check MMU support ... stub in what we must, to help
* implement it in stages, but warn if we need to do so.
*/
if (target->type->write_buffer == NULL)
target->type->write_buffer = target_write_buffer_default;
+ if (target->type->bulk_write_memory == NULL)
+ target->type->bulk_write_memory = target_bulk_write_memory_default;
+
return ERROR_OK;
}
new_wa->size = area->size - size;
new_wa->address = area->address + size;
new_wa->backup = NULL;
+ new_wa->user = NULL;
new_wa->free = true;
area->next = new_wa;
new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */
new_wa->address = target->working_area;
new_wa->backup = NULL;
+ new_wa->user = NULL;
new_wa->free = true;
}
c->free = false;
*area = c;
+ /* user pointer */
+ c->user = area;
+
print_wa_layout(target);
return ERROR_OK;
LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32,
area->size, area->address);
+ /* mark user pointer invalid */
+ /* TODO: Is this really safe? It points to some previous caller's memory.
+ * How could we know that the area pointer is still in that place and not
+ * some other vital data? What's the purpose of this, anyway? */
+ *area->user = NULL;
+ area->user = NULL;
+
target_merge_working_areas(target);
print_wa_layout(target);
if (restore)
target_restore_working_area(target, c);
c->free = true;
+ *c->user = NULL; /* Same as above */
+ c->user = NULL;
}
c = c->next;
}
return ERROR_OK;
}
-static int backoff_times;
-static int backoff_count;
-
/* process target state changes */
static int handle_target(void *priv)
{
recursive = 0;
}
- if (backoff_times > backoff_count) {
- /* do not poll this time as we failed previously */
- backoff_count++;
- return ERROR_OK;
- }
- backoff_count = 0;
-
/* Poll targets for state changes unless that's globally disabled.
* Skip targets that are currently disabled.
*/
if (!target->tap->enabled)
continue;
+ if (target->backoff.times > target->backoff.count) {
+ /* do not poll this time as we failed previously */
+ target->backoff.count++;
+ continue;
+ }
+ target->backoff.count = 0;
+
/* only poll target if we've got power and srst isn't asserted */
if (!powerDropout && !srstAsserted) {
/* polling may fail silently until the target has been examined */
retval = target_poll(target);
if (retval != ERROR_OK) {
/* 100ms polling interval. Increase interval between polling up to 5000ms */
- if (backoff_times * polling_interval < 5000) {
- backoff_times *= 2;
- backoff_times++;
+ if (target->backoff.times * polling_interval < 5000) {
+ target->backoff.times *= 2;
+ target->backoff.times++;
}
- LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms",
- backoff_times * polling_interval);
+ LOG_USER("Polling target %s failed, GDB will be halted. Polling again in %dms",
+ target_name(target),
+ target->backoff.times * polling_interval);
/* Tell GDB to halt the debugger. This allows the user to
* run monitor commands to handle the situation.
return retval;
}
/* Since we succeeded, we reset backoff count */
- if (backoff_times > 0)
- LOG_USER("Polling succeeded again");
- backoff_times = 0;
+ if (target->backoff.times > 0)
+ LOG_USER("Polling target %s succeeded again", target_name(target));
+ target->backoff.times = 0;
}
}
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- unsigned ms = 5000;
+ unsigned ms = DEFAULT_HALT_TIMEOUT;
if (1 == CMD_ARGC) {
int retval = parse_uint(CMD_ARGV[0], &ms);
if (ERROR_OK != retval)
return ERROR_COMMAND_SYNTAX_ERROR;
- /* convert seconds (given) to milliseconds (needed) */
- ms *= 1000;
}
struct target *target = get_current_target(CMD_CTX);
LOG_USER("requesting target halt and executing a soft reset");
- target->type->soft_reset_halt(target);
+ target_soft_reset_halt(target);
return ERROR_OK;
}
/* found */
break;
}
+
+ /* check for deprecated name */
+ if (target_types[x]->deprecated_name) {
+ if (0 == strcmp(cp, target_types[x]->deprecated_name)) {
+ /* found */
+ LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name);
+ break;
+ }
+ }
}
if (target_types[x] == NULL) {
Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp);
}
/* now - create the new target name command */
- const const struct command_registration target_subcommands[] = {
+ const struct command_registration target_subcommands[] = {
{
.chain = target_instance_command_handlers,
},
},
COMMAND_REGISTRATION_DONE
};
- const const struct command_registration target_commands[] = {
+ const struct command_registration target_commands[] = {
{
.name = cp,
.mode = COMMAND_ANY,
struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx != NULL);
- Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1);
+ Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1);
return JIM_OK;
}
.handler = handle_wait_halt_command,
.mode = COMMAND_EXEC,
.help = "wait up to the specified number of milliseconds "
- "(default 5) for a previously requested halt",
+ "(default 5000) for a previously requested halt",
.usage = "[milliseconds]",
},
{
.handler = handle_halt_command,
.mode = COMMAND_EXEC,
.help = "request target to halt, then wait up to the specified"
- "number of milliseconds (default 5) for it to complete",
+ "number of milliseconds (default 5000) for it to complete",
.usage = "[milliseconds]",
},
{