Browse Source

- split fileio handling into fileio part and image handling

- reworked etm/etb into a generic etm part with trace capture drivers (currently only etb supported)
- added XScale debug handler binary to repository
- added Thumb disassembling (thanks to Vincent Palatin for this patch)
- added support for non-CFI compatible flashes to cfi driver (currently only SST39VFxxx devices supported)
This checkin is experimental, not suitable for general use


git-svn-id: svn://svn.berlios.de/openocd/trunk@155 b42882b7-edfa-0310-969c-e2dbd0fdcd60
tags/v0.1.0
drath 16 years ago
parent
commit
237e894805
26 changed files with 2522 additions and 938 deletions
  1. +2
    -2
      src/flash/Makefile.am
  2. +260
    -150
      src/flash/cfi.c
  3. +17
    -1
      src/flash/cfi.h
  4. +14
    -14
      src/flash/flash.c
  5. +26
    -32
      src/flash/nand.c
  6. +175
    -0
      src/flash/non_cfi.c
  7. +41
    -0
      src/flash/non_cfi.h
  8. +5
    -269
      src/helper/fileio.c
  9. +12
    -45
      src/helper/fileio.h
  10. +1
    -0
      src/jtag/jtag.c
  11. +1
    -1
      src/openocd.c
  12. +2
    -2
      src/target/Makefile.am
  13. +3
    -82
      src/target/arm7_9_common.c
  14. +3
    -4
      src/target/arm7_9_common.h
  15. +3
    -3
      src/target/arm7tdmi.c
  16. +3
    -9
      src/target/arm9tdmi.c
  17. +776
    -11
      src/target/arm_disassembler.c
  18. +3
    -2
      src/target/arm_disassembler.h
  19. +36
    -14
      src/target/arm_simulator.c
  20. +4
    -4
      src/target/armv4_5.h
  21. +289
    -254
      src/target/etb.c
  22. +9
    -3
      src/target/etb.h
  23. +685
    -1
      src/target/etm.c
  24. +127
    -4
      src/target/etm.h
  25. +25
    -31
      src/target/target.c
  26. BIN
      src/target/xscale/debug_handler.bin

+ 2
- 2
src/flash/Makefile.am View File

@@ -1,5 +1,5 @@
INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target $(all_includes)
METASOURCES = AUTO
noinst_LIBRARIES = libflash.a
libflash_a_SOURCES = flash.c lpc2000.c cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c
noinst_HEADERS = flash.h lpc2000.h cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h
libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c
noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h

+ 260
- 150
src/flash/cfi.c View File

@@ -66,17 +66,33 @@ flash_driver_t cfi_flash =
.info = cfi_info
};

cfi_unlock_addresses_t cfi_unlock_addresses[] =
{
[CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },
[CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },
};

/* CFI fixups foward declarations */
void cfi_fixup_non_cfi(flash_bank_t *flash, void *param);
void cfi_fixup_0002_erase_regions(flash_bank_t *flash, void *param);
void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);
void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);

/* fixup after identifying JEDEC manufactuer and ID */
cfi_fixup_t cfi_jedec_fixups[] = {
{CFI_MFR_SST, 0x00D4, cfi_fixup_non_cfi, NULL},
{CFI_MFR_SST, 0x00D5, cfi_fixup_non_cfi, NULL},
{CFI_MFR_SST, 0x00D6, cfi_fixup_non_cfi, NULL},
{CFI_MFR_SST, 0x00D7, cfi_fixup_non_cfi, NULL},
{0, 0, NULL, NULL}
};

/* fixup after reading cmdset 0002 primary query table */
cfi_fixup_t cfi_0002_fixups[] = {
{CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},
{CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},
{0, 0, NULL, NULL}
@@ -421,6 +437,11 @@ int cfi_read_spansion_pri_ext(flash_bank_t *bank)
DEBUG("WP# protection 0x%x", pri_ext->TopBottom);
/* default values for implementation specific workarounds */
pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
pri_ext->_reversed_geometry = 0;
return ERROR_OK;
}

@@ -594,7 +615,9 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **
cfi_info = malloc(sizeof(cfi_flash_bank_t));
bank->driver_priv = cfi_info;
cfi_info->x16_as_x8 = 1;
cfi_info->x16_as_x8 = 0;
cfi_info->jedec_probe = 0;
cfi_info->not_cfi = 0;
cfi_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
if (!cfi_info->target)
@@ -605,9 +628,13 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **

