|
|
@@ -82,6 +82,9 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, |
|
|
|
int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); |
|
|
|
int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc); |
|
|
|
int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); |
|
|
|
int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); |
|
|
|
int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); |
|
|
|
|
|
|
|
static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
|
|
|
static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
|
|
|
static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
|
|
@@ -929,6 +932,14 @@ int target_register_commands(struct command_context_s *cmd_ctx) |
|
|
|
register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address"); |
|
|
|
register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC"); |
|
|
|
|
|
|
|
register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY, |
|
|
|
"same args as load_image, image stored in memory - mainly for profiling purposes"); |
|
|
|
|
|
|
|
register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY, |
|
|
|
"loads active fast load image to current target - mainly for profiling purposes"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
register_jim(cmd_ctx, "target", jim_target, "configure target" ); |
|
|
|
|
|
|
|
|
|
|
@@ -3845,7 +3856,7 @@ static int target_create( Jim_GetOptInfo *goi ) |
|
|
|
/* incase variant is not set */ |
|
|
|
if (!target->variant) |
|
|
|
target->variant = strdup(""); |
|
|
|
|
|
|
|
|
|
|
|
/* create the target specific commands */ |
|
|
|
if( target->type->register_commands ){ |
|
|
|
(*(target->type->register_commands))( cmd_ctx ); |
|
|
@@ -3993,3 +4004,196 @@ static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv ) |
|
|
|
|
|
|
|
return JIM_ERR; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct FastLoad |
|
|
|
{ |
|
|
|
u32 address; |
|
|
|
u8 *data; |
|
|
|
int length; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
static int fastload_num; |
|
|
|
static struct FastLoad *fastload; |
|
|
|
|
|
|
|
static void free_fastload() |
|
|
|
{ |
|
|
|
if (fastload!=NULL) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
for (i=0; i<fastload_num; i++) |
|
|
|
{ |
|
|
|
if (fastload[i].data) |
|
|
|
free(fastload[i].data); |
|
|
|
} |
|
|
|
free(fastload); |
|
|
|
fastload=NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) |
|
|
|
{ |
|
|
|
u8 *buffer; |
|
|
|
u32 buf_cnt; |
|
|
|
u32 image_size; |
|
|
|
u32 min_address=0; |
|
|
|
u32 max_address=0xffffffff; |
|
|
|
int i; |
|
|
|
int retval; |
|
|
|
|
|
|
|
image_t image; |
|
|
|
|
|
|
|
duration_t duration; |
|
|
|
char *duration_text; |
|
|
|
|
|
|
|
if ((argc < 1)||(argc > 5)) |
|
|
|
{ |
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
/* 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; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
image.start_address_set = 0; |
|
|
|
|
|
|
|
if (argc>=4) |
|
|
|
{ |
|
|
|
min_address=strtoul(args[3], NULL, 0); |
|
|
|
} |
|
|
|
if (argc>=5) |
|
|
|
{ |
|
|
|
max_address=strtoul(args[4], NULL, 0)+min_address; |
|
|
|
} |
|
|
|
|
|
|
|
if (min_address>max_address) |
|
|
|
{ |
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
duration_start_measure(&duration); |
|
|
|
|
|
|
|
if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK) |
|
|
|
{ |
|
|
|
return ERROR_OK; |
|
|
|
} |
|
|
|
|
|
|
|
image_size = 0x0; |
|
|
|
retval = ERROR_OK; |
|
|
|
fastload_num=image.num_sections; |
|
|
|
fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections); |
|
|
|
if (fastload==NULL) |
|
|
|
{ |
|
|
|
image_close(&image); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); |
|
|
|
for (i = 0; i < image.num_sections; i++) |
|
|
|
{ |
|
|
|
buffer = malloc(image.sections[i].size); |
|
|
|
if (buffer == NULL) |
|
|
|
{ |
|
|
|
command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) |
|
|
|
{ |
|
|
|
free(buffer); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
u32 offset=0; |
|
|
|
u32 length=buf_cnt; |
|
|
|
|
|
|
|
|
|
|
|
/* DANGER!!! beware of unsigned comparision here!!! */ |
|
|
|
|
|
|
|
if ((image.sections[i].base_address+buf_cnt>=min_address)&& |
|
|
|
(image.sections[i].base_address<max_address)) |
|
|
|
{ |
|
|
|
if (image.sections[i].base_address<min_address) |
|
|
|
{ |
|
|
|
/* clip addresses below */ |
|
|
|
offset+=min_address-image.sections[i].base_address; |
|
|
|
length-=offset; |
|
|
|
} |
|
|
|
|
|
|
|
if (image.sections[i].base_address+buf_cnt>max_address) |
|
|
|
{ |
|
|
|
length-=(image.sections[i].base_address+buf_cnt)-max_address; |
|
|
|
} |
|
|
|
|
|
|
|
fastload[i].address=image.sections[i].base_address+offset; |
|
|
|
fastload[i].data=malloc(length); |
|
|
|
if (fastload[i].data==NULL) |
|
|
|
{ |
|
|
|
free(buffer); |
|
|
|
break; |
|
|
|
} |
|
|
|
memcpy(fastload[i].data, buffer+offset, length); |
|
|
|
fastload[i].length=length; |
|
|
|
|
|
|
|
image_size += length; |
|
|
|
command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset); |
|
|
|
} |
|
|
|
|
|
|
|
free(buffer); |
|
|
|
} |
|
|
|
|
|
|
|
duration_stop_measure(&duration, &duration_text); |
|
|
|
if (retval==ERROR_OK) |
|
|
|
{ |
|
|
|
command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text); |
|
|
|
command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so."); |
|
|
|
} |
|
|
|
free(duration_text); |
|
|
|
|
|
|
|
image_close(&image); |
|
|
|
|
|
|
|
if (retval!=ERROR_OK) |
|
|
|
{ |
|
|
|
free_fastload(); |
|
|
|
} |
|
|
|
|
|
|
|
return retval; |
|
|
|
} |
|
|
|
|
|
|
|
int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) |
|
|
|
{ |
|
|
|
if (argc>0) |
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR; |
|
|
|
if (fastload==NULL) |
|
|
|
{ |
|
|
|
LOG_ERROR("No image in memory"); |
|
|
|
return ERROR_FAIL; |
|
|
|
} |
|
|
|
int i; |
|
|
|
int ms=timeval_ms(); |
|
|
|
int size=0; |
|
|
|
for (i=0; i<fastload_num;i++) |
|
|
|
{ |
|
|
|
int retval; |
|
|
|
target_t *target = get_current_target(cmd_ctx); |
|
|
|
if ((retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data)) != ERROR_OK) |
|
|
|
{ |
|
|
|
return retval; |
|
|
|
} |
|
|
|
size+=fastload[i].length; |
|
|
|
} |
|
|
|
int after=timeval_ms(); |
|
|
|
command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); |
|
|
|
return ERROR_OK; |
|
|
|
} |