reset cleanup
[fw/openocd] / src / target / target.c
index 08a0505f2331b003aa4423e76cd2debb53740750..f843a6ed51bffd25e4f1d706f5d6d6c1d71db579 100644 (file)
@@ -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     *
@@ -160,8 +166,9 @@ const Jim_Nvp nvp_target_event[] = {
        { .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" },
@@ -188,7 +195,7 @@ const Jim_Nvp nvp_target_event[] = {
 
        { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
        { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-end" },
-       
+
 
        { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
        { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },
@@ -342,7 +349,7 @@ target_t* get_target_by_num(int num)
        while (target){
                if( target->target_number == num ){
                        return target;
-               } 
+               }
                target = target->next;
        }
 
@@ -411,102 +418,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 +525,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)
        {
@@ -630,8 +569,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,8 +699,15 @@ 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;
 
-       LOG_DEBUG("target event %i (%s)", 
-                         event, 
+       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 );
 
        target_handle_event( target, event );
@@ -808,7 +756,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 +778,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 +855,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 +889,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 +909,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 +930,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)
@@ -1000,7 +963,7 @@ int target_arch_state(struct target_s *target)
                return ERROR_OK;
        }
 
-       LOG_USER("target state: %s", 
+       LOG_USER("target state: %s",
                 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
 
        if (target->state!=TARGET_HALTED)
@@ -1165,7 +1128,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)
@@ -1349,6 +1312,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 +1339,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 <file> <address> <size>");
        register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [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)
@@ -1394,18 +1361,18 @@ int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **
                        if( 0 == strcmp( args[0], target->cmd_name ) ){
                                /* MATCH */
                                goto Match;
-                       } 
+                       }
                  }
                }
                /* no match, try as number */
-               
+
                int num = strtoul(args[0], &cp, 0 );
                if( *cp != 0 ){
                        /* then it was not a number */
                        command_print( cmd_ctx, "Target: %s unknown, try one of:\n", args[0] );
                        goto DumpTargets;
                }
-                       
+
                target = get_target_by_num( num );
                if( target == NULL ){
                        command_print(cmd_ctx,"Target: %s is unknown, try one of:\n", args[0] );
@@ -1422,11 +1389,11 @@ int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **
        while (target)
        {
                /* XX: abcdefghij abcdefghij abcdefghij abcdefghij */
-               command_print(cmd_ctx, "%2d: %-10s %-10s %-10s %8d %s", 
+               command_print(cmd_ctx, "%2d: %-10s %-10s %-10s %8d %s",
                                          target->target_number,
                                          target->cmd_name,
-                                         target->type->name, 
-                                         Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness )->name, 
+                                         target->type->name,
+                                         Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness )->name,
                                          target->chain_position,
                                          Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
                target = target->next;
@@ -1439,6 +1406,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 +1442,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 +1457,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 +1547,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 +1562,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 +1581,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 +1606,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)
@@ -1689,14 +1655,14 @@ int target_wait_state(target_t *target, enum target_state state, int ms)
                if (once)
                {
                        once=0;
-                       LOG_DEBUG("waiting for target %s...", 
+                       LOG_DEBUG("waiting for target %s...",
                              Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
                }
 
                gettimeofday(&now, NULL);
                if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
                {
-                       LOG_ERROR("timed out while waiting for target %s", 
+                       LOG_ERROR("timed out while waiting for target %s",
                              Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
                        return ERROR_FAIL;
                }
@@ -1749,6 +1715,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 +1880,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 +1900,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 +2000,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 +2025,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 +2075,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 +2096,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 +2195,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 +2209,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 +2541,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 +2561,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;
@@ -2801,7 +2800,7 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        command_context_t *context;
        target_t *target;
-       
+
        context = Jim_GetAssocData(interp, "context");
        if (context == NULL){
                LOG_ERROR("array2mem: no command context");
@@ -2812,10 +2811,10 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                LOG_ERROR("array2mem: no current target");
                return JIM_ERR;
        }
-       
+
        return target_array2mem( interp,target, argc, argv );
 }
-                          
+
 
 static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
 {
@@ -2955,7 +2954,7 @@ target_all_handle_event( enum target_event e )
        target_t *target;
 
 
-       LOG_DEBUG( "**all*targets: event: %d, %s", 
+       LOG_DEBUG( "**all*targets: event: %d, %s",
                   e,
                   Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
 
@@ -2985,12 +2984,15 @@ 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;
        }
        if( !done ){
-               LOG_DEBUG( "event: %d %s - no action", 
+               LOG_DEBUG( "event: %d %s - no action",
                                   e,
                                   Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
        }
@@ -2998,8 +3000,7 @@ target_handle_event( target_t *target, enum target_event e )
 
 enum target_cfg_param {
        TCFG_TYPE,
-       TCFG_EVENT, 
-       TCFG_RESET,
+       TCFG_EVENT,
        TCFG_WORK_AREA_VIRT,
        TCFG_WORK_AREA_PHYS,
        TCFG_WORK_AREA_SIZE,
@@ -3013,7 +3014,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 },
@@ -3021,10 +3021,10 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-endian" ,          .value = TCFG_ENDIAN },
        { .name = "-variant",          .value = TCFG_VARIANT },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
-       
+
        { .name = NULL, .value = -1 }
 };
-         
+
 
 static int
 target_configure( Jim_GetOptInfo *goi,
@@ -3038,7 +3038,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,10 +3090,10 @@ 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;
-                               }  
+                               }
                        } else {
                                if( goi->argc != 0 ){
                                        Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
@@ -3101,10 +3101,10 @@ target_configure( Jim_GetOptInfo *goi,
                                }
                        }
 
-       
-                       { 
+
+                       {
                                target_event_action_t *teap;
-                               
+
                                teap = target->event_action;
                                /* replace existing? */
                                while( teap ){
@@ -3113,7 +3113,7 @@ target_configure( Jim_GetOptInfo *goi,
                                        }
                                        teap = teap->next;
                                }
-                               
+
                                if( goi->isconfigure ){
                                        if( teap == NULL ){
                                                /* create new */
@@ -3126,7 +3126,7 @@ target_configure( Jim_GetOptInfo *goi,
                                        }
                                        teap->body  = Jim_DuplicateObj( goi->interp, o );
                                        /*
-                                        * FIXME: 
+                                        * FIXME:
                                         *     Tcl/TK - "tk events" have a nice feature.
                                         *     See the "BIND" command.
                                         *    We should support that here.
@@ -3153,32 +3153,6 @@ target_configure( Jim_GetOptInfo *goi,
                        /* loop for more */
                        break;
 
-               case TCFG_RESET:
-                       if( goi->isconfigure ){
-                               e = Jim_GetOpt_Nvp( goi, nvp_reset_modes, &n );
-                               if( e != JIM_OK ){
-                                       Jim_GetOpt_NvpUnknown( goi, nvp_reset_modes, 1 );
-                                       return e;
-                               }
-                               if( n->value == RESET_UNKNOWN ){
-                                       Jim_SetResultString( interp, "'unknown' is not a valid selection",-1);
-                                       return JIM_ERR;
-                               }
-                               target->reset_mode = n->value;
-                       } else {
-                               if( goi->argc != 0 ){
-                                       goto no_params;
-                               }
-                       }
-                       n = Jim_Nvp_value2name_simple( nvp_reset_modes, target->reset_mode );
-                       if( n->name == NULL ){
-                               target->reset_mode = RESET_HALT;
-                               n = Jim_Nvp_value2name_simple( nvp_reset_modes, target->reset_mode );
-                       }
-                       Jim_SetResultString( goi->interp, n->name, -1 );
-                       /* loop for more */
-                       break;
-                       
                case TCFG_WORK_AREA_VIRT:
                        if( goi->isconfigure ){
                                target_free_all_working_areas(target);
@@ -3191,11 +3165,11 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_virt ) );
                        /* loop for more */
                        break;
-                               
+
                case TCFG_WORK_AREA_PHYS:
                        if( goi->isconfigure ){
                                target_free_all_working_areas(target);
@@ -3208,7 +3182,7 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_phys ) );
                        /* loop for more */
                        break;
@@ -3225,7 +3199,7 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_size ) );
                        /* loop for more */
                        break;
@@ -3243,7 +3217,7 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_size ) );
                        /* loop for more e*/
                        break;
@@ -3265,7 +3239,7 @@ target_configure( Jim_GetOptInfo *goi,
                        if( n->name == NULL ){
                                target->endianness = TARGET_LITTLE_ENDIAN;
                                n = Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness );
-                       } 
+                       }
                        Jim_SetResultString( goi->interp, n->name, -1 );
                        /* loop for more */
                        break;
@@ -3287,7 +3261,7 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResultString( goi->interp, target->variant,-1 );
                        /* loop for more */
                        break;
@@ -3304,13 +3278,13 @@ target_configure( Jim_GetOptInfo *goi,
                                if( goi->argc != 0 ){
                                        goto no_params;
                                }
-                       } 
+                       }
                        Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->chain_position ) );
                        /* loop for more e*/
                        break;
                }
