diff options
author | Matthias Welwarsky <matthias.welwarsky@sysgo.com> | 2017-02-20 14:29:01 +0100 |
---|---|---|
committer | Matthias Welwarsky <matthias@welwarsky.de> | 2018-09-10 09:37:03 +0100 |
commit | 5d458cf72734a4474f38bbed10eea4d9acfe93a2 (patch) | |
tree | 38593c85509aa7f58fd46447f66eb813f4806aa9 /src/target/mem_ap.c | |
parent | 23cd59cdf2a563b840e5917e36c4241ee4d988f4 (diff) | |
download | riscv-openocd-5d458cf72734a4474f38bbed10eea4d9acfe93a2.zip riscv-openocd-5d458cf72734a4474f38bbed10eea4d9acfe93a2.tar.gz riscv-openocd-5d458cf72734a4474f38bbed10eea4d9acfe93a2.tar.bz2 |
target/mem_ap: generic mem-ap target
This pseudo target allows attaching to any access point on the DAP at the
MEM-AP level and read and write addresses on the connected bus. For
example, one can create a mem_ap target on the APB-AP and read and write
registers of debug components directly. This allows many diagnostic
and other features be programmed entirely using TCL, without necessity
of adding drivers to OpenOCD.
Change-Id: I53229ffd68fb0f96fb68be15b0f3a76cc8843c8e
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/4002
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Leonard Crestez <cdleonard@gmail.com>
Diffstat (limited to 'src/target/mem_ap.c')
-rw-r--r-- | src/target/mem_ap.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c new file mode 100644 index 0000000..3a2d4b7 --- /dev/null +++ b/src/target/mem_ap.c @@ -0,0 +1,181 @@ +/***************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky <matthias.welwarsky@sysgo.com> * + * * + * 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. * + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "target.h" +#include "target_type.h" +#include "arm.h" +#include "arm_adi_v5.h" + +#include <jtag/jtag.h> + +struct mem_ap { + struct arm arm; + struct adiv5_ap *ap; + int ap_num; +}; + +static int mem_ap_target_create(struct target *target, Jim_Interp *interp) +{ + struct mem_ap *mem_ap = calloc(1, sizeof(struct mem_ap)); + struct adiv5_private_config *pc; + + pc = (struct adiv5_private_config *)target->private_config; + if (pc == NULL) + return ERROR_FAIL; + + if (pc->ap_num == DP_APSEL_INVALID) { + LOG_ERROR("AP number not specified"); + return ERROR_FAIL; + } + + mem_ap->ap_num = pc->ap_num; + mem_ap->arm.common_magic = ARM_COMMON_MAGIC; + mem_ap->arm.dap = pc->dap; + + target->arch_info = mem_ap; + + return ERROR_OK; +} + +static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *target) +{ + LOG_DEBUG("%s", __func__); + target->state = TARGET_UNKNOWN; + return ERROR_OK; +} + +static int mem_ap_arch_state(struct target *target) +{ + LOG_DEBUG("%s", __func__); + return ERROR_OK; +} + +static int mem_ap_poll(struct target *target) +{ + if (target->state == TARGET_UNKNOWN) + target->state = TARGET_RUNNING; + + return ERROR_OK; +} + +static int mem_ap_halt(struct target *target) +{ + LOG_DEBUG("%s", __func__); + target->state = TARGET_HALTED; + return ERROR_OK; +} + +static int mem_ap_resume(struct target *target, int current, target_addr_t address, + int handle_breakpoints, int debug_execution) +{ + LOG_DEBUG("%s", __func__); + target->state = TARGET_RUNNING; + return ERROR_OK; +} + +static int mem_ap_step(struct target *target, int current, target_addr_t address, + int handle_breakpoints) +{ + LOG_DEBUG("%s", __func__); + target->state = TARGET_HALTED; + return ERROR_OK; +} + +static int mem_ap_assert_reset(struct target *target) +{ + target->state = TARGET_RESET; + + LOG_DEBUG("%s", __func__); + return ERROR_OK; +} + +static int mem_ap_examine(struct target *target) +{ + struct mem_ap *mem_ap = target->arch_info; + + if (!target_was_examined(target)) { + mem_ap->ap = dap_ap(mem_ap->arm.dap, mem_ap->ap_num); + target_set_examined(target); + target->state = TARGET_UNKNOWN; + return mem_ap_init(mem_ap->ap); + } + + return ERROR_OK; +} + +static int mem_ap_deassert_reset(struct target *target) +{ + if (target->reset_halt) + target->state = TARGET_HALTED; + else + target->state = TARGET_RUNNING; + + LOG_DEBUG("%s", __func__); + return ERROR_OK; +} + +static int mem_ap_read_memory(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer) +{ + struct mem_ap *mem_ap = target->arch_info; + + LOG_DEBUG("Reading memory at physical address 0x" TARGET_ADDR_FMT + "; size %" PRId32 "; count %" PRId32, address, size, count); + + if (count == 0 || buffer == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + return mem_ap_read_buf(mem_ap->ap, buffer, size, count, address); +} + +static int mem_ap_write_memory(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, + const uint8_t *buffer) +{ + struct mem_ap *mem_ap = target->arch_info; + + LOG_DEBUG("Writing memory at physical address 0x" TARGET_ADDR_FMT + "; size %" PRId32 "; count %" PRId32, address, size, count); + + if (count == 0 || buffer == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + return mem_ap_write_buf(mem_ap->ap, buffer, size, count, address); +} + +struct target_type mem_ap_target = { + .name = "mem_ap", + + .target_create = mem_ap_target_create, + .init_target = mem_ap_init_target, + .examine = mem_ap_examine, + .target_jim_configure = adiv5_jim_configure, + + .poll = mem_ap_poll, + .arch_state = mem_ap_arch_state, + + .halt = mem_ap_halt, + .resume = mem_ap_resume, + .step = mem_ap_step, + + .assert_reset = mem_ap_assert_reset, + .deassert_reset = mem_ap_deassert_reset, + + .read_memory = mem_ap_read_memory, + .write_memory = mem_ap_write_memory, +}; |