aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/openocd.texi8
-rw-r--r--src/target/mem_ap.c93
2 files changed, 97 insertions, 4 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 2cba45e..6b74243 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -4509,7 +4509,13 @@ The current implementation supports eSi-32xx cores.
@item @code{hla_target} -- a Cortex-M alternative to work with HL adapters like ST-Link.
@item @code{ls1_sap} -- this is the SAP on NXP LS102x CPUs,
allowing access to physical memory addresses independently of CPU cores.
-@item @code{mem_ap} -- this is an ARM debug infrastructure Access Port without a CPU, through which bus read and write cycles can be generated; it may be useful for working with non-CPU hardware behind an AP or during development of support for new CPUs.
+@item @code{mem_ap} -- this is an ARM debug infrastructure Access Port without
+a CPU, through which bus read and write cycles can be generated; it may be
+useful for working with non-CPU hardware behind an AP or during development of
+support for new CPUs.
+It's possible to connect a GDB client to this target (the GDB port has to be
+specified, @xref{gdbportoverride,,option -gdb-port}), and a fake ARM core will
+be emulated to comply to GDB remote protocol.
@item @code{mips_m4k} -- a MIPS core.
@item @code{mips_mips64} -- a MIPS64 core.
@item @code{nds32_v2} -- this is an Andes NDS32 v2 core.
diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c
index 7ed41c6..89c0c02 100644
--- a/src/target/mem_ap.c
+++ b/src/target/mem_ap.c
@@ -20,6 +20,7 @@
#include "target_type.h"
#include "arm.h"
#include "arm_adi_v5.h"
+#include "register.h"
#include <jtag/jtag.h>
@@ -55,6 +56,9 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
target->arch_info = mem_ap;
+ if (!target->gdb_port_override)
+ target->gdb_port_override = strdup("disabled");
+
return ERROR_OK;
}
@@ -62,6 +66,7 @@ static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *ta
{
LOG_DEBUG("%s", __func__);
target->state = TARGET_UNKNOWN;
+ target->debug_reason = DBG_REASON_UNDEFINED;
return ERROR_OK;
}
@@ -82,8 +87,10 @@ static int mem_ap_arch_state(struct target *target)
static int mem_ap_poll(struct target *target)
{
- if (target->state == TARGET_UNKNOWN)
+ if (target->state == TARGET_UNKNOWN) {
target->state = TARGET_RUNNING;
+ target->debug_reason = DBG_REASON_NOTHALTED;
+ }
return ERROR_OK;
}
@@ -92,6 +99,8 @@ static int mem_ap_halt(struct target *target)
{
LOG_DEBUG("%s", __func__);
target->state = TARGET_HALTED;
+ target->debug_reason = DBG_REASON_DBGRQ;
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
return ERROR_OK;
}
@@ -100,6 +109,7 @@ static int mem_ap_resume(struct target *target, int current, target_addr_t addre
{
LOG_DEBUG("%s", __func__);
target->state = TARGET_RUNNING;
+ target->debug_reason = DBG_REASON_NOTHALTED;
return ERROR_OK;
}
@@ -108,12 +118,15 @@ static int mem_ap_step(struct target *target, int current, target_addr_t address
{
LOG_DEBUG("%s", __func__);
target->state = TARGET_HALTED;
+ target->debug_reason = DBG_REASON_DBGRQ;
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
return ERROR_OK;
}
static int mem_ap_assert_reset(struct target *target)
{
target->state = TARGET_RESET;
+ target->debug_reason = DBG_REASON_UNDEFINED;
LOG_DEBUG("%s", __func__);
return ERROR_OK;
@@ -127,6 +140,7 @@ static int mem_ap_examine(struct target *target)
mem_ap->ap = dap_ap(mem_ap->arm.dap, mem_ap->ap_num);
target_set_examined(target);
target->state = TARGET_UNKNOWN;
+ target->debug_reason = DBG_REASON_UNDEFINED;
return mem_ap_init(mem_ap->ap);
}
@@ -135,15 +149,85 @@ static int mem_ap_examine(struct target *target)
static int mem_ap_deassert_reset(struct target *target)
{
- if (target->reset_halt)
+ if (target->reset_halt) {
target->state = TARGET_HALTED;
- else
+ target->debug_reason = DBG_REASON_DBGRQ;
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+ } else {
target->state = TARGET_RUNNING;
+ target->debug_reason = DBG_REASON_NOTHALTED;
+ }
LOG_DEBUG("%s", __func__);
return ERROR_OK;
}
+static int mem_ap_reg_get(struct reg *reg)
+{
+ return ERROR_OK;
+}
+
+static int mem_ap_reg_set(struct reg *reg, uint8_t *buf)
+{
+ return ERROR_OK;
+}
+
+static struct reg_arch_type mem_ap_reg_arch_type = {
+ .get = mem_ap_reg_get,
+ .set = mem_ap_reg_set,
+};
+
+const char *mem_ap_get_gdb_arch(struct target *target)
+{
+ return "arm";
+}
+
+/*
+ * Dummy ARM register emulation:
+ * reg[0..15]: 32 bits, r0~r12, sp, lr, pc
+ * reg[16..23]: 96 bits, f0~f7
+ * reg[24]: 32 bits, fps
+ * reg[25]: 32 bits, cpsr
+ *
+ * Set 'exist' only to reg[0..15], so initial response to GDB is correct
+ */
+#define NUM_REGS 26
+#define MAX_REG_SIZE 96
+#define REG_EXIST(n) ((n) < 16)
+#define REG_SIZE(n) ((((n) >= 16) && ((n) < 24)) ? 96 : 32)
+
+struct mem_ap_alloc_reg_list {
+ /* reg_list must be the first field */
+ struct reg *reg_list[NUM_REGS];
+ struct reg regs[NUM_REGS];
+ uint8_t regs_value[MAX_REG_SIZE / 8];
+};
+
+static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
+ int *reg_list_size, enum target_register_class reg_class)
+{
+ struct mem_ap_alloc_reg_list *mem_ap_alloc = calloc(1, sizeof(struct mem_ap_alloc_reg_list));
+ if (!mem_ap_alloc) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+
+ *reg_list = mem_ap_alloc->reg_list;
+ *reg_list_size = NUM_REGS;
+ struct reg *regs = mem_ap_alloc->regs;
+
+ for (int i = 0; i < NUM_REGS; i++) {
+ regs[i].number = i;
+ regs[i].value = mem_ap_alloc->regs_value;
+ regs[i].size = REG_SIZE(i);
+ regs[i].exist = REG_EXIST(i);
+ regs[i].type = &mem_ap_reg_arch_type;
+ (*reg_list)[i] = &regs[i];
+ }
+
+ 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)
{
@@ -192,6 +276,9 @@ struct target_type mem_ap_target = {
.assert_reset = mem_ap_assert_reset,
.deassert_reset = mem_ap_deassert_reset,
+ .get_gdb_arch = mem_ap_get_gdb_arch,
+ .get_gdb_reg_list = mem_ap_get_gdb_reg_list,
+
.read_memory = mem_ap_read_memory,
.write_memory = mem_ap_write_memory,
};