for (i = 6; i < argc; i++)
{
if (strcmp(args[i], "x16_as_x8") != 0)
if (strcmp(args[i], "x16_as_x8") == 0)
{
cfi_info->x16_as_x8 = 0;
cfi_info->x16_as_x8 = 1;
}
else if (strcmp(args[i], "jedec_probe") == 0)
{
cfi_info->jedec_probe = 1;
}
}
@@ -665,19 +692,19 @@ int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last)
for (i = first; i <= last; i++)
{
cfi_command(bank, 0xaa, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
cfi_command(bank, 0x55, command);
target->type->write_memory(target, flash_address(bank, 0, 0x2aa), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
cfi_command(bank, 0x80, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);

cfi_command(bank, 0xaa, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
cfi_command(bank, 0x55, command);
target->type->write_memory(target, flash_address(bank, 0, 0x2aa), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
cfi_command(bank, 0x30, command);
target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
@@ -891,9 +918,10 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
armv4_5_algorithm_t armv4_5_info;
working_area_t *source;
u32 buffer_size = 32768;
u8 write_command[CFI_MAX_BUS_WIDTH];
u8 busy_pattern[CFI_MAX_BUS_WIDTH];
u8 error_pattern[CFI_MAX_BUS_WIDTH];
u8 write_command_buf[CFI_MAX_BUS_WIDTH];
u8 busy_pattern_buf[CFI_MAX_BUS_WIDTH];
u8 error_pattern_buf[CFI_MAX_BUS_WIDTH];
u32 write_command_val, busy_pattern_val, error_pattern_val;
int retval;

/* algorithm register usage:
@@ -906,7 +934,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
* r6: error test pattern
*/
u32 word_32_code[] = {
static const u32 word_32_code[] = {
0xe4904004, /* loop: ldr r4, [r0], #4 */
0xe5813000, /* str r3, [r1] */
0xe5814000, /* str r4, [r1] */
@@ -923,7 +951,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
0xeafffffe, /* done: b -2 */
};
u32 word_16_code[] = {
static const u32 word_16_code[] = {
0xe0d040b2, /* loop: ldrh r4, [r0], #2 */
0xe1c130b0, /* strh r3, [r1] */
0xe1c140b0, /* strh r4, [r1] */
@@ -940,7 +968,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
0xeafffffe, /* done: b -2 */
};
u32 word_8_code[] = {
static const u32 word_8_code[] = {
0xe4d04001, /* loop: ldrb r4, [r0], #1 */
0xe5c13000, /* strb r3, [r1] */
0xe5c14000, /* strb r4, [r1] */
@@ -966,29 +994,37 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
/* flash write code */
if (!cfi_info->write_algorithm)
{
u8 write_code_buf[14 * 4];
int i;
if (target_alloc_working_area(target, 4 * 14, &cfi_info->write_algorithm) != ERROR_OK)
{
WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
};
/* write algorithm code to working area */
if (bank->bus_width == 1)
{
target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_8_code);
for (i = 0; i < 14; i++)
target_buffer_set_u32(target, write_code_buf + (i*4), word_8_code[i]);
}
else if (bank->bus_width == 2)
{
target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_16_code);
for (i = 0; i < 14; i++)
target_buffer_set_u32(target, write_code_buf + (i*4), word_16_code[i]);
}
else if (bank->bus_width == 4)
{
target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_32_code);
for (i = 0; i < 14; i++)
target_buffer_set_u32(target, write_code_buf + (i*4), word_32_code[i]);
}
else
{
return ERROR_FLASH_OPERATION_FAILED;
}

target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, write_code_buf);
}
while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
@@ -1013,10 +1049,30 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);

cfi_command(bank, 0x40, write_command);
cfi_command(bank, 0x80, busy_pattern);
cfi_command(bank, 0x7e, error_pattern);

/* prepare command and status register patterns */
cfi_command(bank, 0x40, write_command_buf);
cfi_command(bank, 0x80, busy_pattern_buf);
cfi_command(bank, 0x7e, error_pattern_buf);
if (bank->bus_width == 1)
{
write_command_val = write_command_buf[0];
busy_pattern_val = busy_pattern_buf[0];
error_pattern_val = error_pattern_buf[0];
}
else if (bank->bus_width == 2)
{
write_command_val = target_buffer_get_u16(target, write_command_buf);
busy_pattern_val = target_buffer_get_u16(target, busy_pattern_buf);
error_pattern_val = target_buffer_get_u16(target, error_pattern_buf);
}
else if (bank->bus_width == 4)
{
write_command_val = target_buffer_get_u32(target, write_command_buf);
busy_pattern_val = target_buffer_get_u32(target, busy_pattern_buf);
error_pattern_val = target_buffer_get_u32(target, error_pattern_buf);
}
while (count > 0)
{
u32 thisrun_count = (count > buffer_size) ? buffer_size : count;
@@ -1026,11 +1082,9 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
buf_set_u32(reg_params[3].value, 0, 32, target_buffer_get_u32(target, write_command));
buf_set_u32(reg_params[5].value, 0, 32, target_buffer_get_u32(target, busy_pattern));
buf_set_u32(reg_params[6].value, 0, 32, target_buffer_get_u32(target, error_pattern));
buf_set_u32(reg_params[5].value, 0, 32, buf_get_u32(busy_pattern, 0, 32));
buf_set_u32(reg_params[6].value, 0, 32, buf_get_u32(error_pattern, 0, 32));
buf_set_u32(reg_params[3].value, 0, 32, write_command_val);
buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);
buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);
if ((retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (13 * 4), 10000, &armv4_5_info)) != ERROR_OK)
{
@@ -1038,7 +1092,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
return ERROR_FLASH_OPERATION_FAILED;
}
if (buf_get_u32(reg_params[4].value, 0, 32) & target_buffer_get_u32(target, error_pattern))
if (buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val)
{
/* read status register (outputs debug inforation) */
cfi_intel_wait_status_busy(bank, 100);
@@ -1078,8 +1132,6 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
int i;
int retval;
int exit_code = ERROR_OK;
int code_size;
void *code_p;

/* input parameters - */
/* R0 = source address */
@@ -1095,8 +1147,8 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
/* unlock registers - */
/* R8 = unlock1_addr */
/* R9 = unlock1_cmd */
/* R10 = unlock1_addr */
/* R11 = unlock1_cmd */
/* R10 = unlock2_addr */
/* R11 = unlock2_cmd */

u32 word_32_code[] = {
/* 00008100 <sp_32_code>: */
@@ -1207,36 +1259,47 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
/* flash write code */
if (!cfi_info->write_algorithm)
{
/* write algorithm code to working area */
u8 *code_p;

/* convert bus-width dependent algorithm code to correct endiannes */
if (bank->bus_width == 1)
{
code_size = sizeof(word_8_code);
code_p = word_8_code;
code_p = malloc(24 * 4);
for (i = 0; i < 24; i++)
target_buffer_set_u32(target, code_p + (i*4), word_8_code[i]);
}
else if (bank->bus_width == 2)
{
code_size = sizeof(word_16_code);
code_p = word_16_code;
}
code_p = malloc(24 * 4);
for (i = 0; i < 24; i++)
target_buffer_set_u32(target, code_p + (i*4), word_16_code[i]);
}
else if (bank->bus_width == 4)
{
code_size = sizeof(word_32_code);
code_p = word_32_code;
code_p = malloc(24 * 4);
for (i = 0; i < 24; i++)
target_buffer_set_u32(target, code_p + (i*4), word_32_code[i]);
}
else
{
return ERROR_FLASH_OPERATION_FAILED;
}

if (target_alloc_working_area(target, code_size,
&cfi_info->write_algorithm) != ERROR_OK)
/* allocate working area */
if (target_alloc_working_area(target, 24 * 4,
&cfi_info->write_algorithm) != ERROR_OK)
{
WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
target_write_buffer(target, cfi_info->write_algorithm->address,
code_size, code_p);
/* write algorithm code to working area */
target_write_buffer(target, cfi_info->write_algorithm->address, 24 * 4, code_p);
free(code_p);
}
while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
@@ -1277,14 +1340,14 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));
cfi_command(bank, 0x80, write_command);
buf_set_u32(reg_params[4].value, 0, 32, buf_get_u32(write_command, 0, 32));
buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, 0x555));
buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));
buf_set_u32(reg_params[7].value, 0, 32, 0xaa);
buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, 0xaaa));
buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));
buf_set_u32(reg_params[9].value, 0, 32, 0x55);
retval = target->type->run_algorithm(target, 0, NULL, 10, reg_params,
cfi_info->write_algorithm->address,
cfi_info->write_algorithm->address + (code_size - 4),
cfi_info->write_algorithm->address + ((24 * 4) - 4),
10000, &armv4_5_info);

