This checkin is still experimental, not recommended for general use git-svn-id: svn://svn.berlios.de/openocd/trunk@159 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.1.0
@@ -490,9 +490,10 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c | |||
int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | |||
{ | |||
u32 offset; | |||
u32 binary_size; | |||
u8 *buffer; | |||
u32 buf_cnt; | |||
u32 image_size; | |||
int i; | |||
image_t image; | |||
@@ -531,51 +532,62 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||
return ERROR_OK; | |||
} | |||
binary_size = image.size; | |||
buffer = malloc(binary_size); | |||
image_read(&image, binary_size, buffer, &buf_cnt); | |||
if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) | |||
image_size = 0x0; | |||
for (i = 0; i < image.num_sections; i++) | |||
{ | |||
command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", | |||
args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); | |||
switch (retval) | |||
buffer = malloc(image.sections[i].size); | |||
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) | |||
{ | |||
case ERROR_TARGET_NOT_HALTED: | |||
command_print(cmd_ctx, "can't work with this flash while target is running"); | |||
break; | |||
case ERROR_INVALID_ARGUMENTS: | |||
command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>"); | |||
break; | |||
case ERROR_FLASH_BANK_INVALID: | |||
command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); | |||
break; | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
command_print(cmd_ctx, "flash program error"); | |||
break; | |||
case ERROR_FLASH_DST_BREAKS_ALIGNMENT: | |||
command_print(cmd_ctx, "offset breaks required alignment"); | |||
break; | |||
case ERROR_FLASH_DST_OUT_OF_BANK: | |||
command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); | |||
break; | |||
case ERROR_FLASH_SECTOR_NOT_ERASED: | |||
command_print(cmd_ctx, "destination sector(s) not erased"); | |||
break; | |||
default: | |||
command_print(cmd_ctx, "unknown error"); | |||
ERROR("image_read_section failed with error code: %i", retval); | |||
command_print(cmd_ctx, "image reading failed, flash write aborted"); | |||
free(buffer); | |||
image_close(&image); | |||
return ERROR_OK; | |||
} | |||
if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) | |||
{ | |||
command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", | |||
args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); | |||
switch (retval) | |||
{ | |||
case ERROR_TARGET_NOT_HALTED: | |||
command_print(cmd_ctx, "can't work with this flash while target is running"); | |||
break; | |||
case ERROR_INVALID_ARGUMENTS: | |||
command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>"); | |||
break; | |||
case ERROR_FLASH_BANK_INVALID: | |||
command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); | |||
break; | |||
case ERROR_FLASH_OPERATION_FAILED: | |||
command_print(cmd_ctx, "flash program error"); | |||
break; | |||
case ERROR_FLASH_DST_BREAKS_ALIGNMENT: | |||
command_print(cmd_ctx, "offset breaks required alignment"); | |||
break; | |||
case ERROR_FLASH_DST_OUT_OF_BANK: | |||
command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); | |||
break; | |||
case ERROR_FLASH_SECTOR_NOT_ERASED: | |||
command_print(cmd_ctx, "destination sector(s) not erased"); | |||
break; | |||
default: | |||
command_print(cmd_ctx, "unknown error"); | |||
} | |||
} | |||
image_size += buf_cnt; | |||
free(buffer); | |||
} | |||
else | |||
{ | |||
duration_stop_measure(&duration, &duration_text); | |||
command_print(cmd_ctx, "wrote file %s to flash bank %i at offset 0x%8.8x in %s", | |||
args[1], strtoul(args[0], NULL, 0), offset, duration_text); | |||
free(duration_text); | |||
} | |||
free(buffer); | |||
duration_stop_measure(&duration, &duration_text); | |||
command_print(cmd_ctx, "wrote %u byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)", | |||
image_size, args[1], strtoul(args[0], NULL, 0), offset, duration_text, | |||
(float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); | |||
free(duration_text); | |||
image_close(&image); | |||
return ERROR_OK; | |||
@@ -1164,8 +1164,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
u32 buf_cnt; | |||
enum oob_formats oob_format = NAND_OOB_NONE; | |||
image_t image; | |||
int image_type_identified = 0; | |||
fileio_t fileio; | |||
duration_t duration; | |||
char *duration_text; | |||
@@ -1187,7 +1186,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
u32 oob_size = 0; | |||
duration_start_measure(&duration); | |||
strtoul(args[2], NULL, 0); | |||
offset = strtoul(args[2], NULL, 0); | |||
if (argc > 3) | |||
{ | |||
@@ -1200,40 +1199,18 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; | |||
else | |||
{ | |||
if (identify_image_type(&image.type, args[i]) == ERROR_OK) | |||
{ | |||
image_type_identified = 1; | |||
} | |||
else | |||
{ | |||
command_print(cmd_ctx, "unknown option: %s", args[i]); | |||
} | |||
command_print(cmd_ctx, "unknown option: %s", args[i]); | |||
} | |||
} | |||
} | |||
/* if no image type option was encountered, set the default */ | |||
if (!image_type_identified) | |||
{ | |||
identify_image_type(&image.type, NULL); | |||
image_type_identified = 1; | |||
} | |||
image.base_address_set = 1; | |||
image.base_address = strtoul(args[2], NULL, 0); | |||
image.start_address_set = 0; | |||
if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK) | |||
if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) | |||
{ | |||
command_print(cmd_ctx, "flash write error: %s", image.error_str); | |||
command_print(cmd_ctx, "file open error: %s", fileio.error_str); | |||
return ERROR_OK; | |||
} | |||
/* the offset might have been overwritten by the image base address */ | |||
offset = image.base_address; | |||
buf_cnt = binary_size = image.size; | |||
buf_cnt = binary_size = fileio.size; | |||
if (!(oob_format & NAND_OOB_ONLY)) | |||
{ | |||
@@ -1262,7 +1239,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
if (page) | |||
{ | |||
image_read(&image, page_size, page, &size_read); | |||
fileio_read(&fileio, page_size, page, &size_read); | |||
buf_cnt -= size_read; | |||
if (size_read < page_size) | |||
{ | |||
@@ -1272,7 +1249,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
if (oob) | |||
{ | |||
image_read(&image, oob_size, oob, &size_read); | |||
fileio_read(&fileio, oob_size, oob, &size_read); | |||
buf_cnt -= size_read; | |||
if (size_read < oob_size) | |||
{ | |||
@@ -1289,9 +1266,11 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
offset += page_size; | |||
} | |||
fileio_close(&fileio); | |||
duration_stop_measure(&duration, &duration_text); | |||
command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s", | |||
args[1], args[0], image.base_address, duration_text); | |||
args[1], args[0], offset, duration_text); | |||
free(duration_text); | |||
} | |||
else | |||
@@ -18,7 +18,7 @@ | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-29 13:15 CEST)" | |||
#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-30 17:45 CEST)" | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
@@ -23,6 +23,7 @@ | |||
#ifndef ETM_H | |||
#define ETM_H | |||
#include "image.h" | |||
#include "trace.h" | |||
#include "target.h" | |||
#include "register.h" | |||
@@ -142,7 +143,7 @@ typedef struct etm_context_s | |||
etm_portmode_t portmode; /* normal, multiplexed or demultiplexed */ | |||
etmv1_tracemode_t tracemode; /* type of information the trace contains (data, addres, contextID, ...) */ | |||
armv4_5_state_t core_state; /* current core state (ARM, Thumb, Jazelle) */ | |||
// trace_image_provider_t image_provider; /* source for target opcodes */ | |||
image_t image; /* source for target opcodes */ | |||
u32 pipe_index; /* current trace cycle */ | |||
u32 data_index; /* cycle holding next data packet */ | |||
u32 current_pc; /* current program counter */ | |||
@@ -39,29 +39,38 @@ int image_ihex_buffer_complete(image_t *image) | |||
fileio_t *fileio = &ihex->fileio; | |||
u32 raw_bytes_read, raw_bytes; | |||
int retval; | |||
u32 full_address = image->base_address; | |||
char *buffer = malloc(ihex->raw_size); | |||
u32 cooked_bytes = 0x0; | |||
u32 full_address = 0x0; | |||
char *buffer = malloc(fileio->size); | |||
u32 cooked_bytes; | |||
int i; | |||
ihex->raw_size = fileio->size; | |||
ihex->buffer = malloc(ihex->raw_size >> 1); | |||
/* we can't determine the number of sections that we'll have to create ahead of time, | |||
* so we locally hold them until parsing is finished */ | |||
image_section_t section[IMAGE_MAX_SECTIONS]; | |||
u8 *section_pointer[IMAGE_MAX_SECTIONS]; | |||
if ((retval = fileio_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK) | |||
if ((retval = fileio_read(fileio, fileio->size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK) | |||
{ | |||
free(buffer); | |||
ERROR("failed buffering IHEX file, read failed"); | |||
return ERROR_FILEIO_OPERATION_FAILED; | |||
} | |||
if (raw_bytes_read != ihex->raw_size) | |||
if (raw_bytes_read != fileio->size) | |||
{ | |||
free(buffer); | |||
ERROR("failed buffering complete IHEX file, only partially read"); | |||
return ERROR_FILEIO_OPERATION_FAILED; | |||
} | |||
image->size = 0x0; | |||
ihex->buffer = malloc(fileio->size >> 1); | |||
raw_bytes = 0x0; | |||
cooked_bytes = 0x0; | |||
image->num_sections = 0; | |||
section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; | |||
section[image->num_sections].base_address = 0x0; | |||
section[image->num_sections].size = 0x0; | |||
section[image->num_sections].flags = 0; | |||
while (raw_bytes < raw_bytes_read) | |||
{ | |||
u32 count; | |||
@@ -75,13 +84,24 @@ int image_ihex_buffer_complete(image_t *image) | |||
} | |||
raw_bytes += 9; | |||
if (record_type == 0) | |||
if (record_type == 0) /* Data Record */ | |||
{ | |||
if ((full_address & 0xffff) != address) | |||
{ | |||
free(buffer); | |||
ERROR("can't handle non-linear IHEX file"); | |||
return ERROR_IMAGE_FORMAT_ERROR; | |||
/* we encountered a nonconsecutive location, create a new section, | |||
* unless the current section has zero size, in which case this specifies | |||
* the current section's base address | |||
*/ | |||
if (section[image->num_sections].size != 0) | |||
{ | |||
image->num_sections++; | |||
section[image->num_sections].size = 0x0; | |||
section[image->num_sections].flags = 0; | |||
section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; | |||
} | |||
section[image->num_sections].base_address = | |||
(full_address & 0xffff0000) | address; | |||
full_address = (full_address & 0xffff0000) | address; | |||
} | |||
while (count-- > 0) | |||
@@ -89,16 +109,31 @@ int image_ihex_buffer_complete(image_t *image) | |||
sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]); | |||
raw_bytes += 2; | |||
cooked_bytes += 1; | |||
section[image->num_sections].size += 1; | |||
full_address++; | |||
} | |||
} | |||
else if (record_type == 1) | |||
else if (record_type == 1) /* End of File Record */ | |||
{ | |||
/* finish the current section */ | |||
image->num_sections++; | |||
/* copy section information */ | |||
ihex->section_pointer = malloc(sizeof(u8*) * image->num_sections); | |||
image->sections = malloc(sizeof(image_section_t) * image->num_sections); | |||
for (i = 0; i < image->num_sections; i++) | |||
{ | |||
ihex->section_pointer[i] = section_pointer[i]; | |||
image->sections[i].base_address = section[i].base_address + | |||
((image->base_address_set) ? image->base_address : 0); | |||
image->sections[i].size = section[i].size; | |||
image->sections[i].flags = section[i].flags; | |||
} | |||
free(buffer); | |||
image->size = cooked_bytes; | |||
return ERROR_OK; | |||
} | |||
else if (record_type == 4) | |||
else if (record_type == 4) /* Extended Linear Address Record */ | |||
{ | |||
u16 upper_address; | |||
@@ -107,12 +142,23 @@ int image_ihex_buffer_complete(image_t *image) | |||
if ((full_address >> 16) != upper_address) | |||
{ | |||
free(buffer); | |||
ERROR("can't handle non-linear IHEX file"); | |||
return ERROR_IMAGE_FORMAT_ERROR; | |||
/* we encountered a nonconsecutive location, create a new section, | |||
* unless the current section has zero size, in which case this specifies | |||
* the current section's base address | |||
*/ | |||
if (section[image->num_sections].size != 0) | |||
{ | |||
image->num_sections++; | |||
section[image->num_sections].size = 0x0; | |||
section[image->num_sections].flags = 0; | |||
section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; | |||
} | |||
section[image->num_sections].base_address = | |||
(full_address & 0xffff) | (upper_address << 16); | |||
full_address = (full_address & 0xffff) | (upper_address << 16); | |||
} | |||
} | |||
else if (record_type == 5) | |||
else if (record_type == 5) /* Start Linear Address Record */ | |||
{ | |||
u32 start_address; | |||
@@ -163,10 +209,14 @@ int image_open(image_t *image, void *source, enum fileio_access access) | |||
return retval; | |||
} | |||
if (access == FILEIO_WRITE) | |||
image->size = 0; | |||
else | |||
image->size = image_binary->fileio.size; | |||
image->num_sections = 1; | |||
image->sections = malloc(sizeof(image_section_t)); | |||
image->sections[0].base_address = 0x0; | |||
image->sections[0].size = image_binary->fileio.size; | |||
image->sections[0].flags = 0; | |||
if (image->base_address_set == 1) | |||
image->sections[0].base_address = image->base_address; | |||
return ERROR_OK; | |||
} | |||
@@ -192,9 +242,6 @@ int image_open(image_t *image, void *source, enum fileio_access access) | |||
return retval; | |||
} | |||
image_ihex->position = 0; | |||
image_ihex->raw_size = image_ihex->fileio.size; | |||
if ((retval = image_ihex_buffer_complete(image)) != ERROR_OK) | |||
{ | |||
snprintf(image->error_str, IMAGE_MAX_ERROR_STRING, | |||
@@ -217,7 +264,7 @@ int image_open(image_t *image, void *source, enum fileio_access access) | |||
return retval; | |||
}; | |||
int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) | |||
int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read) | |||
{ | |||
int retval; | |||
@@ -225,6 +272,21 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) | |||
{ | |||
image_binary_t *image_binary = image->type_private; | |||
/* only one section in a plain binary */ | |||
if (section != 0) | |||
return ERROR_INVALID_ARGUMENTS; | |||
if ((offset > image->sections[0].size) || (offset + size > image->sections[0].size)) | |||
return ERROR_INVALID_ARGUMENTS; | |||
/* seek to offset */ | |||
if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK) | |||
{ | |||
strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); | |||
return retval; | |||
} | |||
/* return requested bytes */ | |||
if ((retval = fileio_read(&image_binary->fileio, size, buffer, size_read)) != ERROR_OK) | |||
{ | |||
strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); | |||
@@ -234,15 +296,8 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) | |||
else if (image->type == IMAGE_IHEX) | |||
{ | |||
image_ihex_t *image_ihex = image->type_private; | |||
if ((image_ihex->position + size) > image->size) | |||
{ | |||
/* don't read past the end of the file */ | |||
size = (image->size - image_ihex->position); | |||
} | |||
memcpy(buffer, image_ihex->buffer + image_ihex->position, size); | |||
image_ihex->position += size; | |||
memcpy(buffer, image_ihex->section_pointer[section] + offset, size); | |||
*size_read = size; | |||
image->error_str[0] = '\0'; | |||
@@ -256,37 +311,6 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) | |||
return ERROR_OK; | |||
} | |||
int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written) | |||
{ | |||
int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED; | |||
if (image->type == IMAGE_BINARY) | |||
{ | |||
image_binary_t *image_binary = image->type_private; | |||
if ((retval = fileio_write(&image_binary->fileio, size, buffer, size_written)) != ERROR_OK) | |||
{ | |||
strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); | |||
return retval; | |||
} | |||
} | |||
else if (image->type == IMAGE_IHEX) | |||
{ | |||
return ERROR_FILEIO_OPERATION_NOT_SUPPORTED; | |||
} | |||
else if (image->type == IMAGE_MEMORY) | |||
{ | |||
/* TODO: handle target memory pseudo image */ | |||
} | |||
if (retval != ERROR_OK) | |||
return retval; | |||
image->size += size; | |||
return ERROR_OK; | |||
} | |||
int image_close(image_t *image) | |||
{ | |||
if (image->type == IMAGE_BINARY) | |||
@@ -301,6 +325,9 @@ int image_close(image_t *image) | |||
fileio_close(&image_ihex->fileio); | |||
if (image_ihex->section_pointer) | |||
free(image_ihex->section_pointer); | |||
if (image_ihex->buffer) | |||
free(image_ihex->buffer); | |||
} | |||
@@ -309,7 +336,11 @@ int image_close(image_t *image) | |||
/* do nothing for now */ | |||
} | |||
free(image->type_private); | |||
if (image->type_private) | |||
free(image->type_private); | |||
if (image->sections) | |||
free(image->sections); | |||
return ERROR_OK; | |||
} | |||
@@ -24,11 +24,12 @@ | |||
#include "target.h" | |||
#define IMAGE_MAX_ERROR_STRING (128) | |||
#define IMAGE_MAX_SECTIONS (128) | |||
typedef enum image_type | |||
{ | |||
IMAGE_BINARY, /* plain binary */ | |||
IMAGE_IHEX, /* intel hex-record format */ | |||
IMAGE_IHEX, /* intel hex-record format */ | |||
IMAGE_MEMORY, /* target-memory pseudo-image */ | |||
/* | |||
* Possible future enhancements: | |||
@@ -37,15 +38,23 @@ typedef enum image_type | |||
*/ | |||
} image_type_t; | |||
typedef struct image_section_s | |||
{ | |||
u32 base_address; | |||
u32 size; | |||
int flags; | |||
} image_section_t; | |||
typedef struct image_s | |||
{ | |||
image_type_t type; /* image type (plain, ihex, ...) */ | |||
void *type_private; /* type private data */ | |||
int base_address_set; /* whether the image start address has been set */ | |||
u32 base_address; /* base address of image in target memory */ | |||
int num_sections; /* number of sections contained in the image */ | |||
image_section_t *sections; /* array of sections */ | |||
int base_address_set; /* whether the image has a base address set (for relocation purposes) */ | |||
int base_address; /* base address, if one is set */ | |||
int start_address_set; /* whether the image has a start address (entry point) associated */ | |||
u32 start_address; /* start address, if one is set */ | |||
u32 size; /* image size in byte */ | |||
char error_str[IMAGE_MAX_ERROR_STRING]; | |||
} image_t; | |||
@@ -57,9 +66,8 @@ typedef struct image_binary_s | |||
typedef struct image_ihex_s | |||
{ | |||
fileio_t fileio; | |||
u32 position; | |||
u32 raw_size; | |||
u8 *buffer; | |||
u8 **section_pointer; | |||
} image_ihex_t; | |||
typedef struct image_memory_s | |||
@@ -68,8 +76,7 @@ typedef struct image_memory_s | |||
} image_memory_t; | |||
extern int image_open(image_t *image, void *source, enum fileio_access access); | |||
extern int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_written); | |||
extern int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written); | |||
extern int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read); | |||
extern int image_close(image_t *image); | |||
extern int identify_image_type(image_type_t *type, char *type_string); | |||
@@ -1658,6 +1658,8 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
u8 *buffer; | |||
u32 buf_cnt; | |||
u32 image_size; | |||
int i; | |||
int retval; | |||
image_t image; | |||
@@ -1678,8 +1680,6 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
image.base_address = strtoul(args[1], NULL, 0); | |||
image.start_address_set = 0; | |||
buffer = malloc(128 * 1024); | |||
duration_start_measure(&duration); | |||
@@ -1689,21 +1689,27 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
return ERROR_OK; | |||
} | |||
image_size = image.size; | |||
address = image.base_address; | |||
while ((image_size > 0) && | |||
(image_read(&image, 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; | |||
image_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 %u byte in %s", image.size, duration_text); | |||
command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text); | |||
free(duration_text); | |||
image_close(&image); | |||