openocd: fix SPDX tag format for files .c
[fw/openocd] / src / target / mem_ap.c
index ade48b6d7695806c9de0da1124a949f06cd01852..a6625069373632761da17ffca83245240b534222 100644 (file)
@@ -1,16 +1,8 @@
-/*****************************************************************************
- *   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.                            *
- ****************************************************************************/
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2016 by Matthias Welwarsky <matthias.welwarsky@sysgo.com>
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 
 #include "target.h"
 #include "target_type.h"
-#include "arm.h"
 #include "arm_adi_v5.h"
+#include "register.h"
 
 #include <jtag/jtag.h>
 
+#define MEM_AP_COMMON_MAGIC 0x4DE4DA50
+
 struct mem_ap {
-       struct arm arm;
+       int common_magic;
+       struct adiv5_dap *dap;
        struct adiv5_ap *ap;
-       int ap_num;
+       uint64_t ap_num;
 };
 
 static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
@@ -35,7 +30,7 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
        struct adiv5_private_config *pc;
 
        pc = (struct adiv5_private_config *)target->private_config;
-       if (pc == NULL)
+       if (!pc)
                return ERROR_FAIL;
 
        if (pc->ap_num == DP_APSEL_INVALID) {
@@ -44,17 +39,20 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
        }
 
        mem_ap = calloc(1, sizeof(struct mem_ap));
-       if (mem_ap == NULL) {
+       if (!mem_ap) {
                LOG_ERROR("Out of memory");
                return ERROR_FAIL;
        }
 
        mem_ap->ap_num = pc->ap_num;
-       mem_ap->arm.common_magic = ARM_COMMON_MAGIC;
-       mem_ap->arm.dap = pc->dap;
+       mem_ap->common_magic = MEM_AP_COMMON_MAGIC;
+       mem_ap->dap = pc->dap;
 
        target->arch_info = mem_ap;
 
+       if (!target->gdb_port_override)
+               target->gdb_port_override = strdup("disabled");
+
        return ERROR_OK;
 }
 
@@ -62,13 +60,19 @@ 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;
 }
 
 static void mem_ap_deinit_target(struct target *target)
 {
+       struct mem_ap *mem_ap = target->arch_info;
+
        LOG_DEBUG("%s", __func__);
 
+       if (mem_ap->ap)
+               dap_put_ap(mem_ap->ap);
+
        free(target->private_config);
        free(target->arch_info);
        return;
@@ -82,8 +86,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 +98,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 +108,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 +117,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;
@@ -124,9 +136,19 @@ 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);
+               if (mem_ap->ap) {
+                       dap_put_ap(mem_ap->ap);
+                       mem_ap->ap = NULL;
+               }
+
+               mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num);
+               if (!mem_ap->ap) {
+                       LOG_ERROR("Cannot get AP");
+                       return ERROR_FAIL;
+               }
                target_set_examined(target);
                target->state = TARGET_UNKNOWN;
+               target->debug_reason = DBG_REASON_UNDEFINED;
                return mem_ap_init(mem_ap->ap);
        }
 
@@ -135,24 +157,94 @@ 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,
+};
+
+static 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)
 {
        struct mem_ap *mem_ap = target->arch_info;
 
        LOG_DEBUG("Reading memory at physical address " TARGET_ADDR_FMT
-                 "; size %" PRId32 "; count %" PRId32, address, size, count);
+                 "; size %" PRIu32 "; count %" PRIu32, address, size, count);
 
-       if (count == 0 || buffer == NULL)
+       if (count == 0 || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        return mem_ap_read_buf(mem_ap->ap, buffer, size, count, address);
@@ -165,9 +257,9 @@ static int mem_ap_write_memory(struct target *target, target_addr_t address,
        struct mem_ap *mem_ap = target->arch_info;
 
        LOG_DEBUG("Writing memory at physical address " TARGET_ADDR_FMT
-                 "; size %" PRId32 "; count %" PRId32, address, size, count);
+                 "; size %" PRIu32 "; count %" PRIu32, address, size, count);
 
-       if (count == 0 || buffer == NULL)
+       if (count == 0 || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        return mem_ap_write_buf(mem_ap->ap, buffer, size, count, address);
@@ -192,6 +284,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,
 };