status = buf_get_u32(reg_params[5].value, 0, 32);
@@ -1301,6 +1364,8 @@ int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address,
count -= thisrun_count;
}
target_free_working_area(target, source);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
@@ -1347,13 +1412,13 @@ int cfi_spansion_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
u8 command[8];
cfi_command(bank, 0xaa, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
cfi_command(bank, 0x55, command);
target->type->write_memory(target, flash_address(bank, 0, 0x2aa), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
cfi_command(bank, 0xa0, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);

target->type->write_memory(target, address, bank->bus_width, 1, word);
@@ -1554,6 +1619,16 @@ void cfi_fixup_0002_erase_regions(flash_bank_t *bank, void *param)
}
}

void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)
{
cfi_flash_bank_t *cfi_info = bank->driver_priv;
cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
cfi_unlock_addresses_t *unlock_addresses = param;
pri_ext->_unlock1 = unlock_addresses->unlock1;
pri_ext->_unlock2 = unlock_addresses->unlock2;
}

int cfi_probe(struct flash_bank_s *bank)
{
cfi_flash_bank_t *cfi_info = bank->driver_priv;
@@ -1563,14 +1638,25 @@ int cfi_probe(struct flash_bank_s *bank)
int i;
int sector = 0;
u32 offset = 0;
u32 unlock1 = 0x555;
u32 unlock2 = 0x2aa;
/* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,
* while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa
*/
if (cfi_info->jedec_probe)
{
unlock1 = 0x5555;
unlock2 = 0x2aaa;
}
/* switch to read identifier codes mode ("AUTOSELECT") */
cfi_command(bank, 0xaa, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);
cfi_command(bank, 0x55, command);
target->type->write_memory(target, flash_address(bank, 0, 0x2aa), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, unlock2), bank->bus_width, 1, command);
cfi_command(bank, 0x90, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);

if (bank->chip_width == 1)
{
@@ -1594,105 +1680,132 @@ int cfi_probe(struct flash_bank_s *bank)

cfi_fixup(bank, cfi_jedec_fixups);

/* enter CFI query mode
* according to JEDEC Standard No. 68.01,
* a single bus sequence with address = 0x55, data = 0x98 should put
* the device into CFI query mode.
*
* SST flashes clearly violate this, and we will consider them incompatbile for now
/* query only if this is a CFI compatible flash,
* otherwise the relevant info has already been filled in
*/
cfi_command(bank, 0x98, command);
target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
if (cfi_info->not_cfi == 0)
{
/* enter CFI query mode
* according to JEDEC Standard No. 68.01,
* a single bus sequence with address = 0x55, data = 0x98 should put
* the device into CFI query mode.
*
* SST flashes clearly violate this, and we will consider them incompatbile for now
*/
cfi_command(bank, 0x98, command);
target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
{
cfi_command(bank, 0xf0, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
cfi_command(bank, 0xff, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
return ERROR_FLASH_BANK_INVALID;
}
cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);
cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);
cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);
DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);
cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);
cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);
cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);
cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);
cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);
cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);
cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);
cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);
cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);
cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);
cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);
DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",
(cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
(cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
(cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
(cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
(1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
(1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
(1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);
cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);
cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);
cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);
DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));
if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)
{
WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);
}
if (cfi_info->num_erase_regions)
{
cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);
for (i = 0; i < cfi_info->num_erase_regions; i++)
{
cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));
DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);
}
}
else
{
cfi_info->erase_region_info = NULL;
}
/* We need to read the primary algorithm extended query table before calculating
* the sector layout to be able to apply fixups
*/
switch(cfi_info->pri_id)
{
/* Intel command set (standard and extended) */
case 0x0001:
case 0x0003:
cfi_read_intel_pri_ext(bank);
break;
/* AMD/Spansion, Atmel, ... command set */
case 0x0002:
cfi_read_0002_pri_ext(bank);
break;
default:
ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
break;
}
/* return to read array mode
* we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
*/
cfi_command(bank, 0xf0, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
cfi_command(bank, 0xff, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
return ERROR_FLASH_BANK_INVALID;
}
cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);
cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);
cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);
DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);
cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);
cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);
cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);
cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);
cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);
cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);
cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);
cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);
cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);
cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);
cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);
DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",
(cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
(cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
(cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
(cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
(1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
(1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
(1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);
cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);
cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);
cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);
DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));
if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)
{
WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);
}
if (cfi_info->num_erase_regions)
{
cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);
for (i = 0; i < cfi_info->num_erase_regions; i++)
{
cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));
DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);
num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;
}
}
else
{
cfi_info->erase_region_info = NULL;
}
/* We need to read the primary algorithm extended query table before calculating
* the sector layout to be able to apply fixups
*/
/* apply fixups depending on the primary command set */
switch(cfi_info->pri_id)
{
/* Intel command set (standard and extended) */
case 0x0001:
case 0x0003:
cfi_read_intel_pri_ext(bank);
cfi_fixup(bank, cfi_0001_fixups);
break;
/* AMD/Spansion, Atmel, ... command set */
case 0x0002:
cfi_read_0002_pri_ext(bank);
case 0x0002:
cfi_fixup(bank, cfi_0002_fixups);
break;
default:
@@ -1713,6 +1826,11 @@ int cfi_probe(struct flash_bank_s *bank)
}
else
{
for (i = 0; i < cfi_info->num_erase_regions; i++)
{
num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;
}
bank->num_sectors = num_sectors;
bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
@@ -1731,14 +1849,6 @@ int cfi_probe(struct flash_bank_s *bank)
}
}
/* return to read array mode
* we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
*/
cfi_command(bank, 0xf0, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
cfi_command(bank, 0xff, command);
target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
return ERROR_OK;
}