-       }
-       /* done - we return */
+       } /* while( goi->argc ) */
+               /* done - we return */
        return JIM_OK;
 }
 
@@ -3318,7 +3292,7 @@ target_configure( Jim_GetOptInfo *goi,
 /** this is the 'tcl' handler for the target specific command */
 static int
 tcl_target_func( Jim_Interp *interp,
-                                int argc, 
+                                int argc,
                                 Jim_Obj *const *argv )
 {
        Jim_GetOptInfo goi;
@@ -3334,20 +3308,21 @@ tcl_target_func( Jim_Interp *interp,
        enum {
                TS_CMD_CONFIGURE,
                TS_CMD_CGET,
-               
+
                TS_CMD_MWW, TS_CMD_MWH, TS_CMD_MWB,
                TS_CMD_MDW, TS_CMD_MDH, TS_CMD_MDB,
                TS_CMD_MRW, TS_CMD_MRH, TS_CMD_MRB,
                TS_CMD_MEM2ARRAY, TS_CMD_ARRAY2MEM,
-               TS_CMD_EXAMINE, 
+               TS_CMD_EXAMINE,
                TS_CMD_POLL,
                TS_CMD_RESET,
                TS_CMD_HALT,
                TS_CMD_WAITSTATE,
                TS_CMD_EVENTLIST,
                TS_CMD_CURSTATE,
+               TS_CMD_INVOKE_EVENT,
        };
-       
+
        static const Jim_Nvp target_options[] = {
                { .name = "configure", .value = TS_CMD_CONFIGURE },
                { .name = "cget", .value = TS_CMD_CGET },
@@ -3367,6 +3342,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 },
        };
@@ -3412,7 +3388,7 @@ tcl_target_func( Jim_Interp *interp,
                 * argv[2] = data
                 * argv[3] = optional count.
                 */
-                 
+
                if( (goi.argc == 3) || (goi.argc == 4) ){
                        /* all is well */
                } else {
@@ -3420,7 +3396,7 @@ tcl_target_func( Jim_Interp *interp,
                        Jim_SetResult_sprintf( goi.interp, "expected: %s ADDR DATA [COUNT]", n->name );
                        return JIM_ERR;
                }
-               
+
                e = Jim_GetOpt_Wide( &goi, &a );
                if( e != JIM_OK ){
                        goto mwx_error;
@@ -3438,7 +3414,7 @@ tcl_target_func( Jim_Interp *interp,
                } else {
                        c = 1;
                }
-                       
+
                switch( n->value ){
                case TS_CMD_MWW:
                        target_buffer_set_u32( target, target_buf, b );
@@ -3515,7 +3491,7 @@ tcl_target_func( Jim_Interp *interp,
                                Jim_SetResult_sprintf( interp, "error reading target @ 0x%08lx", (int)(a) );
                                return JIM_ERR;
                        }
-                       
+
                        Jim_fprintf( interp, interp->cookie_stdout, "0x%08x ", (int)(a) );
                        switch( b ){
                        case 4:
@@ -3549,7 +3525,7 @@ tcl_target_func( Jim_Interp *interp,
                        }
                        /* ascii-ify the bytes */
                        for( x = 0 ; x < y ; x++ ){
-                               if( (target_buf[x] >= 0x20) && 
+                               if( (target_buf[x] >= 0x20) &&
                                        (target_buf[x] <= 0x7e) ){
                                        /* good */
                                } else {
@@ -3579,7 +3555,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 );
@@ -3590,7 +3566,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) ){
@@ -3606,8 +3582,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 );
@@ -3615,6 +3591,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);
 
@@ -3633,7 +3616,7 @@ tcl_target_func( Jim_Interp *interp,
                target->type->halt( target );
                return JIM_OK;
        case TS_CMD_WAITSTATE:
-               // params:  <name>  statename timeoutmsecs 
+               // params:  <name>  statename timeoutmsecs
                if( goi.argc != 2 ){
                        Jim_SetResult_sprintf( goi.interp, "%s STATENAME TIMEOUTMSECS", n->name );
                        return JIM_ERR;
@@ -3648,12 +3631,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;
@@ -3666,12 +3649,12 @@ tcl_target_func( Jim_Interp *interp,
                        target_event_action_t *teap;
                        teap = target->event_action;
                        command_print( cmd_ctx, "Event actions for target (%d) %s\n",
-                                                  target->target_number, 
+                                                  target->target_number,
                                                   target->cmd_name );
                        command_print( cmd_ctx, "%-25s | Body", "Event");
                        command_print( cmd_ctx, "------------------------- | ----------------------------------------");
                        while( teap ){
-                               command_print( cmd_ctx, 
+                               command_print( cmd_ctx,
                                                           "%-25s | %s",
                                                           Jim_Nvp_value2name_simple( nvp_target_event, teap->event )->name,
                                                           Jim_GetString( teap->body, NULL ) );
@@ -3685,9 +3668,21 @@ tcl_target_func( Jim_Interp *interp,
                        Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]");
                        return JIM_ERR;
                }
-               Jim_SetResultString( goi.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;
 }
@@ -3695,8 +3690,8 @@ tcl_target_func( Jim_Interp *interp,
 
 static int
 target_create( Jim_GetOptInfo *goi )
-{      
-       
+{
+
        Jim_Obj *new_cmd;
        Jim_Cmd *cmd;
        const char *cp;
@@ -3721,7 +3716,7 @@ target_create( Jim_GetOptInfo *goi )
                Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
                return JIM_ERR;
        }
-       
+
        /* TYPE */
        e = Jim_GetOpt_String( goi, &cp2, NULL );
        cp = cp2;
@@ -3736,12 +3731,12 @@ target_create( Jim_GetOptInfo *goi )
                Jim_SetResult_sprintf( goi->interp, "Unknown target type %s, try one of ", cp );
                for( x = 0 ; target_types[x] ; x++ ){
                        if( target_types[x+1] ){
-                               Jim_AppendStrings( goi->interp, 
+                               Jim_AppendStrings( goi->interp,
                                                                   Jim_GetResult(goi->interp),
                                                                   target_types[x]->name,
                                                                   ", ", NULL);
                        } else {
-                               Jim_AppendStrings( goi->interp, 
+                               Jim_AppendStrings( goi->interp,
                                                                   Jim_GetResult(goi->interp),
                                                                   " or ",
                                                                   target_types[x]->name,NULL );
@@ -3750,7 +3745,7 @@ target_create( Jim_GetOptInfo *goi )
                return JIM_ERR;
        }
 
-               
+
        /* Create it */
        target = calloc(1,sizeof(target_t));
        /* set target number */
@@ -3760,7 +3755,7 @@ target_create( Jim_GetOptInfo *goi )
        target->type = (target_type_t*)calloc(1,sizeof(target_type_t));
 
        memcpy( target->type, target_types[x], sizeof(target_type_t));
-       
+
        /* will be set by "-endian" */
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
@@ -3768,7 +3763,7 @@ target_create( Jim_GetOptInfo *goi )
        target->working_area_size   = 0x0;
        target->working_areas       = NULL;
        target->backup_working_area = 0;
-       
+
        target->state               = TARGET_UNKNOWN;
        target->debug_reason        = DBG_REASON_UNDEFINED;
        target->reg_cache           = NULL;
@@ -3776,7 +3771,7 @@ target_create( Jim_GetOptInfo *goi )
        target->watchpoints         = NULL;
        target->next                = NULL;
        target->arch_info           = NULL;
-       
+
        /* initialize trace information */
        target->trace_info = malloc(sizeof(trace_t));
        target->trace_info->num_trace_points         = 0;
@@ -3786,7 +3781,7 @@ target_create( Jim_GetOptInfo *goi )
        target->trace_info->trace_history            = NULL;
        target->trace_info->trace_history_pos        = 0;
        target->trace_info->trace_history_overflowed = 0;
-       
+
        target->dbgmsg          = NULL;
        target->dbg_msg_enabled = 0;
 
@@ -3858,9 +3853,9 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                TG_CMD_COUNT,
        };
        const char *target_cmds[] = {
-               "create", "types", "names", "current", "number", 
+               "create", "types", "names", "current", "number",
                "count",
-               NULL // terminate 
+               NULL // terminate
        };
 
        LOG_DEBUG("Target command params:");
@@ -3887,9 +3882,9 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                /* YES IT IS OLD SYNTAX */
                Jim_Obj *new_argv[10];
                int      new_argc;
-               
-               /* target_old_syntax 
-                * 
+
+               /* target_old_syntax
+                *
                 * argv[0] typename (above)
                 * argv[1] endian
                 * argv[2] reset method, deprecated/ignored
@@ -3936,14 +3931,14 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                 *   argv[8] = -variant
                 *   argv[9] = "somestring"
                 */
-               
+
                /* don't let these be released */
                for( x = 0 ; x < new_argc ; x++ ){
                        Jim_IncrRefCount( new_argv[x]);
                }
                /* call our self */
                LOG_DEBUG("Target OLD SYNTAX - converted to new syntax");
-               
+
                r = jim_target( goi.interp, new_argc, new_argv );
 
                /* release? these items */
@@ -3995,7 +3990,7 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                                                                   Jim_NewStringObj( goi.interp, target->cmd_name, -1 ) );
                        target = target->next;
                }
-               return JIM_OK;          
+               return JIM_OK;
        case TG_CMD_CREATE:
                if( goi.argc < 3 ){
                        Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
@@ -4027,17 +4022,10 @@ jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                        Jim_WrongNumArgs( goi.interp, 0, goi.argv, "<no parameters>");
                        return JIM_ERR;
                }
-               Jim_SetResult( goi.interp, 
+               Jim_SetResult( goi.interp,
                                           Jim_NewIntObj( goi.interp, max_target_number()));
                return JIM_OK;
        }
-}
-
-
 
-/*
- * Local Variables: ***
- * c-basic-offset: 4 ***
- * tab-width: 4 ***
- * End: ***
- */
+       return JIM_ERR;
+}