- cleaned up str7, str9 and stm32 flash drivers
[fw/openocd] / src / target / target.c
index 376fc52f5ffd1d54182b33bbbe378e20ef0fdffc..f471167b3197675d332b3322e7758a78c8f73370 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "replacements.h"
 #include "target.h"
+#include "target_request.h"
 
 #include "log.h"
 #include "configuration.h"
@@ -31,6 +32,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <inttypes.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -43,6 +45,7 @@
 #include <time_support.h>
 
 #include <fileio.h>
+#include <image.h>
 
 int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
 
@@ -79,6 +82,8 @@ extern target_type_t arm9tdmi_target;
 extern target_type_t arm920t_target;
 extern target_type_t arm966e_target;
 extern target_type_t arm926ejs_target;
+extern target_type_t xscale_target;
+extern target_type_t cortexm3_target;
 
 target_type_t *target_types[] =
 {
@@ -88,6 +93,8 @@ target_type_t *target_types[] =
        &arm720t_target,
        &arm966e_target,
        &arm926ejs_target,
+       &xscale_target,
+       &cortexm3_target,
        NULL,
 };
 
@@ -245,7 +252,23 @@ int target_process_reset(struct command_context_s *cmd_ctx)
 {
        int retval = ERROR_OK;
        target_t *target;
-        
+       
+       /* prepare reset_halt where necessary */
+       target = targets;
+       while (target)
+       {
+               switch (target->reset_mode)
+               {
+                       case RESET_HALT:
+                       case RESET_INIT:
+                               target->type->prepare_reset_halt(target);
+                               break;
+                       default:
+                               break;
+               }
+               target = target->next;
+       }
+       
        target = targets;
        while (target)
        {
@@ -631,6 +654,7 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff
        {
                if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
                        return retval;
+               return ERROR_OK;
        }
        
        /* handle unaligned head bytes */
@@ -689,6 +713,7 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
        {
                if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
                        return retval;
+               return ERROR_OK;
        }
        
        /* handle unaligned head bytes */
@@ -727,60 +752,107 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
        return ERROR_OK;
 }
 
-void target_read_u32(struct target_s *target, u32 address, u32 *value)
+int target_read_u32(struct target_s *target, u32 address, u32 *value)
 {
        u8 value_buf[4];
+
+       int retval = target->type->read_memory(target, address, 4, 1, value_buf);
        
-       target->type->read_memory(target, address, 4, 1, value_buf);
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u32(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
        
-       *value = target_buffer_get_u32(target, value_buf);
-
-       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+       return retval;
 }
 
-void target_read_u16(struct target_s *target, u32 address, u16 *value)
+int target_read_u16(struct target_s *target, u32 address, u16 *value)
 {
        u8 value_buf[2];
        
-       target->type->read_memory(target, address, 2, 1, value_buf);
+       int retval = target->type->read_memory(target, address, 2, 1, value_buf);
        
-       *value = target_buffer_get_u16(target, value_buf);
-
-       DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u16(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
 }
 
-void target_read_u8(struct target_s *target, u32 address, u8 *value)
+int target_read_u8(struct target_s *target, u32 address, u8 *value)
 {
-       target->type->read_memory(target, address, 1, 1, value);
+       int retval = target->type->read_memory(target, address, 1, 1, value);
 
-       DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+       if (retval == ERROR_OK)
+       {
+               DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
 }
 
-void target_write_u32(struct target_s *target, u32 address, u32 value)
+int target_write_u32(struct target_s *target, u32 address, u32 value)
 {
+       int retval;
        u8 value_buf[4];
 
        DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
        target_buffer_set_u32(target, value_buf, value);        
-       target->type->write_memory(target, address, 4, 1, value_buf);
+       if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
-void target_write_u16(struct target_s *target, u32 address, u16 value)
+int target_write_u16(struct target_s *target, u32 address, u16 value)
 {
+       int retval;
        u8 value_buf[2];
        
        DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
        target_buffer_set_u16(target, value_buf, value);        
-       target->type->write_memory(target, address, 2, 1, value_buf);
+       if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
-void target_write_u8(struct target_s *target, u32 address, u8 value)
+int target_write_u8(struct target_s *target, u32 address, u8 value)
 {
+       int retval;
+       
        DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
 
-       target->type->read_memory(target, address, 1, 1, &value);
+       if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
 int target_register_user_commands(struct command_context_s *cmd_ctx)
@@ -790,7 +862,7 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
        register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
        register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
-       register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction");
+       register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
        register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");
        register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
 
@@ -807,11 +879,14 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");    
        register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
        
-       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex']");
+       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
        register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
        register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
        register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
        
+       target_request_register_commands(cmd_ctx);
+       trace_register_commands(cmd_ctx);
+       
        return ERROR_OK;
 }
 
@@ -929,6 +1004,18 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a
                                (*last_target_p)->next = NULL;
                                (*last_target_p)->arch_info = NULL;
                                
+                               /* initialize trace information */
+                               (*last_target_p)->trace_info = malloc(sizeof(trace_t));
+                               (*last_target_p)->trace_info->num_trace_points = 0;
+                               (*last_target_p)->trace_info->trace_points_size = 0;
+                               (*last_target_p)->trace_info->trace_points = NULL;
+                               (*last_target_p)->trace_info->trace_history_size = 0;
+                               (*last_target_p)->trace_info->trace_history = NULL;
+                               (*last_target_p)->trace_info->trace_history_pos = 0;
+                               (*last_target_p)->trace_info->trace_history_overflowed = 0;
+                               
+                               (*last_target_p)->dbgmsg = NULL;
+                               
                                (*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
                                
                                found = 1;
@@ -1588,61 +1675,70 @@ int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 
 int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       u32 address;
        u8 *buffer;
        u32 buf_cnt;
-       u32 binary_size;
-       
-       fileio_t file;
-       enum fileio_pri_type pri_type = FILEIO_IMAGE;
-       fileio_image_t image_info;
-       enum fileio_sec_type sec_type;
+       u32 image_size;
+       int i;
+       int retval;
+
+       image_t image;  
        
        duration_t duration;
        char *duration_text;
        
        target_t *target = get_current_target(cmd_ctx);
 
-       if (argc < 2)
+       if (argc < 1)
        {
-               command_print(cmd_ctx, "usage: load_image <filename> <address> [type]");
+               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
                return ERROR_OK;
        }
        
-       memset(&file, 0, sizeof(fileio_t));
-       fileio_identify_image_type(&sec_type, (argc == 3) ? args[2] : NULL);
-
-       image_info.base_address = strtoul(args[1], NULL, 0);
-       image_info.has_start_address = 0;
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
+       {
+               image.base_address_set = 1;
+               image.base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               image.base_address_set = 0;
+       }
        
-       buffer = malloc(128 * 1024);
+       image.start_address_set = 0;
 
        duration_start_measure(&duration);
        
-       if (fileio_open(&file, args[0], FILEIO_READ, 
-               pri_type, &image_info, sec_type) != ERROR_OK)
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
        {
-               command_print(cmd_ctx, "load_image error: %s", file.error_str);
+               command_print(cmd_ctx, "load_image error: %s", image.error_str);
                return ERROR_OK;
        }
        
-       binary_size = file.size;
-       address = image_info.base_address;
-       while ((binary_size > 0) &&
-               (fileio_read(&file, 128 * 1024, buffer, &buf_cnt) == ERROR_OK))
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
        {
-               target_write_buffer(target, address, buf_cnt, buffer);
-               address += buf_cnt;
-               binary_size -= buf_cnt;
+               buffer = malloc(image.sections[i].size);
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, download aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+               image_size += buf_cnt;
+               command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
+               
+               free(buffer);
        }
 
-       free(buffer);
-       
        duration_stop_measure(&duration, &duration_text);
-       command_print(cmd_ctx, "downloaded %lli byte in %s", file.size, duration_text);
+       command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
        free(duration_text);
        
-       fileio_close(&file);
+       image_close(&image);
 
        return ERROR_OK;
 
@@ -1650,8 +1746,7 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
 
 int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       fileio_t file;
-       fileio_image_t image_info;
+       fileio_t fileio;
        
        u32 address;
        u32 size;
@@ -1677,13 +1772,9 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_OK;
        }
        
-       image_info.base_address = address;
-       image_info.has_start_address = 0;
-       
-       if (fileio_open(&file, args[0], FILEIO_WRITE, 
-               FILEIO_IMAGE, &image_info, FILEIO_PLAIN) != ERROR_OK)
+       if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
-               command_print(cmd_ctx, "dump_image error: %s", file.error_str);
+               command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);
                return ERROR_OK;
        }
        
@@ -1695,16 +1786,16 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                u32 this_run_size = (size > 560) ? 560 : size;
                
                target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
-               fileio_write(&file, this_run_size, buffer, &size_written);
+               fileio_write(&fileio, this_run_size, buffer, &size_written);
                
                size -= this_run_size;
                address += this_run_size;
        }
 
-       fileio_close(&file);
+       fileio_close(&fileio);
 
        duration_stop_measure(&duration, &duration_text);
-       command_print(cmd_ctx, "dumped %lli byte in %s", file.size, duration_text);
+       command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
        free(duration_text);
        
        return ERROR_OK;
@@ -1787,6 +1878,7 @@ int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args
 int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
+       int retval;
 
        if (argc == 0)
        {
@@ -1830,7 +1922,23 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
                {
                        data_mask = strtoul(args[4], NULL, 0);
                }
-               watchpoint_add(target, strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0), type, data_value, data_mask);
+               
+               if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
+                               strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
+               {
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       command_print(cmd_ctx, "target must be halted to set watchpoints");
+                                       break;
+                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+                                       command_print(cmd_ctx, "no more watchpoints available");
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "unknown error, watchpoint not set");
+                                       break;
+                       }       
+               }
        }
        else
        {