@@ -1893,13 +2003,13 @@ int cfi_spansion_protect_check(struct flash_bank_s *bank)
int i;
cfi_command(bank, 0xaa, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
cfi_command(bank, 0x55, command);
target->type->write_memory(target, flash_address(bank, 0, 0x2aa), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
cfi_command(bank, 0x90, command);
target->type->write_memory(target, flash_address(bank, 0, 0x555), bank->bus_width, 1, command);
target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);

for (i = 0; i < bank->num_sectors; i++)
{


+ 17
- 1
src/flash/cfi.h View File

@@ -30,10 +30,12 @@ typedef struct cfi_flash_bank_s
working_area_t *erase_check_algorithm;
int x16_as_x8;
int jedec_probe;
int not_cfi;
u16 manufacturer;
u16 device_id;
char qry[3];
/* identification string */
@@ -108,6 +110,8 @@ typedef struct cfi_spansion_pri_ext_s
u8 VppMax;
u8 TopBottom;
int _reversed_geometry;
u32 _unlock1;
u32 _unlock2;
} cfi_spansion_pri_ext_t;

/* Atmel primary extended query table as defined for and used by
@@ -124,6 +128,17 @@ typedef struct cfi_atmel_pri_ext_s
u8 page_mode;
} cfi_atmel_pri_ext_t;

enum {
CFI_UNLOCK_555_2AA,
CFI_UNLOCK_5555_2AAA,
};

typedef struct cfi_unlock_addresses_s
{
u32 unlock1;
u32 unlock2;
} cfi_unlock_addresses_t;

typedef struct cfi_fixup_s
{
u16 mfr;
@@ -135,6 +150,7 @@ typedef struct cfi_fixup_s
#define CFI_MFR_AMD 0x0001
#define CFI_MFR_ATMEL 0x001F
#define CFI_MFR_ST 0x0020 /* STMicroelectronics */
#define CFI_MFR_SST 0x00BF

#define CFI_MFR_ANY 0xffff
#define CFI_ID_ANY 0xffff


+ 14
- 14
src/flash/flash.c View File

@@ -35,6 +35,7 @@
#include <errno.h>

#include <fileio.h>
#include <image.h>

/* command handlers */
int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -493,9 +494,7 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
u8 *buffer;
u32 buf_cnt;

fileio_t file;
fileio_image_t image_info;
enum fileio_sec_type sec_type;
image_t image;
duration_t duration;
char *duration_text;
@@ -511,7 +510,12 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
duration_start_measure(&duration);
fileio_identify_image_type(&sec_type, (argc == 4) ? args[3] : NULL);
identify_image_type(&image.type, (argc == 4) ? args[3] : NULL);

image.base_address_set = 1;
image.base_address = strtoul(args[1], NULL, 0);
image.start_address_set = 0;
offset = strtoul(args[2], NULL, 0);
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
@@ -521,20 +525,16 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
return ERROR_OK;
}
image_info.base_address = strtoul(args[2], NULL, 0);
image_info.has_start_address = 0;

if (fileio_open(&file, args[1], FILEIO_READ,
FILEIO_IMAGE, &image_info, sec_type) != ERROR_OK)
if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
{
command_print(cmd_ctx, "flash write error: %s", file.error_str);
command_print(cmd_ctx, "flash write error: %s", image.error_str);
return ERROR_OK;
}
binary_size = file.size;
binary_size = image.size;
buffer = malloc(binary_size);

fileio_read(&file, binary_size, buffer, &buf_cnt);
image_read(&image, binary_size, buffer, &buf_cnt);
if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK)
{
@@ -571,12 +571,12 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
{
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "wrote file %s to flash bank %i at offset 0x%8.8x in %s",
file.url, strtoul(args[0], NULL, 0), offset, duration_text);
args[1], strtoul(args[0], NULL, 0), offset, duration_text);
free(duration_text);
}
free(buffer);
fileio_close(&file);
image_close(&image);
return ERROR_OK;
}

+ 26
- 32
src/flash/nand.c View File

@@ -38,6 +38,7 @@
#include "flash.h"
#include "time_support.h"
#include "fileio.h"
#include "image.h"

