From: Spencer O. <nt...@us...> - 2010-03-01 00:11:59
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 409e23e39b955d92c8e879143d2b979b7de799e9 (commit) via 57fc63f9f16934be777a14707d518ea9c9c3db80 (commit) via c9560ba19071b2f988b0210ad03e6d9e8eca5edb (commit) via 73c1cff7c242566d995e7b77de0fcec9fe50a6bb (commit) via 8d13a4662647c33901592f699fcf544d88cfe443 (commit) via 9d6ede25ddb0863873f84b6a55f4300891429049 (commit) via 550abe7396f60274ffd0c5f373eda046af9d9a85 (commit) via 4c9f29bd9c9e38c3f495f8c26869f4dfe8fe9983 (commit) via b8d8953ae9995829a61ce7b34e544f004bb23c55 (commit) via a851ce0d6f2b961f94e09746304e0fb0dad6a15f (commit) from 0324eb24967088f753bc2fd997b4c18f4ea988c8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 409e23e39b955d92c8e879143d2b979b7de799e9 Author: Spencer Oliver <nt...@us...> Date: Sun Feb 28 23:06:49 2010 +0000 armv4_5: remove core_type check in mcr/mrc cmd core_type check is not required as the core function will be null for cores that do not support the mcr/mrc functions. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 0488785..1e9a296 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -840,13 +840,6 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_ERR; } - if (arm->core_type == ARM_MODE_THREAD) - { - /* armv7m not supported */ - LOG_ERROR("Unsupported Command"); - return ERROR_OK; - } - if ((argc < 6) || (argc > 7)) { /* FIXME use the command name to verify # params... */ LOG_ERROR("%s: wrong number of arguments", __func__); commit 57fc63f9f16934be777a14707d518ea9c9c3db80 Author: Spencer Oliver <nt...@us...> Date: Sun Feb 28 22:52:06 2010 +0000 cm3-ftest: change to use arm disassemble Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/testing/examples/cortex/cm3-ftest.cfg b/testing/examples/cortex/cm3-ftest.cfg index 2dae249..2c7809d 100644 --- a/testing/examples/cortex/cm3-ftest.cfg +++ b/testing/examples/cortex/cm3-ftest.cfg @@ -63,7 +63,7 @@ proc load_and_run { name halfwords n_instr } { mwh $addr 0xe7fe # disassemble, as sanity check and what's-happening trace - cortex_m3 disassemble 0x20000000 [expr 1 + $n_instr ] + arm disassemble 0x20000000 [expr 1 + $n_instr ] # Assume that block of code is at most 16 halfwords long. # Create a basic table of loop-to-self exception handlers. commit c9560ba19071b2f988b0210ad03e6d9e8eca5edb Author: Spencer Oliver <nt...@us...> Date: Sun Feb 28 22:40:23 2010 +0000 stellaris: recover_command use usleep rather than sleep windows api does not define a posix sleep, use usleep that has an openocd wrapper to the win32 native function. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index b80daed..c9c800e 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -1215,7 +1215,7 @@ COMMAND_HANDLER(stellaris_handle_recover_command) retval = jtag_execute_queue(); /* wait 400+ msec ... OK, "1+ second" is simpler */ - sleep(1); + usleep(1000); /* USER INTERVENTION required for the power cycle * Restarting OpenOCD is likely needed because of mode switching. commit 73c1cff7c242566d995e7b77de0fcec9fe50a6bb Author: Spencer Oliver <nt...@us...> Date: Sun Feb 28 22:37:53 2010 +0000 FT2232: add missing enum when using ftd2xx library Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index 43e7b9f..38195c7 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -86,6 +86,16 @@ /* FT2232 access library includes */ #if BUILD_FT2232_FTD2XX == 1 #include <ftd2xx.h> + +enum ftdi_interface +{ + INTERFACE_ANY = 0, + INTERFACE_A = 1, + INTERFACE_B = 2, + INTERFACE_C = 3, + INTERFACE_D = 4 +}; + #elif BUILD_FT2232_LIBFTDI == 1 #include <ftdi.h> #endif commit 8d13a4662647c33901592f699fcf544d88cfe443 Author: Spencer Oliver <nt...@us...> Date: Fri Feb 26 23:30:30 2010 +0000 semihosting: add armv7m semihosting support do_semihosting and arm_semihosting now check the core type and use the generic arm structure. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 24a4de5..2f50a4a 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -39,6 +39,9 @@ #include "arm.h" #include "armv4_5.h" +#include "arm7_9_common.h" +#include "armv7m.h" +#include "cortex_m3.h" #include "register.h" #include "arm_semihosting.h" #include <helper/binarybuffer.h> @@ -62,14 +65,19 @@ static int open_modeflags[12] = { static int do_semihosting(struct target *target) { - struct arm *armv4_5 = target_to_arm(target); - uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32); - uint32_t r1 = buf_get_u32(armv4_5->core_cache->reg_list[1].value, 0, 32); - uint32_t lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, ARM_MODE_SVC, 14).value, 0, 32); - uint32_t spsr = buf_get_u32(armv4_5->spsr->value, 0, 32);; + struct arm *arm = target_to_arm(target); + uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); + uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); + uint32_t lr, spsr; uint8_t params[16]; int retval, result; + if (is_arm7_9(target_to_arm7_9(target))) + { + lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, ARM_MODE_SVC, 14).value, 0, 32); + spsr = buf_get_u32(arm->spsr->value, 0, 32);; + } + /* * TODO: lots of security issues are not considered yet, such as: * - no validation on target provided file descriptors @@ -105,10 +113,10 @@ static int do_semihosting(struct target *target) * written file */ result = open((char *)fn, open_modeflags[m], 0644); } - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; } else { result = -1; - armv4_5->semihosting_errno = EINVAL; + arm->semihosting_errno = EINVAL; } } break; @@ -120,7 +128,7 @@ static int do_semihosting(struct target *target) else { int fd = target_buffer_get_u32(target, params+0); result = close(fd); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; } break; @@ -159,7 +167,7 @@ static int do_semihosting(struct target *target) uint8_t *buf = malloc(l); if (!buf) { result = -1; - armv4_5->semihosting_errno = ENOMEM; + arm->semihosting_errno = ENOMEM; } else { retval = target_read_buffer(target, a, l, buf); if (retval != ERROR_OK) { @@ -167,7 +175,7 @@ static int do_semihosting(struct target *target) return retval; } result = write(fd, buf, l); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; if (result >= 0) result = l - result; free(buf); @@ -186,10 +194,10 @@ static int do_semihosting(struct target *target) uint8_t *buf = malloc(l); if (!buf) { result = -1; - armv4_5->semihosting_errno = ENOMEM; + arm->semihosting_errno = ENOMEM; } else { result = read(fd, buf, l); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; if (result >= 0) { retval = target_write_buffer(target, a, result, buf); if (retval != ERROR_OK) { @@ -229,7 +237,7 @@ static int do_semihosting(struct target *target) int fd = target_buffer_get_u32(target, params+0); off_t pos = target_buffer_get_u32(target, params+4); result = lseek(fd, pos, SEEK_SET); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; if (result == pos) result = 0; } @@ -244,7 +252,7 @@ static int do_semihosting(struct target *target) struct stat buf; result = fstat(fd, &buf); if (result == -1) { - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; result = -1; break; } @@ -266,10 +274,10 @@ static int do_semihosting(struct target *target) return retval; fn[l] = 0; result = remove((char *)fn); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; } else { result = -1; - armv4_5->semihosting_errno = EINVAL; + arm->semihosting_errno = EINVAL; } } break; @@ -294,10 +302,10 @@ static int do_semihosting(struct target *target) fn1[l1] = 0; fn2[l2] = 0; result = rename((char *)fn1, (char *)fn2); - armv4_5->semihosting_errno = errno; + arm->semihosting_errno = errno; } else { result = -1; - armv4_5->semihosting_errno = EINVAL; + arm->semihosting_errno = EINVAL; } } break; @@ -307,7 +315,7 @@ static int do_semihosting(struct target *target) break; case 0x13: /* SYS_ERRNO */ - result = armv4_5->semihosting_errno; + result = arm->semihosting_errno; break; case 0x15: /* SYS_GET_CMDLINE */ @@ -383,25 +391,37 @@ static int do_semihosting(struct target *target) fprintf(stderr, "semihosting: unsupported call %#x\n", (unsigned) r0); result = -1; - armv4_5->semihosting_errno = ENOTSUP; + arm->semihosting_errno = ENOTSUP; } /* resume execution to the original mode */ - /* return value in R0 */ - buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, result); - armv4_5->core_cache->reg_list[0].dirty = 1; - - /* LR --> PC */ - buf_set_u32(armv4_5->pc->value, 0, 32, lr); - armv4_5->pc->dirty = 1; - - /* saved PSR --> current PSR */ - buf_set_u32(armv4_5->cpsr->value, 0, 32, spsr); - armv4_5->cpsr->dirty = 1; - armv4_5->core_mode = spsr & 0x1f; - if (spsr & 0x20) - armv4_5->core_state = ARM_STATE_THUMB; + if (is_arm7_9(target_to_arm7_9(target))) + { + /* return value in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); + arm->core_cache->reg_list[0].dirty = 1; + + /* LR --> PC */ + buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, lr); + arm->core_cache->reg_list[15].dirty = 1; + + /* saved PSR --> current PSR */ + buf_set_u32(arm->cpsr->value, 0, 32, spsr); + arm->cpsr->dirty = 1; + arm->core_mode = spsr & 0x1f; + if (spsr & 0x20) + arm->core_state = ARM_STATE_THUMB; + } + else + { + /* resume execution, this will be pc+2 to skip over the + * bkpt instruction */ + + /* return result in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); + arm->core_cache->reg_list[0].dirty = 1; + } return target_resume(target, 1, 0, 0, 0); } @@ -425,60 +445,90 @@ int arm_semihosting(struct target *target, int *retval) uint32_t pc, lr, spsr; struct reg *r; - if (!arm->is_semihosting || arm->core_mode != ARM_MODE_SVC) + if (!arm->is_semihosting) return 0; - /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */ - r = arm->pc; - pc = buf_get_u32(r->value, 0, 32); - if (pc != 0x00000008 && pc != 0xffff0008) - return 0; + if (is_arm7_9(target_to_arm7_9(target))) + { + if (arm->core_mode != ARM_MODE_SVC) + return 0; - r = arm_reg_current(arm, 14); - lr = buf_get_u32(r->value, 0, 32); + /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */ + r = arm->pc; + pc = buf_get_u32(r->value, 0, 32); + if (pc != 0x00000008 && pc != 0xffff0008) + return 0; - /* Core-specific code should make sure SPSR is retrieved - * when the above checks pass... - */ - if (!arm->spsr->valid) { - LOG_ERROR("SPSR not valid!"); - *retval = ERROR_FAIL; - return 1; - } + r = arm_reg_current(arm, 14); + lr = buf_get_u32(r->value, 0, 32); - spsr = buf_get_u32(arm->spsr->value, 0, 32); + /* Core-specific code should make sure SPSR is retrieved + * when the above checks pass... + */ + if (!arm->spsr->valid) { + LOG_ERROR("SPSR not valid!"); + *retval = ERROR_FAIL; + return 1; + } - /* check instruction that triggered this trap */ - if (spsr & (1 << 5)) { - /* was in Thumb (or ThumbEE) mode */ - uint8_t insn_buf[2]; - uint16_t insn; + spsr = buf_get_u32(arm->spsr->value, 0, 32); - *retval = target_read_memory(target, lr-2, 2, 1, insn_buf); - if (*retval != ERROR_OK) - return 1; - insn = target_buffer_get_u16(target, insn_buf); + /* check instruction that triggered this trap */ + if (spsr & (1 << 5)) { + /* was in Thumb (or ThumbEE) mode */ + uint8_t insn_buf[2]; + uint16_t insn; + + *retval = target_read_memory(target, lr-2, 2, 1, insn_buf); + if (*retval != ERROR_OK) + return 1; + insn = target_buffer_get_u16(target, insn_buf); - /* SVC 0xab */ - if (insn != 0xDFAB) + /* SVC 0xab */ + if (insn != 0xDFAB) + return 0; + } else if (spsr & (1 << 24)) { + /* was in Jazelle mode */ + return 0; + } else { + /* was in ARM mode */ + uint8_t insn_buf[4]; + uint32_t insn; + + *retval = target_read_memory(target, lr-4, 4, 1, insn_buf); + if (*retval != ERROR_OK) + return 1; + insn = target_buffer_get_u32(target, insn_buf); + + /* SVC 0x123456 */ + if (insn != 0xEF123456) + return 0; + } + } + else if (is_armv7m(target_to_armv7m(target))) + { + uint16_t insn; + + if (target->debug_reason != DBG_REASON_BREAKPOINT) return 0; - } else if (spsr & (1 << 24)) { - /* was in Jazelle mode */ - return 0; - } else { - /* was in ARM mode */ - uint8_t insn_buf[4]; - uint32_t insn; - *retval = target_read_memory(target, lr-4, 4, 1, insn_buf); + r = arm->pc; + pc = buf_get_u32(r->value, 0, 32); + + pc &= ~1; + *retval = target_read_u16(target, pc, &insn); if (*retval != ERROR_OK) return 1; - insn = target_buffer_get_u32(target, insn_buf); - /* SVC 0x123456 */ - if (insn != 0xEF123456) + /* bkpt 0xAB */ + if (insn != 0xBEAB) return 0; } + else + { + LOG_ERROR("Unsupported semi-hosting Target"); + return 0; + } *retval = do_semihosting(target); return 1; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index ec11176..65e03bf 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -469,14 +469,15 @@ int armv7m_arch_state(struct target *target) sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32); LOG_USER("target halted due to %s, current mode: %s %s\n" - "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32, + "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s", debug_reason_name(target), armv7m_mode_strings[armv7m->core_mode], armv7m_exception_string(armv7m->exception_number), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), (ctrl & 0x02) ? 'p' : 'm', - sp); + sp, + arm->is_semihosting ? ", semihosting" : ""); return ERROR_OK; } @@ -529,6 +530,12 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) return cache; } +int armv7m_setup_semihosting(struct target *target, int enable) +{ + /* nothing todo for armv7m */ + return ERROR_OK; +} + /** Sets up target as a generic ARMv7-M core */ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) { @@ -538,6 +545,7 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) arm->core_type = ARM_MODE_THREAD; arm->arch_info = armv7m; + arm->setup_semihosting = armv7m_setup_semihosting; /* FIXME remove v7m-specific r/w core_reg functions; * use the generic ARM core support.. diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 0aa7ac1..aecf371 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -38,7 +38,7 @@ #include "arm_disassembler.h" #include "register.h" #include "arm_opcodes.h" - +#include "arm_semihosting.h" /* NOTE: most of this should work fine for the Cortex-M1 and * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M. @@ -495,6 +495,9 @@ static int cortex_m3_poll(struct target *target) if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK) return retval; + if (arm_semihosting(target, &retval) != 0) + return retval; + target_call_event_callbacks(target, TARGET_EVENT_HALTED); } if (prev_target_state == TARGET_DEBUG_RUNNING) commit 9d6ede25ddb0863873f84b6a55f4300891429049 Author: Spencer Oliver <nt...@us...> Date: Fri Feb 26 23:29:38 2010 +0000 semihosting: move semihosting cmd to arm cmd group Move semihosting cmd to the arm cmd group. Targets that support semihosting will setup the setup_semihosting callback function. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/doc/openocd.texi b/doc/openocd.texi index d54ad12..507498f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6021,6 +6021,18 @@ Display a table of all banked core registers, fetching the current value from ev core mode if necessary. @end deffn +@deffn Command {arm semihosting} [@option{enable}|@option{disable}] +@cindex ARM semihosting +Display status of semihosting, after optionally changing that status. + +Semihosting allows for code executing on an ARM target to use the +I/O facilities on the host computer i.e. the system where OpenOCD +is running. The target application must be linked against a library +implementing the ARM semihosting convention that forwards operation +requests by using a special SVC instruction that is trapped at the +Supervisor Call vector by OpenOCD. +@end deffn + @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 @@ -6073,18 +6085,6 @@ cables (FT2232), but might be unsafe if used with targets running at very low speeds, like the 32kHz startup clock of an AT91RM9200. @end deffn -@deffn Command {arm7_9 semihosting} [@option{enable}|@option{disable}] -@cindex ARM semihosting -Display status of semihosting, after optionally changing that status. - -Semihosting allows for code executing on an ARM target to use the -I/O facilities on the host computer i.e. the system where OpenOCD -is running. The target application must be linked against a library -implementing the ARM semihosting convention that forwards operation -requests by using a special SVC instruction that is trapped at the -Supervisor Call vector by OpenOCD. -@end deffn - @subsection ARM720T specific commands @cindex ARM720T diff --git a/src/target/arm.h b/src/target/arm.h index 6b304e9..ee4bd76 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -132,6 +132,8 @@ struct arm { /** Value to be returned by semihosting SYS_ERRNO request. */ int semihosting_errno; + int (*setup_semihosting)(struct target *target, int enable); + /** Backpointer to the target. */ struct target *target; diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 2176729..f9deb83 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2834,54 +2834,32 @@ COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command) return ERROR_OK; } -COMMAND_HANDLER(handle_arm7_9_semihosting_command) +int arm7_9_setup_semihosting(struct target *target, int enable) { - struct target *target = get_current_target(CMD_CTX); struct arm7_9_common *arm7_9 = target_to_arm7_9(target); if (!is_arm7_9(arm7_9)) { - command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target"); + LOG_USER("current target isn't an ARM7/ARM9 target"); return ERROR_TARGET_INVALID; } - if (CMD_ARGC > 0) - { - int semihosting; - - COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); - - if (!target_was_examined(target)) - { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - if (arm7_9->has_vector_catch) { - struct reg *vector_catch = &arm7_9->eice_cache - ->reg_list[EICE_VEC_CATCH]; - - if (!vector_catch->valid) - embeddedice_read_reg(vector_catch); - buf_set_u32(vector_catch->value, 2, 1, semihosting); - embeddedice_store_reg(vector_catch); - } else { - /* TODO: allow optional high vectors and/or BKPT_HARD */ - if (semihosting) - breakpoint_add(target, 8, 4, BKPT_SOFT); - else - breakpoint_remove(target, 8); - } - - /* FIXME never let that "catch" be dropped! */ - arm7_9->armv4_5_common.is_semihosting = semihosting; + if (arm7_9->has_vector_catch) { + struct reg *vector_catch = &arm7_9->eice_cache + ->reg_list[EICE_VEC_CATCH]; + if (!vector_catch->valid) + embeddedice_read_reg(vector_catch); + buf_set_u32(vector_catch->value, 2, 1, enable); + embeddedice_store_reg(vector_catch); + } else { + /* TODO: allow optional high vectors and/or BKPT_HARD */ + if (enable) + breakpoint_add(target, 8, 4, BKPT_SOFT); + else + breakpoint_remove(target, 8); } - command_print(CMD_CTX, "semihosting is %s", - arm7_9->armv4_5_common.is_semihosting - ? "enabled" : "disabled"); - return ERROR_OK; } @@ -2906,6 +2884,7 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) armv4_5->read_core_reg = arm7_9_read_core_reg; armv4_5->write_core_reg = arm7_9_write_core_reg; armv4_5->full_context = arm7_9_full_context; + armv4_5->setup_semihosting = arm7_9_setup_semihosting; retval = arm_init_arch_info(target, armv4_5); if (retval != ERROR_OK) @@ -2939,13 +2918,6 @@ static const struct command_registration arm7_9_any_command_handlers[] = { .usage = "['enable'|'disable']", .help = "use DCC downloads for larger memory writes", }, - { - "semihosting", - .handler = handle_arm7_9_semihosting_command, - .mode = COMMAND_EXEC, - .usage = "['enable'|'disable']", - .help = "activate support for semihosting operations", - }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm7_9_command_handlers[] = { diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 36101b0..0488785 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -951,6 +951,49 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } +COMMAND_HANDLER(handle_arm_semihosting_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct arm *arm = target ? target_to_arm(target) : NULL; + + if (!is_arm(arm)) { + command_print(CMD_CTX, "current target isn't an ARM"); + return ERROR_FAIL; + } + + if (!arm->setup_semihosting) + { + command_print(CMD_CTX, "semihosting not supported for current target"); + } + + if (CMD_ARGC > 0) + { + int semihosting; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); + + if (!target_was_examined(target)) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (arm->setup_semihosting(target, semihosting) != ERROR_OK) { + LOG_ERROR("Failed to Configure semihosting"); + return ERROR_FAIL; + } + + /* FIXME never let that "catch" be dropped! */ + arm->is_semihosting = semihosting; + } + + command_print(CMD_CTX, "semihosting is %s", + arm->is_semihosting + ? "enabled" : "disabled"); + + return ERROR_OK; +} + static const struct command_registration arm_exec_command_handlers[] = { { .name = "reg", @@ -985,6 +1028,13 @@ static const struct command_registration arm_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn op2 CRm", }, + { + "semihosting", + .handler = handle_arm_semihosting_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting operations", + }, COMMAND_REGISTRATION_DONE }; commit 550abe7396f60274ffd0c5f373eda046af9d9a85 Author: Spencer Oliver <nt...@us...> Date: Fri Feb 26 23:25:55 2010 +0000 CortexM3: move disassemble cmd to arm cmd group Rather than using a Cortex disassemble cmd, we now use the arm generic version. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 9da2977..d54ad12 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6427,12 +6427,6 @@ If @var{value} is defined, first assigns that. @subsection Cortex-M3 specific commands @cindex Cortex-M3 -@deffn Command {cortex_m3 disassemble} address [count] -@cindex disassemble -Disassembles @var{count} Thumb2 instructions starting at @var{address}. -If @var{count} is not specified, a single instruction is disassembled. -@end deffn - @deffn Command {cortex_m3 maskisr} (@option{on}|@option{off}) Control masking (disabling) interrupts during target step/resume. @end deffn diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 3ebc34a..0aa7ac1 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -1899,50 +1899,6 @@ static int cortex_m3_verify_pointer(struct command_context *cmd_ctx, * cortexm3_target structure, which is only used with CM3 targets. */ -/* - * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well - * as at least ARM-1156T2. The interesting thing about Cortex-M is - * that *only* Thumb2 disassembly matters. There are also some small - * additions to Thumb2 that are specific to ARMv7-M. - */ -COMMAND_HANDLER(handle_cortex_m3_disassemble_command) -{ - int retval; - struct target *target = get_current_target(CMD_CTX); - struct cortex_m3_common *cortex_m3 = target_to_cm3(target); - uint32_t address; - unsigned long count = 1; - struct arm_instruction cur_instruction; - - retval = cortex_m3_verify_pointer(CMD_CTX, cortex_m3); - if (retval != ERROR_OK) - return retval; - - errno = 0; - switch (CMD_ARGC) { - case 2: - COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], count); - /* FALL THROUGH */ - case 1: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); - break; - default: - command_print(CMD_CTX, - "usage: cortex_m3 disassemble <address> [<count>]"); - return ERROR_OK; - } - - while (count--) { - retval = thumb2_opcode(target, address, &cur_instruction); - if (retval != ERROR_OK) - return retval; - command_print(CMD_CTX, "%s", cur_instruction.text); - address += cur_instruction.instruction_size; - } - - return ERROR_OK; -} - static const struct { char name[10]; unsigned mask; @@ -2057,13 +2013,6 @@ COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command) static const struct command_registration cortex_m3_exec_command_handlers[] = { { - .name = "disassemble", - .handler = handle_cortex_m3_disassemble_command, - .mode = COMMAND_EXEC, - .help = "disassemble Thumb2 instructions", - .usage = "address [count]", - }, - { .name = "maskisr", .handler = handle_cortex_m3_mask_interrupts_command, .mode = COMMAND_EXEC, commit 4c9f29bd9c9e38c3f495f8c26869f4dfe8fe9983 Author: Spencer Oliver <nt...@us...> Date: Fri Feb 26 23:14:51 2010 +0000 ARMv7M: add arm cmd group - Add arm cmd group to armv7m cmd chain. - arm cmd's now check the core type before running a cmd. - todo: add support for armv7m registers for reg cmd. Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index a4a15b4..36101b0 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -627,6 +627,12 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) return ERROR_FAIL; } + if (armv4_5->core_type != ARM_MODE_ANY) + { + command_print(CMD_CTX, "Microcontroller Profile not supported - use standard reg cmd"); + return ERROR_OK; + } + if (!is_arm_mode(armv4_5->core_mode)) return ERROR_FAIL; @@ -706,6 +712,13 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) return ERROR_FAIL; } + if (armv4_5->core_type == ARM_MODE_THREAD) + { + /* armv7m not supported */ + command_print(CMD_CTX, "Unsupported Command"); + return ERROR_OK; + } + if (CMD_ARGC > 0) { if (strcmp(CMD_ARGV[0], "arm") == 0) @@ -723,7 +736,7 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command) return ERROR_OK; } -COMMAND_HANDLER(handle_armv4_5_disassemble_command) +COMMAND_HANDLER(handle_arm_disassemble_command) { int retval = ERROR_OK; struct target *target = get_current_target(CMD_CTX); @@ -737,6 +750,12 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command) return ERROR_FAIL; } + if (arm->core_type == ARM_MODE_THREAD) + { + /* armv7m is always thumb mode */ + thumb = 1; + } + switch (CMD_ARGC) { case 3: if (strcmp(CMD_ARGV[2], "thumb") != 0) @@ -821,6 +840,13 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_ERR; } + if (arm->core_type == ARM_MODE_THREAD) + { + /* armv7m not supported */ + LOG_ERROR("Unsupported Command"); + return ERROR_OK; + } + if ((argc < 6) || (argc > 7)) { /* FIXME use the command name to verify # params... */ LOG_ERROR("%s: wrong number of arguments", __func__); @@ -941,7 +967,7 @@ static const struct command_registration arm_exec_command_handlers[] = { }, { .name = "disassemble", - .handler = handle_armv4_5_disassemble_command, + .handler = handle_arm_disassemble_command, .mode = COMMAND_EXEC, .usage = "address [count ['thumb']]", .help = "disassemble instructions ", diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 056ac7b..ec11176 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -878,6 +878,9 @@ static const struct command_registration armv7m_exec_command_handlers[] = { }; const struct command_registration armv7m_command_handlers[] = { { + .chain = arm_command_handlers, + }, + { .name = "dap", .mode = COMMAND_EXEC, .help = "Cortex DAP command group", commit b8d8953ae9995829a61ce7b34e544f004bb23c55 Author: Spencer Oliver <nt...@us...> Date: Wed Jan 13 10:12:34 2010 +0000 MIPS: add mips algorithm support - add mips support for target algorithms. - added handlers for target_checksum_memory and target_blank_check_memory. - clean up long lines Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/target/mips32.c b/src/target/mips32.c index 5bb4104..b0cb79c 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -27,6 +27,8 @@ #endif #include "mips32.h" +#include "breakpoints.h" +#include "algorithm.h" #include "register.h" char* mips32_core_reg_list[] = @@ -319,9 +321,168 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s return ERROR_OK; } -int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) +/* run to exit point. return error if exit point was not reached. */ +static int mips32_run_and_wait(struct target *target, uint32_t entry_point, + int timeout_ms, uint32_t exit_point, struct mips32_common *mips32) { - /*TODO*/ + uint32_t pc; + int retval; + /* This code relies on the target specific resume() and poll()->debug_entry() + * sequence to write register values to the processor and the read them back */ + if ((retval = target_resume(target, 0, entry_point, 0, 1)) != ERROR_OK) + { + return retval; + } + + retval = target_wait_state(target, TARGET_HALTED, timeout_ms); + /* If the target fails to halt due to the breakpoint, force a halt */ + if (retval != ERROR_OK || target->state != TARGET_HALTED) + { + if ((retval = target_halt(target)) != ERROR_OK) + return retval; + if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK) + { + return retval; + } + return ERROR_TARGET_TIMEOUT; + } + + pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); + if (pc != exit_point) + { + LOG_DEBUG("failed algoritm halted at 0x%" PRIx32 " ", pc); + return ERROR_TARGET_TIMEOUT; + } + + return ERROR_OK; +} + +int mips32_run_algorithm(struct target *target, int num_mem_params, + struct mem_param *mem_params, int num_reg_params, + struct reg_param *reg_params, uint32_t entry_point, + uint32_t exit_point, int timeout_ms, void *arch_info) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips32_algorithm *mips32_algorithm_info = arch_info; + enum mips32_isa_mode isa_mode = mips32->isa_mode; + + uint32_t context[MIPS32NUMCOREREGS]; + int i; + int retval = ERROR_OK; + + LOG_DEBUG("Running algorithm"); + + /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + if (mips32->common_magic != MIPS32_COMMON_MAGIC) + { + LOG_ERROR("current target isn't a MIPS32 target"); + return ERROR_TARGET_INVALID; + } + + if (target->state != TARGET_HALTED) + { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* refresh core register cache */ + for (unsigned i = 0; i < MIPS32NUMCOREREGS; i++) + { + if (!mips32->core_cache->reg_list[i].valid) + mips32->read_core_reg(target, i); + context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32); + } + + for (i = 0; i < num_mem_params; i++) + { + if ((retval = target_write_buffer(target, mem_params[i].address, + mem_params[i].size, mem_params[i].value)) != ERROR_OK) + { + return retval; + } + } + + for (int i = 0; i < num_reg_params; i++) + { + struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0); + + if (!reg) + { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_INVALID_ARGUMENTS; + } + + if (reg->size != reg_params[i].size) + { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", + reg_params[i].reg_name); + return ERROR_INVALID_ARGUMENTS; + } + + mips32_set_core_reg(reg, reg_params[i].value); + } + + mips32->isa_mode = mips32_algorithm_info->isa_mode; + + retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32); + + if (retval != ERROR_OK) + return retval; + + for (i = 0; i < num_mem_params; i++) + { + if (mem_params[i].direction != PARAM_OUT) + { + if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, + mem_params[i].value)) != ERROR_OK) + { + return retval; + } + } + } + + for (i = 0; i < num_reg_params; i++) + { + if (reg_params[i].direction != PARAM_OUT) + { + struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0); + if (!reg) + { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_INVALID_ARGUMENTS; + } + + if (reg->size != reg_params[i].size) + { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", + reg_params[i].reg_name); + return ERROR_INVALID_ARGUMENTS; + } + + buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); + } + } + + /* restore everything we saved before */ + for (i = 0; i < MIPS32NUMCOREREGS; i++) + { + uint32_t regvalue; + regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32); + if (regvalue != context[i]) + { + LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, + mips32->core_cache->reg_list[i].name, context[i]); + buf_set_u32(mips32->core_cache->reg_list[i].value, + 0, 32, context[i]); + mips32->core_cache->reg_list[i].valid = 1; + mips32->core_cache->reg_list[i].dirty = 1; + } + } + + mips32->isa_mode = isa_mode; + return ERROR_OK; } @@ -397,7 +558,8 @@ int mips32_configure_break_unit(struct target *target) return retval; } - LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints, mips32->num_data_bpoints); + LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints, + mips32->num_data_bpoints); mips32->bp_scanned = 1; @@ -441,3 +603,150 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } + +int mips32_checksum_memory(struct target *target, uint32_t address, + uint32_t count, uint32_t* checksum) +{ + struct working_area *crc_algorithm; + struct reg_param reg_params[2]; + struct mips32_algorithm mips32_info; + int retval; + uint32_t i; + + static const uint32_t mips_crc_code[] = + { + 0x248C0000, /* addiu $t4, $a0, 0 */ + 0x24AA0000, /* addiu $t2, $a1, 0 */ + 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */ + 0x10000010, /* beq $zero, $zero, ncomp */ + 0x240B0000, /* addiu $t3, $zero, 0 */ + /* nbyte: */ + 0x81850000, /* lb $a1, ($t4) */ + 0x218C0001, /* addi $t4, $t4, 1 */ + 0x00052E00, /* sll $a1, $a1, 24 */ + 0x3C0204C1, /* lui $v0, 0x04c1 */ + 0x00852026, /* xor $a0, $a0, $a1 */ + 0x34471DB7, /* ori $a3, $v0, 0x1db7 */ + 0x00003021, /* addu $a2, $zero, $zero */ + /* loop: */ + 0x00044040, /* sll $t0, $a0, 1 */ + 0x24C60001, /* addiu $a2, $a2, 1 */ + 0x28840000, /* slti $a0, $a0, 0 */ + 0x01074826, /* xor $t1, $t0, $a3 */ + 0x0124400B, /* movn $t0, $t1, $a0 */ + 0x28C30008, /* slti $v1, $a2, 8 */ + 0x1460FFF9, /* bne $v1, $zero, loop */ + 0x01002021, /* addu $a0, $t0, $zero */ + /* ncomp: */ + 0x154BFFF0, /* bne $t2, $t3, nbyte */ + 0x256B0001, /* addiu $t3, $t3, 1 */ + 0x7000003F, /* sdbbp */ + }; + + /* make sure we have a working area */ + if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK) + { + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + /* convert flash writing code into a buffer in target endianness */ + for (i = 0; i < ARRAY_SIZE(mips_crc_code); i++) + target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), mips_crc_code[i]); + + mips32_info.common_magic = MIPS32_COMMON_MAGIC; + mips32_info.isa_mode = MIPS32_ISA_MIPS32; + + init_reg_param(®_params[0], "a0", 32, PARAM_IN_OUT); + buf_set_u32(reg_params[0].value, 0, 32, address); + + init_reg_param(®_params[1], "a1", 32, PARAM_OUT); + buf_set_u32(reg_params[1].value, 0, 32, count); + + if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params, + crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code)-4), 10000, + &mips32_info)) != ERROR_OK) + { + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + target_free_working_area(target, crc_algorithm); + return 0; + } + + *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; +} + +/** Checks whether a memory region is zeroed. */ +int mips32_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 mips32_algorithm mips32_info; + int retval; + uint32_t i; + + static const uint32_t erase_check_code[] = + { + /* nbyte: */ + 0x80880000, /* lb $t0, ($a0) */ + 0x00C83024, /* and $a2, $a2, $t0 */ + 0x24A5FFFF, /* addiu $a1, $a1, -1 */ + 0x14A0FFFC, /* bne $a1, $zero, nbyte */ + 0x24840001, /* addiu $a0, $a0, 1 */ + 0x7000003F /* sdbbp */ + }; + + /* 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 < ARRAY_SIZE(erase_check_code); i++) + { + target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t), + erase_check_code[i]); + } + + mips32_info.common_magic = MIPS32_COMMON_MAGIC; + mips32_info.isa_mode = MIPS32_ISA_MIPS32; + + init_reg_param(®_params[0], "a0", 32, PARAM_OUT); + buf_set_u32(reg_params[0].value, 0, 32, address); + + init_reg_param(®_params[1], "a1", 32, PARAM_OUT); + buf_set_u32(reg_params[1].value, 0, 32, count); + + init_reg_param(®_params[2], "a2", 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)-2), + 10000, &mips32_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; +} diff --git a/src/target/mips32.h b/src/target/mips32.h index b731c68..94d29ff 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -85,6 +85,12 @@ struct mips32_core_reg struct mips32_common *mips32_common; }; +struct mips32_algorithm +{ + int common_magic; + enum mips32_isa_mode isa_mode; +}; + #define MIPS32_OP_BEQ 0x04 #define MIPS32_OP_BNE 0x05 #define MIPS32_OP_ADDI 0x08 @@ -164,5 +170,9 @@ int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size); +int mips32_checksum_memory(struct target *target, uint32_t address, + uint32_t count, uint32_t* checksum); +int mips32_blank_check_memory(struct target *target, + uint32_t address, uint32_t count, uint32_t* blank); #endif /*MIPS32_H*/ diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 7d91d42..f20c69e 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -206,7 +206,8 @@ static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t ad return ERROR_OK; } -int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code, int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle) +int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code, + int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle) { uint32_t ejtag_ctrl; uint32_t address, data; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 5f5aa72..f581ddf 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -32,61 +32,6 @@ #include "target_type.h" #include "register.h" -/* cli handling */ - -/* forward declarations */ -int mips_m4k_poll(struct target *target); -int mips_m4k_halt(struct target *target); -int mips_m4k_soft_reset_halt(struct target *target); -int mips_m4k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); -int mips_m4k_step(struct target *target, int current, uint32_t address, int handle_breakpoints); -int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int mips_m4k_init_target(struct command_context *cmd_ctx, struct target *target); -int mips_m4k_target_create(struct target *target, Jim_Interp *interp); - -int mips_m4k_examine(struct target *target); -int mips_m4k_assert_reset(struct target *target); -int mips_m4k_deassert_reset(struct target *target); -int mips_m4k_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *checksum); - -struct target_type mips_m4k_target = -{ - .name = "mips_m4k", - - .poll = mips_m4k_poll, - .arch_state = mips32_arch_state, - - .target_request_data = NULL, - - .halt = mips_m4k_halt, - .resume = mips_m4k_resume, - .step = mips_m4k_step, - - .assert_reset = mips_m4k_assert_reset, - .deassert_reset = mips_m4k_deassert_reset, - .soft_reset_halt = mips_m4k_soft_reset_halt, - - .get_gdb_reg_list = mips32_get_gdb_reg_list, - - .read_memory = mips_m4k_read_memory, - .write_memory = mips_m4k_write_memory, - .bulk_write_memory = mips_m4k_bulk_write_memory, - .checksum_memory = mips_m4k_checksum_memory, - .blank_check_memory = NULL, - - .run_algorithm = mips32_run_algorithm, - - .add_breakpoint = mips_m4k_add_breakpoint, - .remove_breakpoint = mips_m4k_remove_breakpoint, - .add_watchpoint = mips_m4k_add_watchpoint, - .remove_watchpoint = mips_m4k_remove_watchpoint, - - .target_create = mips_m4k_target_create, - .init_target = mips_m4k_init_target, - .examine = mips_m4k_examine, -}; - int mips_m4k_examine_debug_reason(struct target *target) { uint32_t break_status; @@ -148,13 +93,8 @@ int mips_m4k_debug_entry(struct target *target) /* default to mips32 isa, it will be changed below if required */ mips32->isa_mode = MIPS32_ISA_MIPS32; - if (ejtag_info->impcode & EJTAG_IMP_MIPS16) - { - if (buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32) & 0x01) - { - /* core is running mips16e isa */ - mips32->isa_mode = MIPS32_ISA_MIPS16E; - } + if (ejtag_info->impcode & EJTAG_IMP_MIPS16) { + mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1); } LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s", @@ -396,6 +336,10 @@ int mips_m4k_resume(struct target *target, int current, uint32_t address, int ha mips32->core_cache->reg_list[MIPS32_PC].valid = 1; } + if (ejtag_info->impcode & EJTAG_IMP_MIPS16) { + buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode); + } + resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32); mips32_restore_context(target); @@ -457,9 +401,12 @@ int mips_m4k_step(struct target *target, int current, uint32_t address, int hand buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); /* the front-end may request us not to handle breakpoints */ - if (handle_breakpoints) - if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)))) + if (handle_breakpoints) { + breakpoint = breakpoint_find(target, + buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32)); + if (breakpoint) mips_m4k_unset_breakpoint(target, breakpoint); + } /* restore context */ mips32_restore_context(target); @@ -545,7 +492,8 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint { uint32_t verify = 0xffffffff; - if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK) + if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, + breakpoint->orig_instr)) != ERROR_OK) { return retval; } @@ -568,7 +516,8 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint { uint16_t verify = 0xffff; - if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK) + if ((retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, + breakpoint->orig_instr)) != ERROR_OK) { return retval; } @@ -633,13 +582,15 @@ int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoi uint32_t current_instr; /* check that user program has not modified breakpoint instruction */ - if ((retval = target_read_memory(target, breakpoint->address, 4, 1, (uint8_t*)¤t_instr)) != ERROR_OK) + if ((retval = target_read_memory(target, breakpoint->address, 4, 1, + (uint8_t*)¤t_instr)) != ERROR_OK) { return retval; } if (current_instr == MIPS32_SDBBP) { - if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK) + if ((retval = target_write_memory(target, breakpoint->address, 4, 1, + breakpoint->orig_instr)) != ERROR_OK) { return retval; } @@ -650,14 +601,16 @@ int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoi uint16_t current_instr; /* check that user program has not modified breakpoint instruction */ - if ((retval = target_read_memory(target, breakpoint->address, 2, 1, (uint8_t*)¤t_instr)) != ERROR_OK) + if ((retval = target_read_memory(target, breakpoint->address, 2, 1, + (uint8_t*)¤t_instr)) != ERROR_OK) { return retval; } if (current_instr == MIPS16_SDBBP) { - if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK) + if ((retval = target_write_memory(target, breakpoint->address, 2, 1, + breakpoint->orig_instr)) != ERROR_OK) { return retval; } @@ -886,12 +839,14 @@ int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, return ERROR_OK; } -int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) +int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size, + uint32_t count, uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); + LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + address, size, count); if (target->state != TARGET_HALTED) { @@ -920,7 +875,8 @@ int mips_m4k_init_target(struct command_context *cmd_ctx, struct target *target) return ERROR_OK; } -int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_m4k, struct jtag_tap *tap) +int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_m4k, + struct jtag_tap *tap) { struct mips32_common *mips32 = &mips_m4k->mips32_common; @@ -973,7 +929,8 @@ int mips_m4k_examine(struct target *target) return ERROR_OK; } -int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) +int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, + uint32_t count, uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -1012,7 +969,8 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, uint32_t } } - retval = mips32_pracc_fastdata_xfer(ejtag_info, source, write, address, count, (uint32_t*) buffer); + retval = mips32_pracc_fastdata_xfer(ejtag_info, source, write, address, + count, (uint32_t*) buffer); if (retval != ERROR_OK) { /* FASTDATA access failed, try normal memory write */ @@ -1026,7 +984,39 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, uint32_t return retval; } -int mips_m4k_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *checksum) +struct target_type mips_m4k_target = { - return ERROR_FAIL; /* use bulk read method */ -} + .name = "mips_m4k", + + .poll = mips_m4k_poll, + .arch_state = mips32_arch_state, + + .target_request_data = NULL, + + .halt = mips_m4k_halt, + .resume = mips_m4k_resume, + .step = mips_m4k_step, + + .assert_reset = mips_m4k_assert_reset, + .deassert_reset = mips_m4k_deassert_reset, + .soft_reset_halt = mips_m4k_soft_reset_halt, + + .get_gdb_reg_list = mips32_get_gdb_reg_list, + + .read_memory = mips_m4k_read_memory, + .write_memory = mips_m4k_write_memory, + .bulk_write_memory = mips_m4k_bulk_write_memory, + .checksum_memory = mips32_checksum_memory, + .blank_check_memory = mips32_blank_check_memory, + + .run_algorithm = mips32_run_algorithm, + + .add_breakpoint = mips_m4k_add_breakpoint, + .remove_breakpoint = mips_m4k_remove_breakpoint, + .add_watchpoint = mips_m4k_add_watchpoint, + .remove_watchpoint = mips_m4k_remove_watchpoint, + + .target_create = mips_m4k_target_create, + .init_target = mips_m4k_init_target, + .examine = mips_m4k_examine, +}; commit a851ce0d6f2b961f94e09746304e0fb0dad6a15f Author: Spencer Oliver <nt...@us...> Date: Tue Feb 2 13:22:07 2010 +0000 ARMv7M: use software breakpoints for algorithms - armv7m_run_algorithm now requires all algorithms to use a software breakpoint at their exit address - updated all algorithms to support this Signed-off-by: Spencer Oliver <nt...@us...> diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index 1b2f27c..5f013ed 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -2046,9 +2046,7 @@ sam3_page_write_opcodes[] = { 0x10,0xf0,0x01,0x0f, // 41 0024 FBD0 beq .L4 0xfb,0xd0, - // 42 .done: - // 43 0026 FEE7 b .done - 0xfe,0xe7 + 0x00,0xBE /* bkpt #0 */ }; diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index fc2b1cf..6674f17 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -267,7 +267,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12)); target_buffer_set_u32(target, jump_gate + 4, - ARMV4_5_T_B(0xfffffe)); + ARMV5_T_BKPT(0)); break; case lpc2000_v1: case lpc2000_v2: diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 21a0cff..b80daed 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -805,8 +805,7 @@ static const uint8_t stellaris_write_code[] = 0x04,0x36, /* adds r6, r6, #4 */ 0x96,0x42, /* cmp r6, r2 */ 0xF4,0xD1, /* bne mainloop */ - /* exit: */ - 0xFE,0xE7, /* b exit */ + 0x00,0xBE, /* bkpt #0 */ /* pFLASH_CTRL_BASE: */ 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */ /* FLASHWRITECMD: */ diff --git a/src/flash/nor/stm32x.c b/src/flash/nor/stm32x.c index bfdd3cd..53fc4ea 100644 --- a/src/flash/nor/stm32x.c +++ b/src/flash/nor/stm32x.c @@ -459,8 +459,7 @@ static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t 0x01, 0xD1, /* bne exit */ 0x01, 0x3A, /* subs r2, r2, #1 */ 0xED, 0xD1, /* bne write */ - /* exit: */ - 0xFE, 0xE7, /* b exit */ + 0x00, 0xBE, /* bkpt #0 */ 0x10, 0x20, 0x02, 0x40, /* STM32_FLASH_CR: .word 0x40022010 */ 0x0C, 0x20, 0x02, 0x40 /* STM32_FLASH_SR: .word 0x4002200C */ }; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 466c0b2..056ac7b 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -338,6 +338,9 @@ int armv7m_run_algorithm(struct target *target, int retval = ERROR_OK; uint32_t context[ARMV7M_NUM_REGS]; + /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { LOG_ERROR("current target isn't an ARMV7M target"); @@ -395,22 +398,8 @@ int armv7m_run_algorithm(struct target *target, armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1; } - /* REVISIT speed things up (3% or so in one case) by requiring - * algorithms to include a BKPT instruction at each exit point. - * This eliminates overheads of adding/removing a breakpoint. - */ - - /* ARMV7M always runs in Thumb state */ - if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK) - { - LOG_ERROR("can't add breakpoint to finish algorithm execution"); - return ERROR_TARGET_FAILURE; - } - retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m); - breakpoint_remove(target, exit_point); - if (retval != ERROR_OK) { return retval; @@ -594,8 +583,7 @@ int armv7m_checksum_memory(struct target *target, /* ncomp: */ 0x429C, /* cmp r4, r3 */ 0xD1E9, /* bne nbyte */ - /* end: */ - 0xE7FE, /* b end */ + 0xBE00, /* bkpt #0 */ 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */ }; @@ -659,8 +647,7 @@ int armv7m_blank_check_memory(struct target *target, 0xEA02, 0x0203, /* and r2, r2, r3 */ 0x3901, /* subs r1, r1, #1 */ 0xD1F9, /* bne loop */ - /* end: */ - 0xE7FE, /* b end */ + 0xBE00, /* bkpt #0 */ }; /* make sure we have a working area */ ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 30 ++-- src/flash/nor/at91sam3.c | 4 +- src/flash/nor/lpc2000.c | 2 +- src/flash/nor/stellaris.c | 5 +- src/flash/nor/stm32x.c | 3 +- src/jtag/drivers/ft2232.c | 10 + src/target/arm.h | 2 + src/target/arm7_9_common.c | 60 ++----- src/target/arm_semihosting.c | 196 +++++++++++++-------- src/target/armv4_5.c | 73 ++++++++- src/target/armv7m.c | 38 ++-- src/target/cortex_m3.c | 56 +------ src/target/mips32.c | 315 ++++++++++++++++++++++++++++++++- src/target/mips32.h | 10 + src/target/mips32_pracc.c | 3 +- src/target/mips_m4k.c | 146 +++++++-------- testing/examples/cortex/cm3-ftest.cfg | 2 +- 17 files changed, 654 insertions(+), 301 deletions(-) hooks/post-receive -- Main OpenOCD repository |