From: Matthias Welwarsky Date: Mon, 20 Feb 2017 13:29:01 +0000 (+0100) Subject: target/mem_ap: generic mem-ap target X-Git-Tag: v0.11.0-rc1~1000 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=5d458cf72734a4474f38bbed10eea4d9acfe93a2 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 Reviewed-on: http://openocd.zylin.com/4002 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Leonard Crestez --- diff --git a/src/target/Makefile.am b/src/target/Makefile.am index b1119e7df0..4b7c8c076c 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -75,7 +75,8 @@ ARMV7_SRC = \ %D%/cortex_m.c \ %D%/armv7a.c \ %D%/cortex_a.c \ - %D%/ls1_sap.c + %D%/ls1_sap.c \ + %D%/mem_ap.c ARMV8_SRC = \ %D%/armv8_dpm.c \ diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c new file mode 100644 index 0000000000..3a2d4b7c52 --- /dev/null +++ b/src/target/mem_ap.c @@ -0,0 +1,181 @@ +/***************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky * + * * + * 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 + +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, +}; diff --git a/src/target/target.c b/src/target/target.c index 253928d7c3..060fbdca5a 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -108,6 +108,7 @@ extern struct target_type quark_x10xx_target; extern struct target_type quark_d20xx_target; extern struct target_type stm8_target; extern struct target_type riscv_target; +extern struct target_type mem_ap_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -144,6 +145,7 @@ static struct target_type *target_types[] = { #if BUILD_TARGET64 &aarch64_target, #endif + &mem_ap_target, NULL, };