int nand_register_commands(struct command_context_s *cmd_ctx);
int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -1163,10 +1164,8 @@ 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;
fileio_t file;
fileio_image_t image_info;
int sec_type_identified = 0;
enum fileio_sec_type sec_type;
image_t image;
int image_type_identified = 0;
duration_t duration;
char *duration_text;
@@ -1201,9 +1200,9 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY;
else
{
if (fileio_identify_image_type(&sec_type, args[i]) == ERROR_OK)
if (identify_image_type(&image.type, args[i]) == ERROR_OK)
{
sec_type_identified = 1;
image_type_identified = 1;
}
else
{
@@ -1214,27 +1213,27 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
}
/* if no image type option was encountered, set the default */
if (!sec_type_identified)
if (!image_type_identified)
{
fileio_identify_image_type(&sec_type, NULL);
sec_type_identified = 1;
identify_image_type(&image.type, NULL);
image_type_identified = 1;
}

image_info.base_address = strtoul(args[2], NULL, 0);
image_info.has_start_address = 0;
image.base_address_set = 1;
image.base_address = strtoul(args[2], NULL, 0);
image.start_address_set = 0;
if (fileio_open(&file, args[1], FILEIO_READ,
FILEIO_IMAGE, &image_info, sec_type) != ERROR_OK)
if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
{
command_print(cmd_ctx, "flash write error: %s", file.error_str);
command_print(cmd_ctx, "flash write error: %s", image.error_str);
return ERROR_OK;
}
/* the offset might have been overwritten by the image base address */
offset = image_info.base_address;
offset = image.base_address;
buf_cnt = binary_size = file.size;
buf_cnt = binary_size = image.size;
if (!(oob_format & NAND_OOB_ONLY))
{
@@ -1263,7 +1262,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (page)
{
fileio_read(&file, page_size, page, &size_read);
image_read(&image, page_size, page, &size_read);
buf_cnt -= size_read;
if (size_read < page_size)
{
@@ -1273,7 +1272,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (oob)
{
fileio_read(&file, oob_size, oob, &size_read);
image_read(&image, oob_size, oob, &size_read);
buf_cnt -= size_read;
if (size_read < oob_size)
{
@@ -1284,7 +1283,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
if (nand_write_page(p, offset / p->page_size, page, page_size, oob, oob_size) != ERROR_OK)
{
command_print(cmd_ctx, "failed writing file %s to NAND flash %s at offset 0x%8.8x",
file.url, args[0], offset);
args[1], args[0], offset);
return ERROR_OK;
}
offset += page_size;
@@ -1292,7 +1291,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char

duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s",
file.url, args[0], image_info.base_address, duration_text);
args[1], args[0], image.base_address, duration_text);
free(duration_text);
}
else
@@ -1318,8 +1317,7 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
{
if (p->device)
{
fileio_t file;
fileio_image_t image_info;
fileio_t fileio;
duration_t duration;
char *duration_text;
int retval;
@@ -1367,14 +1365,10 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
oob_size = 64;
oob = malloc(oob_size);
}

image_info.base_address = address;
image_info.has_start_address = 0;
if (fileio_open(&file, args[1], FILEIO_WRITE,
FILEIO_IMAGE, &image_info, FILEIO_PLAIN) != ERROR_OK)
if (fileio_open(&fileio, args[1], 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;
}
@@ -1391,13 +1385,13 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
if (page)
{
fileio_write(&file, page_size, page, &size_written);
fileio_write(&fileio, page_size, page, &size_written);
bytes_done += page_size;
}
if (oob)
{
fileio_write(&file, oob_size, oob, &size_written);
fileio_write(&fileio, oob_size, oob, &size_written);
bytes_done += oob_size;
}
@@ -1411,10 +1405,10 @@ int handle_nand_dump_command(struct command_context_s *cmd_ctx, char *cmd, char
if (oob)
free(oob);
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 %lli byte in %s", fileio.size, duration_text);
free(duration_text);
}
else


+ 175
- 0
src/flash/non_cfi.c View File

@@ -0,0 +1,175 @@
/***************************************************************************
* Copyright (C) 2007 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>

#include "log.h"

#include "flash.h"
#include "cfi.h"
#include "non_cfi.h"

/* non-CFI compatible flashes */
non_cfi_t non_cfi_flashes[] = {
{
.mfr = CFI_MFR_SST,
.id = 0xd4,
.pri_id = 0x02,
.dev_size = 0x10,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010000f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd5,
.pri_id = 0x02,
.dev_size = 0x11,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010001f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd6,
.pri_id = 0x02,
.dev_size = 0x12,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010003f,
0x00000000
}
},
{
.mfr = CFI_MFR_SST,
.id = 0xd7,
.pri_id = 0x02,
.dev_size = 0x13,
.interface_desc = 0x0,
.max_buf_write_size = 0x0,
.num_erase_regions = 1,
.erase_region_info =
{
0x0010007f,
0x00000000
}
},
{
.mfr = 0,
.id = 0,
}
};

void cfi_fixup_non_cfi(flash_bank_t *bank, void *param)
{
cfi_flash_bank_t *cfi_info = bank->driver_priv;
non_cfi_t *non_cfi = non_cfi_flashes;
while (non_cfi->mfr)
{
if ((cfi_info->manufacturer == non_cfi->mfr)
&& (cfi_info->device_id == non_cfi->id))
{
break;
}
non_cfi++;
}
cfi_info->not_cfi = 1;
/* fill in defaults for non-critical data */
cfi_info->vcc_min = 0x0;
cfi_info->vcc_max = 0x0;
cfi_info->vpp_min = 0x0;
cfi_info->vpp_max = 0x0;
cfi_info->word_write_timeout_typ = 0x0;
cfi_info->buf_write_timeout_typ = 0x0;
cfi_info->block_erase_timeout_typ = 0x0;
cfi_info->chip_erase_timeout_typ = 0x0;
cfi_info->word_write_timeout_max = 0x0;
cfi_info->buf_write_timeout_max = 0x0;
cfi_info->block_erase_timeout_max = 0x0;
cfi_info->chip_erase_timeout_max = 0x0;
cfi_info->qry[0] = 'Q';
cfi_info->qry[1] = 'R';
cfi_info->qry[2] = 'Y';
cfi_info->pri_id = non_cfi->pri_id;
cfi_info->pri_addr = 0x0;
cfi_info->alt_id = 0x0;
cfi_info->alt_addr = 0x0;
cfi_info->alt_ext = NULL;
cfi_info->interface_desc = non_cfi->interface_desc;
cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
cfi_info->num_erase_regions = non_cfi->num_erase_regions;
cfi_info->erase_region_info = non_cfi->erase_region_info;
if (cfi_info->pri_id == 0x2)
{
cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));

pri_ext->pri[0] = 'P';
pri_ext->pri[1] = 'R';
pri_ext->pri[2] = 'I';
pri_ext->major_version = '1';
pri_ext->minor_version = '0';
pri_ext->SiliconRevision = 0x0;
pri_ext->EraseSuspend = 0x0;
pri_ext->EraseSuspend = 0x0;
pri_ext->BlkProt = 0x0;
pri_ext->TmpBlkUnprotect = 0x0;
pri_ext->BlkProtUnprot = 0x0;
pri_ext->SimultaneousOps = 0x0;
pri_ext->BurstMode = 0x0;
pri_ext->PageMode = 0x0;
pri_ext->VppMin = 0x0;
pri_ext->VppMax = 0x0;
pri_ext->TopBottom = 0x0;
pri_ext->_reversed_geometry = 0;
cfi_info->pri_ext = pri_ext;
} else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
{
ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
exit(-1);
}
}


+ 41
- 0
src/flash/non_cfi.h View File

@@ -0,0 +1,41 @@
/***************************************************************************
* Copyright (C) 2007 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef NON_CFI_H
#define NON_CFI_H

#include "types.h"

typedef struct non_cfi_s
{
u16 mfr;
u16 id;
u16 pri_id;
u8 dev_size;
u16 interface_desc;
u16 max_buf_write_size;
u8 num_erase_regions;
u32 erase_region_info[6];
} non_cfi_t;

extern non_cfi_t non_cfi_flashes[];
extern void cfi_fixup_non_cfi(flash_bank_t *bank, void *param);

#endif /* NON_CFI_H */


+ 5
- 269
src/helper/fileio.c View File

@@ -98,7 +98,7 @@ int fileio_open_local(fileio_t *fileio)
}
}
if (fileio->pri_type == FILEIO_IMAGE)
if (fileio->type == FILEIO_BINARY)
strcat(access, "b");
if (!(fileio_local->file = fopen(fileio->url, access)))
@@ -120,126 +120,7 @@ int fileio_open_local(fileio_t *fileio)
return ERROR_OK;
}

