X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=5805d0c7c7b106177dc299b6ae343bf1ca408427;hp=ee65147c6d3ef98c2a9d45718128653ce309e8d4;hb=ccc2e3fe760a425f831b9e1f0e143d7d01d73a25;hpb=5ac8036b7fdaa32d44fb756f46f60d8de33e3a50 diff --git a/src/target/target.c b/src/target/target.c index ee65147c6d..5805d0c7c7 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2,9 +2,15 @@ * Copyright (C) 2005 by Dominic Rath * * Dominic.Rath@gmx.de * * * - * Copyright (C) 2007,2008 Øyvind Harboe * + * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * + * Copyright (C) 2008, Duane Ellis * + * openocd@duaneeellis.com * + * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * * 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 * @@ -156,12 +162,11 @@ const char *target_strerror_safe( int err ) } const Jim_Nvp nvp_target_event[] = { - { .value = TARGET_EVENT_OLD_pre_reset , .name = "old-pre_reset" }, { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" }, - { .value = TARGET_EVENT_OLD_post_reset , .name = "old-post_reset" }, { .value = TARGET_EVENT_OLD_pre_resume , .name = "old-pre_resume" }, + { .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" }, { .value = TARGET_EVENT_HALTED, .name = "halted" }, { .value = TARGET_EVENT_RESUMED, .name = "resumed" }, { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, @@ -411,102 +416,33 @@ int target_resume(struct target_s *target, int current, u32 address, int handle_ return retval; } -// Next patch - this turns into TCL... + int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode) { - int retval = ERROR_OK; - target_t *target; - - target = all_targets; - - target_all_handle_event( TARGET_EVENT_OLD_pre_reset ); - - if ((retval = jtag_init_reset(cmd_ctx)) != ERROR_OK) - return retval; - - keep_alive(); /* we might be running on a very slow JTAG clk */ - - /* First time this is executed after launching OpenOCD, it will read out - * the type of CPU, etc. and init Embedded ICE registers in host - * memory. - * - * It will also set up ICE registers in the target. - * - * However, if we assert TRST later, we need to set up the registers again. - * - * For the "reset halt/init" case we must only set up the registers here. - */ - if ((retval = target_examine()) != ERROR_OK) - return retval; - - keep_alive(); /* we might be running on a very slow JTAG clk */ - - target = all_targets; - while (target) - { - /* we have no idea what state the target is in, so we - * have to drop working areas - */ - target_free_all_working_areas_restore(target, 0); - target->reset_halt=((reset_mode==RESET_HALT)||(reset_mode==RESET_INIT)); - if ((retval = target->type->assert_reset(target))!=ERROR_OK) - return retval; - target = target->next; - } - - target = all_targets; - while (target) - { - if ((retval = target->type->deassert_reset(target))!=ERROR_OK) - return retval; - target = target->next; - } - - target = all_targets; - while (target) - { - /* We can fail to bring the target into the halted state, try after reset has been deasserted */ - if (target->reset_halt) - { - /* wait up to 1 second for halt. */ - target_wait_state(target, TARGET_HALTED, 1000); - if (target->state != TARGET_HALTED) - { - LOG_WARNING("Failed to reset target into halted mode - issuing halt"); - if ((retval = target->type->halt(target))!=ERROR_OK) - return retval; - } - } - - target = target->next; + char buf[100]; + int retval; + Jim_Nvp *n; + n = Jim_Nvp_value2name_simple( nvp_reset_modes, reset_mode ); + if( n->name == NULL ){ + LOG_ERROR("invalid reset mode"); + return ERROR_FAIL; } + sprintf( buf, "ocd_process_reset %s", n->name ); + retval = Jim_Eval( interp, buf ); - LOG_DEBUG("Waiting for halted stated as appropriate"); - - if ((reset_mode == RESET_HALT) || (reset_mode == RESET_INIT)) - { - target = all_targets; - while (target) - { - /* Wait for reset to complete, maximum 5 seconds. */ - if (((retval=target_wait_state(target, TARGET_HALTED, 5000)))==ERROR_OK) - { - if (reset_mode == RESET_INIT){ - target_handle_event( target, TARGET_EVENT_OLD_post_reset ); - } - - } - target = target->next; - } + if(retval != JIM_OK) { + Jim_PrintErrorMessage(interp); + return ERROR_FAIL; } /* We want any events to be processed before the prompt */ - target_call_timer_callbacks_now(); + retval = target_call_timer_callbacks_now(); return retval; } + static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical) { *physical = virtual; @@ -587,6 +523,7 @@ static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, int target_init(struct command_context_s *cmd_ctx) { target_t *target = all_targets; + int retval; while (target) { @@ -596,10 +533,10 @@ int target_init(struct command_context_s *cmd_ctx) target->type->examine = default_examine; } - if (target->type->init_target(cmd_ctx, target) != ERROR_OK) + if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK) { LOG_ERROR("target '%s' init failed", target->type->name); - exit(-1); + return retval; } /* Set up default functions if none are provided by target */ @@ -630,8 +567,10 @@ int target_init(struct command_context_s *cmd_ctx) if (all_targets) { - target_register_user_commands(cmd_ctx); - target_register_timer_callback(handle_target, 100, 1, NULL); + if((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK) + return retval; + if((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK) + return retval; } return ERROR_OK; @@ -758,6 +697,13 @@ int target_call_event_callbacks(target_t *target, enum target_event event) target_event_callback_t *callback = target_event_callbacks; target_event_callback_t *next_callback; + if (event == TARGET_EVENT_HALTED) + { + /* execute early halted first */ + target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED); + } + + LOG_DEBUG("target event %i (%s)", event, Jim_Nvp_value2name_simple( nvp_target_event, event )->name ); @@ -808,7 +754,11 @@ static int target_call_timer_callbacks_check_time(int checktime) } } else - target_unregister_timer_callback(callback->callback, callback->priv); + { + int retval; + if((retval = target_unregister_timer_callback(callback->callback, callback->priv)) != ERROR_OK) + return retval; + } } } @@ -826,7 +776,7 @@ int target_call_timer_callbacks(void) /* invoke periodic callbacks immediately */ int target_call_timer_callbacks_now(void) { - return target_call_timer_callbacks(); + return target_call_timer_callbacks_check_time(0); } int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area) @@ -903,8 +853,14 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t if (target->backup_working_area) { + int retval; new_wa->backup = malloc(new_wa->size); - target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup); + if((retval = target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup)) != ERROR_OK) + { + free(new_wa->backup); + free(new_wa); + return retval; + } } else { @@ -931,7 +887,11 @@ int target_free_working_area_restore(struct target_s *target, working_area_t *ar return ERROR_OK; if (restore&&target->backup_working_area) - target->type->write_memory(target, area->address, 4, area->size / 4, area->backup); + { + int retval; + if((retval = target->type->write_memory(target, area->address, 4, area->size / 4, area->backup)) != ERROR_OK) + return retval; + } area->free = 1; @@ -947,7 +907,10 @@ int target_free_working_area(struct target_s *target, working_area_t *area) return target_free_working_area_restore(target, area, 1); } -int target_free_all_working_areas_restore(struct target_s *target, int restore) +/* free resources and restore memory, if restoring memory fails, + * free up resources anyway + */ +void target_free_all_working_areas_restore(struct target_s *target, int restore) { working_area_t *c = target->working_areas; @@ -965,13 +928,11 @@ int target_free_all_working_areas_restore(struct target_s *target, int restore) } target->working_areas = NULL; - - return ERROR_OK; } -int target_free_all_working_areas(struct target_s *target) +void target_free_all_working_areas(struct target_s *target) { - return target_free_all_working_areas_restore(target, 1); + target_free_all_working_areas_restore(target, 1); } int target_register_commands(struct command_context_s *cmd_ctx) @@ -1165,7 +1126,7 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* } if ((retval = target->type->checksum_memory(target, address, - size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + size, &checksum)) != ERROR_OK) { buffer = malloc(size); if (buffer == NULL) @@ -1339,7 +1300,7 @@ int target_write_u8(struct target_s *target, u32 address, u8 value) LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value); - if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK) + if ((retval = target->type->write_memory(target, address, 1, 1, &value)) != ERROR_OK) { LOG_DEBUG("failed: %i", retval); } @@ -1349,6 +1310,7 @@ int target_write_u8(struct target_s *target, u32 address, u8 value) int target_register_user_commands(struct command_context_s *cmd_ctx) { + int retval = ERROR_OK; register_command(cmd_ctx, NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL); register_command(cmd_ctx, NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state"); register_command(cmd_ctx, NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]"); @@ -1375,10 +1337,13 @@ int target_register_user_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image
"); register_command(cmd_ctx, NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image [offset] [type]"); - target_request_register_commands(cmd_ctx); - trace_register_commands(cmd_ctx); + if((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK) + return retval; + if((retval = trace_register_commands(cmd_ctx)) != ERROR_OK) + return retval; + - return ERROR_OK; + return retval; } int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -1439,6 +1404,7 @@ int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char ** int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + int retval = ERROR_OK; target_t *target = NULL; if ((argc < 4) || (argc > 5)) @@ -1474,13 +1440,14 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch return ERROR_COMMAND_SYNTAX_ERROR; } - return ERROR_OK; + return retval; } /* process target state changes */ int handle_target(void *priv) { + int retval = ERROR_OK; target_t *target = all_targets; while (target) @@ -1488,13 +1455,14 @@ int handle_target(void *priv) if (target_continous_poll) { /* polling may fail silently until the target has been examined */ - target_poll(target); + if((retval = target_poll(target)) != ERROR_OK) + return retval; } target = target->next; } - return ERROR_OK; + return retval; } int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -1577,11 +1545,6 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args if (reg->valid == 0) { reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); - if (arch_type == NULL) - { - LOG_ERROR("BUG: encountered unregistered arch type"); - return ERROR_OK; - } arch_type->get(reg); } value = buf_to_str(reg->value, reg->size, 16); @@ -1597,12 +1560,6 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0); reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); - if (arch_type == NULL) - { - LOG_ERROR("BUG: encountered unregistered arch type"); - return ERROR_OK; - } - arch_type->set(reg, buf); value = buf_to_str(reg->value, reg->size, 16); @@ -1622,14 +1579,18 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { + int retval = ERROR_OK; target_t *target = get_current_target(cmd_ctx); if (argc == 0) { - target_poll(target); - target_arch_state(target); + if((retval = target_poll(target)) != ERROR_OK) + return retval; + if((retval = target_arch_state(target)) != ERROR_OK) + return retval; + } - else + else if (argc==1) { if (strcmp(args[0], "on") == 0) { @@ -1643,10 +1604,13 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg { command_print(cmd_ctx, "arg is \"on\" or \"off\""); } + } else + { + return ERROR_COMMAND_SYNTAX_ERROR; } - return ERROR_OK; + return retval; } int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -1749,6 +1713,7 @@ int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **ar return target_process_reset(cmd_ctx, reset_mode); } + int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { int retval; @@ -1913,6 +1878,8 @@ int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, default: return ERROR_OK; } + keep_alive(); + if (retval!=ERROR_OK) { return retval; @@ -1931,7 +1898,7 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char u32 min_address=0; u32 max_address=0xffffffff; int i; - int retval; + int retval, retvaltemp; image_t image; @@ -2031,7 +1998,12 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char free(buffer); } - duration_stop_measure(&duration, &duration_text); + if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) + { + image_close(&image); + return retvaltemp; + } + if (retval==ERROR_OK) { command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text); @@ -2051,7 +2023,7 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char u32 address; u32 size; u8 buffer[560]; - int retval=ERROR_OK; + int retval=ERROR_OK, retvaltemp; duration_t duration; char *duration_text; @@ -2101,9 +2073,12 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char address += this_run_size; } - fileio_close(&fileio); + if((retvaltemp = fileio_close(&fileio)) != ERROR_OK) + return retvaltemp; + + if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) + return retvaltemp; - duration_stop_measure(&duration, &duration_text); if (retval==ERROR_OK) { command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text); @@ -2119,7 +2094,7 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch u32 buf_cnt; u32 image_size; int i; - int retval; + int retval, retvaltemp; u32 checksum = 0; u32 mem_checksum = 0; @@ -2218,6 +2193,10 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch retval=ERROR_FAIL; goto done; } + if ((t%16384)==0) + { + keep_alive(); + } } } @@ -2228,7 +2207,13 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch image_size += buf_cnt; } done: - duration_stop_measure(&duration, &duration_text); + + if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) + { + image_close(&image); + return retvaltemp; + } + if (retval==ERROR_OK) { command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text); @@ -2554,7 +2539,11 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char ** } else if (target->state == TARGET_RUNNING) { // We want to quickly sample the PC. - target_halt(target); + if((retval = target_halt(target)) != ERROR_OK) + { + free(samples); + return retval; + } } else { command_print(cmd_ctx, "Target not halted or running"); @@ -2570,12 +2559,20 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char ** if ((numSamples>=maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { command_print(cmd_ctx, "Profiling completed. %d samples.", numSamples); - target_poll(target); + if((retval = target_poll(target)) != ERROR_OK) + { + free(samples); + return retval; + } if (target->state == TARGET_HALTED) { target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */ } - target_poll(target); + if((retval = target_poll(target)) != ERROR_OK) + { + free(samples); + return retval; + } writeGmon(samples, numSamples, args[1]); command_print(cmd_ctx, "Wrote %s", args[1]); break; @@ -2985,7 +2982,10 @@ target_handle_event( target_t *target, enum target_event e ) e, Jim_Nvp_value2name_simple( nvp_target_event, e )->name, Jim_GetString( teap->body, NULL ) ); - Jim_EvalObj( interp, teap->body ); + if (Jim_EvalObj( interp, teap->body )!=JIM_OK) + { + Jim_PrintErrorMessage(interp); + } } teap = teap->next; } @@ -2999,7 +2999,6 @@ target_handle_event( target_t *target, enum target_event e ) enum target_cfg_param { TCFG_TYPE, TCFG_EVENT, - TCFG_RESET, TCFG_WORK_AREA_VIRT, TCFG_WORK_AREA_PHYS, TCFG_WORK_AREA_SIZE, @@ -3013,7 +3012,6 @@ enum target_cfg_param { static Jim_Nvp nvp_config_opts[] = { { .name = "-type", .value = TCFG_TYPE }, { .name = "-event", .value = TCFG_EVENT }, - { .name = "-reset", .value = TCFG_RESET }, { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS }, { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE }, @@ -3038,7 +3036,7 @@ target_configure( Jim_GetOptInfo *goi, /* parse config or cget options ... */ - while( goi->argc ){ + while( goi->argc > 0 ){ Jim_SetEmptyResult( goi->interp ); //Jim_GetOpt_Debug( goi ); @@ -3090,7 +3088,7 @@ target_configure( Jim_GetOptInfo *goi, } if( goi->isconfigure ){ - if( goi->argc == 0 ){ + if( goi->argc != 1 ){ Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; } @@ -3283,8 +3281,8 @@ target_configure( Jim_GetOptInfo *goi, /* loop for more e*/ break; } - } - /* done - we return */ + } /* while( goi->argc ) */ + /* done - we return */ return JIM_OK; } @@ -3320,6 +3318,7 @@ tcl_target_func( Jim_Interp *interp, TS_CMD_WAITSTATE, TS_CMD_EVENTLIST, TS_CMD_CURSTATE, + TS_CMD_INVOKE_EVENT, }; static const Jim_Nvp target_options[] = { @@ -3341,6 +3340,7 @@ tcl_target_func( Jim_Interp *interp, { .name = "arp_reset", .value = TS_CMD_RESET }, { .name = "arp_halt", .value = TS_CMD_HALT }, { .name = "arp_waitstate", .value = TS_CMD_WAITSTATE }, + { .name = "invoke-event", .value = TS_CMD_INVOKE_EVENT }, { .name = NULL, .value = -1 }, }; @@ -3553,7 +3553,7 @@ tcl_target_func( Jim_Interp *interp, break; case TS_CMD_EXAMINE: if( goi.argc ){ - Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]"); + Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]"); return JIM_ERR; } e = target->type->examine( target ); @@ -3564,7 +3564,7 @@ tcl_target_func( Jim_Interp *interp, return JIM_OK; case TS_CMD_POLL: if( goi.argc ){ - Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]"); + Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]"); return JIM_ERR; } if( !(target->type->examined) ){ @@ -3580,8 +3580,8 @@ tcl_target_func( Jim_Interp *interp, } break; case TS_CMD_RESET: - if( goi.argc != 1 ){ - Jim_WrongNumArgs( interp, 1, argv, "reset t|f|assert|deassert"); + if( goi.argc != 2 ){ + Jim_WrongNumArgs( interp, 2, argv, "t|f|assert|deassert BOOL"); return JIM_ERR; } e = Jim_GetOpt_Nvp( &goi, nvp_assert, &n ); @@ -3589,6 +3589,13 @@ tcl_target_func( Jim_Interp *interp, Jim_GetOpt_NvpUnknown( &goi, nvp_assert, 1 ); return e; } + // the halt or not param + e = Jim_GetOpt_Wide( &goi, &a); + if( e != JIM_OK ){ + return e; + } + // determine if we should halt or not. + target->reset_halt = !!a; // When this happens - all workareas are invalid. target_free_all_working_areas_restore(target, 0); @@ -3622,12 +3629,12 @@ tcl_target_func( Jim_Interp *interp, return e; } e = target_wait_state( target, n->value, a ); - if( e == ERROR_OK ){ + if( e != ERROR_OK ){ Jim_SetResult_sprintf( goi.interp, - "target: %s wait %s fails %d", + "target: %s wait %s fails (%d) %s", target->cmd_name, n->name, - target_strerror_safe(e) ); + e, target_strerror_safe(e) ); return JIM_ERR; } else { return JIM_OK; @@ -3662,6 +3669,18 @@ tcl_target_func( Jim_Interp *interp, Jim_SetResultString( goi.interp, Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name,-1); return JIM_OK; + case TS_CMD_INVOKE_EVENT: + if( goi.argc != 1 ){ + Jim_SetResult_sprintf( goi.interp, "%s ?EVENTNAME?",n->name); + return JIM_ERR; + } + e = Jim_GetOpt_Nvp( &goi, nvp_target_event, &n ); + if( e != JIM_OK ){ + Jim_GetOpt_NvpUnknown( &goi, nvp_target_event, 1 ); + return e; + } + target_handle_event( target, n->value ); + return JIM_OK; } return JIM_ERR; } @@ -4005,13 +4024,6 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) Jim_NewIntObj( goi.interp, max_target_number())); return JIM_OK; } -} - - -/* - * Local Variables: *** - * c-basic-offset: 4 *** - * tab-width: 4 *** - * End: *** - */ + return JIM_ERR; +}