X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm7_9_common.c;h=ff95a0cd7ebc6063df107925b75f4c7cc0e58398;hp=ce2d4f027fac0fcad4315eda5b5b9d2981d5f137;hb=ec93209f51afc09e273a4742dc0b5f2cefc15e76;hpb=ef746e27c55c14b7a4f6381c490e5c175e409c0b diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index ce2d4f027f..ff95a0cd7e 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -30,14 +30,35 @@ #include "config.h" #endif +#include "breakpoints.h" #include "embeddedice.h" #include "target_request.h" -#include "arm7_9_common.h" +#include "etm.h" #include "time_support.h" #include "arm_simulator.h" +#include "algorithm.h" +#include "register.h" -int arm7_9_debug_entry(struct target *target); +/** + * @file + * Hold common code supporting the ARM7 and ARM9 core generations. + * + * While the ARM core implementations evolved substantially during these + * two generations, they look quite similar from the JTAG perspective. + * Both have similar debug facilities, based on the same two scan chains + * providing access to the core and to an EmbeddedICE module. Both can + * support similar ETM and ETB modules, for tracing. And both expose + * what could be viewed as "ARM Classic", with multiple processor modes, + * shadowed registers, and support for the Thumb instruction set. + * + * Processor differences include things like presence or absence of MMU + * and cache, pipeline sizes, use of a modified Harvard Architecure + * (with separate instruction and data busses from the CPU), support + * for cpu clock gating during idle, and more. + */ + +static int arm7_9_debug_entry(struct target *target); /** * Clear watchpoints for an ARM7/9 target. @@ -166,39 +187,6 @@ int arm7_9_setup(struct target *target) return arm7_9_clear_watchpoints(arm7_9); } -/** - * Retrieves the architecture information pointers for ARMv4/5 and ARM7/9 - * targets. A return of ERROR_OK signifies that the target is a valid target - * and that the pointers have been set properly. - * - * @param target Pointer to the target device to get the pointers from - * @param armv4_5_p Pointer to be filled in with the common struct for ARMV4/5 - * targets - * @param arm7_9_p Pointer to be filled in with the common struct for ARM7/9 - * targets - * @return ERROR_OK if successful - */ -int arm7_9_get_arch_pointers(struct target *target, struct arm **armv4_5_p, struct arm7_9_common **arm7_9_p) -{ - struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; - - /* FIXME stop using this routine; just target_to_arm7_9() and - * verify the resulting pointer using a replacement routine - * that emits a usage message. - */ - if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) - return ERROR_TARGET_INVALID; - - if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC) - return ERROR_TARGET_INVALID; - - *armv4_5_p = armv4_5; - *arm7_9_p = arm7_9; - - return ERROR_OK; -} - /** * Set either a hardware or software breakpoint on an ARM7/9 target. The * breakpoint is set up even if it is already set. Some actions, e.g. reset, @@ -1344,7 +1332,7 @@ int arm7_9_halt(struct target *target) * @param target Pointer to target that is entering debug mode * @return Error code if anything fails, otherwise ERROR_OK */ -int arm7_9_debug_entry(struct target *target) +static int arm7_9_debug_entry(struct target *target) { int i; uint32_t context[16]; @@ -1432,7 +1420,8 @@ int arm7_9_debug_entry(struct target *target) return ERROR_TARGET_FAILURE; } - LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]); + LOG_DEBUG("target entered debug state in %s mode", + arm_mode_name(armv4_5->core_mode)); if (armv4_5->core_state == ARMV4_5_STATE_THUMB) { @@ -1625,7 +1614,8 @@ int arm7_9_restore_context(struct target *target) */ for (i = 0; i < 6; i++) { - LOG_DEBUG("examining %s mode", armv4_5_mode_strings[i]); + LOG_DEBUG("examining %s mode", + arm_mode_name(armv4_5->core_mode)); dirty = 0; mode_change = 0; /* check if there are dirty registers in the current mode @@ -1687,7 +1677,10 @@ int arm7_9_restore_context(struct target *target) num_regs++; reg->dirty = 0; reg->valid = 1; - LOG_DEBUG("writing register %i of mode %s with value 0x%8.8" PRIx32 "", j, armv4_5_mode_strings[i], regs[j]); + LOG_DEBUG("writing register %i mode %s " + "with value 0x%8.8" PRIx32, j, + arm_mode_name(armv4_5->core_mode), + regs[j]); } } @@ -2721,185 +2714,70 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t c return retval; } -int arm7_9_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum) +/** + * Perform per-target setup that requires JTAG access. + */ +int arm7_9_examine(struct target *target) { - struct working_area *crc_algorithm; - struct armv4_5_algorithm armv4_5_info; - struct reg_param reg_params[2]; + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval; - static const uint32_t arm7_9_crc_code[] = { - 0xE1A02000, /* mov r2, r0 */ - 0xE3E00000, /* mov r0, #0xffffffff */ - 0xE1A03001, /* mov r3, r1 */ - 0xE3A04000, /* mov r4, #0 */ - 0xEA00000B, /* b ncomp */ - /* nbyte: */ - 0xE7D21004, /* ldrb r1, [r2, r4] */ - 0xE59F7030, /* ldr r7, CRC32XOR */ - 0xE0200C01, /* eor r0, r0, r1, asl 24 */ - 0xE3A05000, /* mov r5, #0 */ - /* loop: */ - 0xE3500000, /* cmp r0, #0 */ - 0xE1A06080, /* mov r6, r0, asl #1 */ - 0xE2855001, /* add r5, r5, #1 */ - 0xE1A00006, /* mov r0, r6 */ - 0xB0260007, /* eorlt r0, r6, r7 */ - 0xE3550008, /* cmp r5, #8 */ - 0x1AFFFFF8, /* bne loop */ - 0xE2844001, /* add r4, r4, #1 */ - /* ncomp: */ - 0xE1540003, /* cmp r4, r3 */ - 0x1AFFFFF1, /* bne nbyte */ - /* end: */ - 0xEAFFFFFE, /* b end */ - 0x04C11DB7 /* CRC32XOR: .word 0x04C11DB7 */ - }; + if (!target_was_examined(target)) { + struct reg_cache *t, **cache_p; - uint32_t i; + t = embeddedice_build_reg_cache(target, arm7_9); + if (t == NULL) + return ERROR_FAIL; - if (target_alloc_working_area(target, sizeof(arm7_9_crc_code), &crc_algorithm) != ERROR_OK) - { - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } + cache_p = register_get_last_cache_p(&target->reg_cache); + (*cache_p) = t; + arm7_9->eice_cache = (*cache_p); - /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(arm7_9_crc_code)/sizeof(uint32_t)); i++) - { - if ((retval = target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), arm7_9_crc_code[i])) != ERROR_OK) - { - return retval; - } - } - - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; - armv4_5_info.core_state = ARMV4_5_STATE_ARM; - - init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - - buf_set_u32(reg_params[0].value, 0, 32, address); - buf_set_u32(reg_params[1].value, 0, 32, count); - - /* 20 second timeout/megabyte */ - int timeout = 20000 * (1 + (count / (1024*1024))); + if (arm7_9->armv4_5_common.etm) + (*cache_p)->next = etm_build_reg_cache(target, + &arm7_9->jtag_info, + arm7_9->armv4_5_common.etm); - if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), timeout, &armv4_5_info)) != ERROR_OK) - { - LOG_ERROR("error executing arm7_9 crc algorithm"); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - target_free_working_area(target, crc_algorithm); - return retval; + target_set_examined(target); } - *checksum = buf_get_u32(reg_params[0].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - - target_free_working_area(target, crc_algorithm); - - return ERROR_OK; + retval = embeddedice_setup(target); + if (retval == ERROR_OK) + retval = arm7_9_setup(target); + if (retval == ERROR_OK && arm7_9->armv4_5_common.etm) + retval = etm_setup(target); + return retval; } -int arm7_9_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank) -{ - struct working_area *erase_check_algorithm; - struct reg_param reg_params[3]; - struct armv4_5_algorithm armv4_5_info; - int retval; - uint32_t i; - - static const uint32_t erase_check_code[] = - { - /* loop: */ - 0xe4d03001, /* ldrb r3, [r0], #1 */ - 0xe0022003, /* and r2, r2, r3 */ - 0xe2511001, /* subs r1, r1, #1 */ - 0x1afffffb, /* bne loop */ - /* end: */ - 0xeafffffe /* b end */ - }; - - /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) - { - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - - /* convert flash writing code into a buffer in target endianness */ - for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint32_t)); i++) - if ((retval = target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t), erase_check_code[i])) != ERROR_OK) - { - return retval; - } - - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; - armv4_5_info.core_state = ARMV4_5_STATE_ARM; - - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - buf_set_u32(reg_params[0].value, 0, 32, address); - - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); - - init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); - - if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &armv4_5_info)) != ERROR_OK) - { - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - target_free_working_area(target, erase_check_algorithm); - return 0; - } - - *blank = buf_get_u32(reg_params[2].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - - target_free_working_area(target, erase_check_algorithm); - - return ERROR_OK; -} COMMAND_HANDLER(handle_arm7_9_write_xpsr_command) { uint32_t value; int spsr; int retval; - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { - command_print(cmd_ctx, "can't write registers while running"); - return ERROR_OK; + command_print(CMD_CTX, "can't write registers while running"); + return ERROR_FAIL; } - if (argc < 2) + if (CMD_ARGC < 2) { - command_print(cmd_ctx, "usage: write_xpsr "); - return ERROR_OK; + command_print(CMD_CTX, "usage: write_xpsr "); + return ERROR_FAIL; } - COMMAND_PARSE_NUMBER(u32, args[0], value); - COMMAND_PARSE_NUMBER(int, args[1], spsr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], spsr); /* if we're writing the CPSR, mask the T bit */ if (!spsr) @@ -2921,31 +2799,30 @@ COMMAND_HANDLER(handle_arm7_9_write_xpsr_im8_command) int rotate; int spsr; int retval; - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { - command_print(cmd_ctx, "can't write registers while running"); - return ERROR_OK; + command_print(CMD_CTX, "can't write registers while running"); + return ERROR_FAIL; } - if (argc < 3) + if (CMD_ARGC < 3) { - command_print(cmd_ctx, "usage: write_xpsr_im8 "); - return ERROR_OK; + command_print(CMD_CTX, "usage: write_xpsr_im8 "); + return ERROR_FAIL; } - COMMAND_PARSE_NUMBER(u32, args[0], value); - COMMAND_PARSE_NUMBER(int, args[1], rotate); - COMMAND_PARSE_NUMBER(int, args[2], spsr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], rotate); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], spsr); arm7_9->write_xpsr_im8(target, value, rotate, spsr); if ((retval = jtag_execute_queue()) != ERROR_OK) @@ -2962,130 +2839,126 @@ COMMAND_HANDLER(handle_arm7_9_write_core_reg_command) uint32_t value; uint32_t mode; int num; - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } if (target->state != TARGET_HALTED) { - command_print(cmd_ctx, "can't write registers while running"); - return ERROR_OK; + command_print(CMD_CTX, "can't write registers while running"); + return ERROR_FAIL; } - if (argc < 3) + if (CMD_ARGC < 3) { - command_print(cmd_ctx, "usage: write_core_reg "); - return ERROR_OK; + command_print(CMD_CTX, "usage: write_core_reg "); + return ERROR_FAIL; } - COMMAND_PARSE_NUMBER(int, args[0], num); - COMMAND_PARSE_NUMBER(u32, args[1], mode); - COMMAND_PARSE_NUMBER(u32, args[2], value); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], num); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mode); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); return arm7_9_write_core_reg(target, num, mode, value); } COMMAND_HANDLER(handle_arm7_9_dbgrq_command) { - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } - if (argc > 0) + if (CMD_ARGC > 0) { - if (strcmp("enable", args[0]) == 0) + if (strcmp("enable", CMD_ARGV[0]) == 0) { arm7_9->use_dbgrq = 1; } - else if (strcmp("disable", args[0]) == 0) + else if (strcmp("disable", CMD_ARGV[0]) == 0) { arm7_9->use_dbgrq = 0; } else { - command_print(cmd_ctx, "usage: arm7_9 dbgrq "); + command_print(CMD_CTX, "usage: arm7_9 dbgrq "); } } - command_print(cmd_ctx, "use of EmbeddedICE dbgrq instead of breakpoint for target halt %s", (arm7_9->use_dbgrq) ? "enabled" : "disabled"); + command_print(CMD_CTX, "use of EmbeddedICE dbgrq instead of breakpoint for target halt %s", (arm7_9->use_dbgrq) ? "enabled" : "disabled"); return ERROR_OK; } COMMAND_HANDLER(handle_arm7_9_fast_memory_access_command) { - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } - if (argc > 0) + if (CMD_ARGC > 0) { - if (strcmp("enable", args[0]) == 0) + if (strcmp("enable", CMD_ARGV[0]) == 0) { arm7_9->fast_memory_access = 1; } - else if (strcmp("disable", args[0]) == 0) + else if (strcmp("disable", CMD_ARGV[0]) == 0) { arm7_9->fast_memory_access = 0; } else { - command_print(cmd_ctx, "usage: arm7_9 fast_memory_access "); + command_print(CMD_CTX, "usage: arm7_9 fast_memory_access "); } } - command_print(cmd_ctx, "fast memory access is %s", (arm7_9->fast_memory_access) ? "enabled" : "disabled"); + command_print(CMD_CTX, "fast memory access is %s", (arm7_9->fast_memory_access) ? "enabled" : "disabled"); return ERROR_OK; } COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command) { - struct target *target = get_current_target(cmd_ctx); - struct arm *armv4_5; - struct arm7_9_common *arm7_9; + struct target *target = get_current_target(CMD_CTX); + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK) + if (!is_arm7_9(arm7_9)) { - command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target"); - return ERROR_OK; + command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + return ERROR_TARGET_INVALID; } - if (argc > 0) + if (CMD_ARGC > 0) { - if (strcmp("enable", args[0]) == 0) + if (strcmp("enable", CMD_ARGV[0]) == 0) { arm7_9->dcc_downloads = 1; } - else if (strcmp("disable", args[0]) == 0) + else if (strcmp("disable", CMD_ARGV[0]) == 0) { arm7_9->dcc_downloads = 0; } else { - command_print(cmd_ctx, "usage: arm7_9 dcc_downloads "); + command_print(CMD_CTX, "usage: arm7_9 dcc_downloads "); } } - command_print(cmd_ctx, "dcc downloads are %s", (arm7_9->dcc_downloads) ? "enabled" : "disabled"); + command_print(CMD_CTX, "dcc downloads are %s", (arm7_9->dcc_downloads) ? "enabled" : "disabled"); return ERROR_OK; }