//#ifdef FILEIO_BUFFER_COMPLETE_IHEX
int fileio_ihex_buffer_complete(fileio_t *fileio)
{
fileio_image_t *image = fileio->pri_type_private;
fileio_ihex_t *ihex = fileio->sec_type_private;
u32 raw_bytes_read, raw_bytes;
int retval;
u32 full_address = image->base_address;
char *buffer = malloc(ihex->raw_size);
u32 cooked_bytes = 0x0;
ihex->raw_size = fileio->size;
ihex->buffer = malloc(ihex->raw_size >> 1);
if ((retval = fileio_dispatch_read(fileio, ihex->raw_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)
{
free(buffer);
ERROR("failed buffering complete IHEX file, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
}
raw_bytes = 0x0;
while (raw_bytes < raw_bytes_read)
{
u32 count;
u32 address;
u32 record_type;
u32 checksum;
if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
{
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid IHEX record");
return ERROR_FILEIO_OPERATION_FAILED;
}
raw_bytes += 9;
if (record_type == 0)
{
if ((full_address & 0xffff) != address)
{
free(buffer);
ERROR("can't handle non-linear IHEX file");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
return ERROR_FILEIO_OPERATION_FAILED;
}
while (count-- > 0)
{
sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
raw_bytes += 2;
cooked_bytes += 1;
full_address++;
}
}
else if (record_type == 1)
{
free(buffer);
fileio->size = cooked_bytes;
return ERROR_OK;
}
else if (record_type == 4)
{
u16 upper_address;
sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
raw_bytes += 4;
if ((full_address >> 16) != upper_address)
{
free(buffer);
ERROR("can't handle non-linear IHEX file");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't handle non-linear IHEX file");
return ERROR_FILEIO_OPERATION_FAILED;
}
}
else if (record_type == 5)
{
u32 start_address;
sscanf(&buffer[raw_bytes], "%8x", &start_address);
raw_bytes += 8;
image->has_start_address = 1;
image->start_address = be_to_h_u32((u8*)&start_address);
}
else
{
free(buffer);
ERROR("unhandled IHEX record type: %i", record_type);
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "unhandled IHEX record type: %i", record_type);
return ERROR_FILEIO_OPERATION_FAILED;
}
sscanf(&buffer[raw_bytes], "%2x", &checksum);
raw_bytes += 2;
/* consume new-line character(s) */
if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
raw_bytes++;

if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
raw_bytes++;
}

free(buffer);
ERROR("premature end of IHEX file, no end-of-file record found");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "premature end of IHEX file, no end-of-file record found");
return ERROR_FILEIO_OPERATION_FAILED;
}
//#endif

int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
enum fileio_pri_type pri_type, void *pri_info, enum fileio_sec_type sec_type)
int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type)
{
int retval = ERROR_OK;
char *resource_identifier = NULL;
@@ -261,9 +142,8 @@ int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
fileio->location = FILEIO_LOCAL;
}
fileio->type = type;
fileio->access = access;
fileio->pri_type = pri_type;
fileio->sec_type = sec_type;
fileio->url = strdup(url);
switch (fileio->location)
@@ -279,50 +159,6 @@ int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
if (retval != ERROR_OK)
return retval;
if (fileio->pri_type == FILEIO_TEXT)
{
/* do nothing for now */
return ERROR_OK;
}
else if (fileio->pri_type == FILEIO_IMAGE)
{
fileio_image_t *image = malloc(sizeof(fileio_image_t));
fileio_image_t *image_info = pri_info;
fileio->pri_type_private = image;
*image = *image_info;
if (fileio->sec_type == FILEIO_PLAIN)
{
fileio->sec_type_private = NULL;
}
else if (fileio->sec_type == FILEIO_IHEX)
{
fileio_ihex_t *fileio_ihex;
if (fileio->access != FILEIO_READ)
{
ERROR("can't write/append to a IHEX file");
snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "can't write/append to a IHEX file");
fileio_close(fileio);
return ERROR_FILEIO_OPERATION_FAILED;
}
fileio_ihex = malloc(sizeof(fileio_ihex_t));
fileio->sec_type_private = fileio_ihex;
fileio_ihex->position = 0;
fileio_ihex->raw_size = fileio->size;
#ifdef FILEIO_BUFFER_COMPLETE_IHEX
if (fileio_ihex_buffer_complete(fileio) != ERROR_OK)
{
fileio_close(fileio);
return ERROR_FILEIO_OPERATION_FAILED;
}
#endif
}
}
return ERROR_OK;
}

@@ -369,29 +205,6 @@ int fileio_close(fileio_t *fileio)
free(fileio->url);
if (fileio->pri_type == FILEIO_TEXT)
{
/* do nothing for now */
}
else if (fileio->pri_type == FILEIO_IMAGE)
{
if (fileio->sec_type == FILEIO_PLAIN)
{
/* nothing special to do for plain binary */
}
else if (fileio->sec_type == FILEIO_IHEX)
{
fileio_ihex_t *fileio_ihex = fileio->sec_type_private;
if (fileio_ihex->buffer)
free(fileio_ihex->buffer);
free(fileio->sec_type_private);
}
free(fileio->pri_type_private);
}
return ERROR_OK;
}

@@ -432,7 +245,7 @@ int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
return ERROR_OK;
}

int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
{
switch (fileio->location)
{
@@ -445,38 +258,6 @@ int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
}
}

int fileio_read_ihex(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
{
fileio_ihex_t *fileio_ihex = fileio->sec_type_private;

if ((fileio_ihex->position + size) > fileio->size)
{
/* don't read past the end of the file */
size = (fileio->size - fileio_ihex->position);
}
#ifdef FILEIO_BUFFER_COMPLETE_IHEX
memcpy(buffer, fileio_ihex->buffer + fileio_ihex->position, size);
*size_read = size;
#endif

return ERROR_OK;
}

int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
{
if (fileio->sec_type == FILEIO_PLAIN)
{
return fileio_dispatch_read(fileio, size, buffer, size_read);
}
else if (fileio->sec_type == FILEIO_IHEX)
{
return fileio_read_ihex(fileio, size, buffer, size_read);
}
return ERROR_OK;
}

int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
{
fileio_local_t *fileio_local = fileio->location_private;
@@ -486,7 +267,7 @@ int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written
return ERROR_OK;
}

int fileio_dispatch_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
{
switch (fileio->location)
{
@@ -499,48 +280,3 @@ int fileio_dispatch_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_writ
return ERROR_OK;
}

int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
{
int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
if (fileio->sec_type == FILEIO_PLAIN)
{
retval = fileio_dispatch_write(fileio, size, buffer, size_written);
}
else if (fileio->sec_type == FILEIO_IHEX)
{
return ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
}
if (retval != ERROR_OK)
return retval;
fileio->size += size;
return ERROR_OK;
}

int fileio_identify_image_type(enum fileio_sec_type *sec_type, char *type_string)
{
if (type_string)
{
if (!strcmp(type_string, "bin"))
{
*sec_type = FILEIO_PLAIN;
}
else if (!strcmp(type_string, "ihex"))
{
*sec_type = FILEIO_IHEX;
}
else
{
return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
}
}
else
{
*sec_type = FILEIO_PLAIN;
}
return ERROR_OK;
}

+ 12
- 45
src/helper/fileio.h View File

@@ -22,28 +22,20 @@

#define FILEIO_MAX_ERROR_STRING (128)

/* make buffering of complete intel-hex format files optional
* to account for resource-limited hosts
*/
#define FILEIO_BUFFER_COMPLETE_IHEX
#include "types.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>

enum fileio_pri_type
{
FILEIO_TEXT = 0x1,
FILEIO_IMAGE = 0x2,
};

enum fileio_sec_type
enum fileio_type
{
FILEIO_PLAIN = 0x10,
FILEIO_IHEX = 0x20,
/*
* Possible future enhancements:
* FILEIO_ELF,
* FILEIO_SRECORD,
*/
FILEIO_TEXT,
FILEIO_BINARY,
};

enum fileio_location
@@ -73,48 +65,23 @@ typedef struct fileio_s
char *url;
char error_str[FILEIO_MAX_ERROR_STRING];
long long size;
enum fileio_pri_type pri_type;
enum fileio_sec_type sec_type;
enum fileio_type type;
enum fileio_location location;
enum fileio_access access;
void *location_private;
void *pri_type_private;
void *sec_type_private;
} fileio_t;

typedef struct fileio_text_s
{
} fileio_text_t;

typedef struct fileio_image_s
{
u32 base_address;
int has_start_address;
u32 start_address;
} fileio_image_t;

typedef struct fileio_local_s
{
FILE *file;
struct stat file_stat;
} fileio_local_t;

typedef struct fileio_ihex_s
{
u32 position;
u32 raw_size;
#ifdef FILEIO_BUFFER_COMPLETE_IHEX
u8 *buffer;
#endif
} fileio_ihex_t;

extern int fileio_identify_image_type(enum fileio_sec_type *sec_type, char *type_string);
extern int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written);
extern int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
extern int fileio_seek(fileio_t *fileio, u32 position);
extern int fileio_close(fileio_t *fileio);
extern int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
enum fileio_pri_type pri_type, void *pri_info, enum fileio_sec_type sec_type);
extern int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type);
#define ERROR_FILEIO_LOCATION_UNKNOWN (-1200)
#define ERROR_FILEIO_NOT_FOUND (-1201)


+ 1
- 0
src/jtag/jtag.c View File

@@ -1282,6 +1282,7 @@ int jtag_examine_chain()
{
ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)",
device_count, jtag_num_devices);
ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
exit(-1);
}


+ 1
- 1
src/openocd.c View File

@@ -18,7 +18,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#define OPENOCD_VERSION "Open On-Chip Debugger (2007-04-26 16:40 CEST)"
#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-29 13:15 CEST)"

#ifdef HAVE_CONFIG_H
#include "config.h"


+ 2
- 2
src/target/Makefile.am View File

@@ -3,7 +3,7 @@ METASOURCES = AUTO
noinst_LIBRARIES = libtarget.a
libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c
arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c image.c
noinst_HEADERS = target.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h
arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h

+ 3
- 82
src/target/arm7_9_common.c View File

@@ -2096,8 +2096,6 @@ int arm7_9_register_commands(struct command_context_s *cmd_ctx)
arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, "arm7/9 specific commands");

register_command(cmd_ctx, arm7_9_cmd, "etm", handle_arm7_9_etm_command, COMMAND_CONFIG, NULL);
register_command(cmd_ctx, arm7_9_cmd, "write_xpsr", handle_arm7_9_write_xpsr_command, COMMAND_EXEC, "write program status register <value> <not cpsr|spsr>");
register_command(cmd_ctx, arm7_9_cmd, "write_xpsr_im8", handle_arm7_9_write_xpsr_im8_command, COMMAND_EXEC, "write program status register <8bit immediate> <rotate> <not cpsr|spsr>");
@@ -2115,7 +2113,8 @@ int arm7_9_register_commands(struct command_context_s *cmd_ctx)
COMMAND_ANY, "use DCC downloads for larger memory writes <enable|disable>");

armv4_5_register_commands(cmd_ctx);
etb_register_commands(cmd_ctx, arm7_9_cmd);
etm_register_commands(cmd_ctx);
return ERROR_OK;
}
@@ -2425,83 +2424,6 @@ int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char
return ERROR_OK;
}

int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
target_t *target;
armv4_5_common_t *armv4_5;
arm7_9_common_t *arm7_9;
if (argc != 1)
{
ERROR("incomplete 'arm7_9 etm <target>' command");
exit(-1);
}
target = get_target_by_num(strtoul(args[0], NULL, 0));
if (!target)
{
ERROR("target number '%s' not defined", args[0]);
exit(-1);
}
if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
{
command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
return ERROR_OK;
}
arm7_9->has_etm = 1;
return ERROR_OK;
}

int handle_arm7_9_etb_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
target_t *target;
jtag_device_t *jtag_device;
armv4_5_common_t *armv4_5;
arm7_9_common_t *arm7_9;
if (argc != 2)
{
ERROR("incomplete 'arm7_9 etb <target> <chain_pos>' command");
exit(-1);
}
target = get_target_by_num(strtoul(args[0], NULL, 0));
if (!target)
{
ERROR("target number '%s' not defined", args[0]);
exit(-1);
}
if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
{
command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
return ERROR_OK;
}
jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));
if (!jtag_device)
{
ERROR("jtag device number '%s' not defined", args[1]);
exit(-1);
}

arm7_9->etb = malloc(sizeof(etb_t));
arm7_9->etb->chain_pos = strtoul(args[1], NULL, 0);
arm7_9->etb->cur_scan_chain = -1;
arm7_9->etb->reg_cache = NULL;
arm7_9->etb->RAM_width = 0;
arm7_9->etb->RAM_depth = 0;

return ERROR_OK;
}

int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
{
armv4_5_common_t *armv4_5 = &arm7_9->armv4_5_common;
@@ -2515,8 +2437,7 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
arm7_9->force_hw_bkpts = 0;
arm7_9->use_dbgrq = 0;
arm7_9->has_etm = 0;
arm7_9->etb = NULL;
arm7_9->etm_ctx = NULL;
arm7_9->has_single_step = 0;
arm7_9->has_monitor_mode = 0;
arm7_9->has_vector_catch = 0;


+ 3
- 4
src/target/arm7_9_common.h View File

@@ -25,7 +25,7 @@
#include "breakpoints.h"
#include "target.h"

#include "etb.h"
#include "etm.h"

#define ARM7_9_COMMON_MAGIC 0x0a790a79

@@ -35,7 +35,6 @@ typedef struct arm7_9_common_s
arm_jtag_t jtag_info;
reg_cache_t *eice_cache;
reg_cache_t *etm_cache;
u32 arm_bkpt;
u16 thumb_bkpt;
@@ -48,8 +47,8 @@ typedef struct arm7_9_common_s
int dbgreq_adjust_pc;
int use_dbgrq;
int has_etm;
etb_t *etb;
etm_context_t *etm_ctx;
int has_single_step;
int has_monitor_mode;
int has_vector_catch;


+ 3
- 3
src/target/arm7tdmi.c View File

@@ -744,10 +744,10 @@ void arm7tdmi_build_reg_cache(target_t *target)
(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
arm7_9->eice_cache = (*cache_p)->next;
if (arm7_9->has_etm)
if (arm7_9->etm_ctx)
{
(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, 0);
arm7_9->etm_cache = (*cache_p)->next->next;
(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
}
}



+ 3
- 9
src/target/arm9tdmi.c View File

@@ -874,16 +874,10 @@ void arm9tdmi_build_reg_cache(target_t *target)
(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
arm7_9->eice_cache = (*cache_p)->next;

if (arm7_9->has_etm)
if (arm7_9->etm_ctx)
{
(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, 0);
arm7_9->etm_cache = (*cache_p)->next->next;
}
if (arm7_9->etb)
{
(*cache_p)->next->next->next = etb_build_reg_cache(arm7_9->etb);
arm7_9->etb->reg_cache = (*cache_p)->next->next->next;
(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
}
}



+ 776
- 11
src/target/arm_disassembler.c View File

@@ -343,7 +343,10 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
if (!I) /* #+-<offset_12> */
{
u32 offset_12 = (opcode & 0xfff);
snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_12);
if (offset_12)
snprintf(offset, 32, ", #%s0x%x", (U) ? "" : "-", offset_12);
else
snprintf(offset, 32, "");
instruction->info.load_store.offset_mode = 0;
instruction->info.load_store.offset.offset = offset_12;
@@ -376,26 +379,26 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)

if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
{
snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
}
else /* +-<Rm>, <Shift>, #<shift_imm> */
{
switch (shift)
{
case 0x0: /* LSL */
snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
break;
case 0x1: /* LSR */
snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
break;
case 0x2: /* ASR */
snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
break;
case 0x3: /* ROR */
snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
break;
case 0x4: /* RRX */
snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
break;
}
}
@@ -405,7 +408,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
{
if (W == 0) /* offset */
{
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]",
address, opcode, operation, COND(opcode), suffix,
Rd, Rn, offset);
@@ -413,7 +416,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
}
else /* pre-indexed */
{
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]!",
address, opcode, operation, COND(opcode), suffix,
Rd, Rn, offset);
@@ -422,7 +425,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
}
else /* post-indexed */
{
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i]%s",
address, opcode, operation, COND(opcode), suffix,
Rd, Rn, offset);
@@ -1157,7 +1160,10 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
}
else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
{
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
if (opcode==0xe1a00000) /* print MOV r0,r0 as NOP */
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tNOP",address, opcode);
else
snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
address, opcode, mnemonic, COND(opcode),
(S) ? "S" : "", Rd, shifter_operand);
}
@@ -1315,3 +1321,762 @@ int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
return -1;
}

int evaluate_b_bl_blx_thumb(u16 opcode, u32 address, arm_instruction_t *instruction)
{
u32 offset = opcode & 0x7ff;
u32 opc = (opcode >> 11) & 0x3;
u32 target_address;
char *mnemonic = NULL;
/* sign extend 11-bit offset */
if (((opc==0) || (opc==2)) && (offset & 0x00000400))
offset = 0xfffff800 | offset;
target_address = address + 4 + (offset<<1);

switch(opc)
{
/* unconditional branch */
case 0:
instruction->type = ARM_B;
mnemonic = "B";
break;
/* BLX suffix */
case 1:
instruction->type = ARM_BLX;
mnemonic = "BLX";
break;
/* BL/BLX prefix */
case 2:
instruction->type = ARM_UNKNOWN_INSTUCTION;
mnemonic = "prefix";
target_address = offset<<12;
break;
/* BL suffix */
case 3:
instruction->type = ARM_BL;
mnemonic = "BL";
break;
}
/* TODO: deals correctly with dual opcodes BL/BLX ... */

snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s 0x%8.8x", address, opcode,mnemonic, target_address);
instruction->info.b_bl_bx_blx.reg_operand = -1;
instruction->info.b_bl_bx_blx.target_address = target_address;

return ERROR_OK;
}

int evaluate_add_sub_thumb(u16 opcode, u32 address, arm_instruction_t *instruction)
{
u8 Rd = (opcode >> 0) & 0x7;
u8 Rn = (opcode >> 3) & 0x7;
u8 Rm_imm = (opcode >> 6) & 0x7;
u32 opc = opcode & (1<<9);
u32 reg_imm = opcode & (1<<10);
char *mnemonic;
if (opc)
{
instruction->type = ARM_SUB;
mnemonic = "SUBS";
}
else