target: add Espressif ESP32-S2 basic support

ESP32-S2 is a single core Xtensa chip.
Not full featured yet. Some of the missing functionality:
-Semihosting
-Flash breakpoints
-Flash loader
-Apptrace
-FreeRTOS

Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
Change-Id: I2fb32978e801af5aa21616c581691406ad7cd6bb
Reviewed-on: https://review.openocd.org/c/openocd/+/6940
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Ian Thompson <ianst@cadence.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
Erhan Kurubas
2022-04-21 07:53:54 +02:00
committed by Antonio Borneo
parent b470b664ca
commit 78c87f5e81
17 changed files with 5122 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
noinst_LTLIBRARIES += %D%/libxtensa.la
%C%_libxtensa_la_SOURCES = \
%D%/xtensa.c \
%D%/xtensa.h \
%D%/xtensa_debug_module.c \
%D%/xtensa_debug_module.h \
%D%/xtensa_regs.h

2731
src/target/xtensa/xtensa.c Normal file

File diff suppressed because it is too large Load Diff

309
src/target/xtensa/xtensa.h Normal file
View File

@@ -0,0 +1,309 @@
/***************************************************************************
* Generic Xtensa target *
* Copyright (C) 2019 Espressif Systems Ltd. *
* Author: Alexey Gerenkov <alexey@espressif.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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_TARGET_XTENSA_H
#define OPENOCD_TARGET_XTENSA_H
#include "assert.h"
#include <target/target.h>
#include <target/breakpoints.h>
#include "xtensa_regs.h"
#include "xtensa_debug_module.h"
/**
* @file
* Holds the interface to Xtensa cores.
*/
#define XT_ISNS_SZ_MAX 3
#define XT_PS_RING(_v_) ((uint32_t)((_v_) & 0x3) << 6)
#define XT_PS_RING_MSK (0x3 << 6)
#define XT_PS_RING_GET(_v_) (((_v_) >> 6) & 0x3)
#define XT_PS_CALLINC_MSK (0x3 << 16)
#define XT_PS_OWB_MSK (0xF << 8)
#define XT_LOCAL_MEM_REGIONS_NUM_MAX 8
#define XT_AREGS_NUM_MAX 64
#define XT_USER_REGS_NUM_MAX 256
#define XT_MEM_ACCESS_NONE 0x0
#define XT_MEM_ACCESS_READ 0x1
#define XT_MEM_ACCESS_WRITE 0x2
enum xtensa_mem_err_detect {
XT_MEM_ERR_DETECT_NONE,
XT_MEM_ERR_DETECT_PARITY,
XT_MEM_ERR_DETECT_ECC,
};
struct xtensa_cache_config {
uint8_t way_count;
uint8_t line_size;
uint16_t size;
bool writeback;
enum xtensa_mem_err_detect mem_err_check;
};
struct xtensa_local_mem_region_config {
target_addr_t base;
uint32_t size;
enum xtensa_mem_err_detect mem_err_check;
int access;
};
struct xtensa_local_mem_config {
uint16_t count;
struct xtensa_local_mem_region_config regions[XT_LOCAL_MEM_REGIONS_NUM_MAX];
};
struct xtensa_mmu_config {
bool enabled;
uint8_t itlb_entries_count;
uint8_t dtlb_entries_count;
bool ivarway56;
bool dvarway56;
};
struct xtensa_exception_config {
bool enabled;
uint8_t depc_num;
};
struct xtensa_irq_config {
bool enabled;
uint8_t irq_num;
};
struct xtensa_high_prio_irq_config {
bool enabled;
uint8_t excm_level;
uint8_t nmi_num;
};
struct xtensa_debug_config {
bool enabled;
uint8_t irq_level;
uint8_t ibreaks_num;
uint8_t dbreaks_num;
uint8_t icount_sz;
};
struct xtensa_tracing_config {
bool enabled;
uint32_t mem_sz;
bool reversed_mem_access;
};
struct xtensa_timer_irq_config {
bool enabled;
uint8_t comp_num;
};
struct xtensa_config {
bool density;
uint8_t aregs_num;
bool windowed;
bool coproc;
bool fp_coproc;
bool loop;
uint8_t miscregs_num;
bool threadptr;
bool boolean;
bool cond_store;
bool ext_l32r;
bool mac16;
bool reloc_vec;
bool proc_id;
bool mem_err_check;
uint16_t user_regs_num;
const struct xtensa_user_reg_desc *user_regs;
int (*fetch_user_regs)(struct target *target);
int (*queue_write_dirty_user_regs)(struct target *target);
struct xtensa_cache_config icache;
struct xtensa_cache_config dcache;
struct xtensa_local_mem_config irom;
struct xtensa_local_mem_config iram;
struct xtensa_local_mem_config drom;
struct xtensa_local_mem_config dram;
struct xtensa_local_mem_config uram;
struct xtensa_local_mem_config xlmi;
struct xtensa_mmu_config mmu;
struct xtensa_exception_config exc;
struct xtensa_irq_config irq;
struct xtensa_high_prio_irq_config high_irq;
struct xtensa_timer_irq_config tim_irq;
struct xtensa_debug_config debug;
struct xtensa_tracing_config trace;
unsigned int gdb_general_regs_num;
const unsigned int *gdb_regs_mapping;
};
typedef uint32_t xtensa_insn_t;
enum xtensa_stepping_isr_mode {
XT_STEPPING_ISR_OFF, /* interrupts are disabled during stepping */
XT_STEPPING_ISR_ON, /* interrupts are enabled during stepping */
};
/* Only supported in cores with in-CPU MMU. None of Espressif chips as of now. */
enum xtensa_mode {
XT_MODE_RING0,
XT_MODE_RING1,
XT_MODE_RING2,
XT_MODE_RING3,
XT_MODE_ANY /* special value to run algorithm in current core mode */
};
struct xtensa_sw_breakpoint {
struct breakpoint *oocd_bp;
/* original insn */
uint8_t insn[XT_ISNS_SZ_MAX];
/* original insn size */
uint8_t insn_sz; /* 2 or 3 bytes */
};
#define XTENSA_COMMON_MAGIC 0x54E4E555U
/**
* Represents a generic Xtensa core.
*/
struct xtensa {
unsigned int common_magic;
const struct xtensa_config *core_config;
struct xtensa_debug_module dbg_mod;
struct reg_cache *core_cache;
unsigned int regs_num;
/* An array of pointers to buffers to backup registers' values while algo is run on target.
* Size is 'regs_num'. */
void **algo_context_backup;
struct target *target;
bool reset_asserted;
enum xtensa_stepping_isr_mode stepping_isr_mode;
struct breakpoint **hw_brps;
struct watchpoint **hw_wps;
struct xtensa_sw_breakpoint *sw_brps;
bool trace_active;
bool permissive_mode; /* bypass memory checks */
bool suppress_dsr_errors;
uint32_t smp_break;
/* Sometimes debug module's 'powered' bit is cleared after reset, but get set after some
* time.This is the number of polling periods after which core is considered to be powered
* off (marked as unexamined) if the bit retains to be cleared (e.g. if core is disabled by
* SW running on target).*/
uint8_t come_online_probes_num;
bool regs_fetched; /* true after first register fetch completed successfully */
};
static inline struct xtensa *target_to_xtensa(struct target *target)
{
assert(target);
struct xtensa *xtensa = target->arch_info;
assert(xtensa->common_magic == XTENSA_COMMON_MAGIC);
return xtensa;
}
int xtensa_init_arch_info(struct target *target,
struct xtensa *xtensa,
const struct xtensa_config *cfg,
const struct xtensa_debug_module_config *dm_cfg);
int xtensa_target_init(struct command_context *cmd_ctx, struct target *target);
void xtensa_target_deinit(struct target *target);
static inline bool xtensa_addr_in_mem(const struct xtensa_local_mem_config *mem, uint32_t addr)
{
for (unsigned int i = 0; i < mem->count; i++) {
if (addr >= mem->regions[i].base &&
addr < mem->regions[i].base + mem->regions[i].size)
return true;
}
return false;
}
static inline bool xtensa_data_addr_valid(struct target *target, uint32_t addr)
{
struct xtensa *xtensa = target_to_xtensa(target);
if (xtensa_addr_in_mem(&xtensa->core_config->drom, addr))
return true;
if (xtensa_addr_in_mem(&xtensa->core_config->dram, addr))
return true;
if (xtensa_addr_in_mem(&xtensa->core_config->uram, addr))
return true;
return false;
}
int xtensa_core_status_check(struct target *target);
int xtensa_examine(struct target *target);
int xtensa_wakeup(struct target *target);
int xtensa_smpbreak_set(struct target *target, uint32_t set);
int xtensa_smpbreak_get(struct target *target, uint32_t *val);
int xtensa_smpbreak_write(struct xtensa *xtensa, uint32_t set);
int xtensa_smpbreak_read(struct xtensa *xtensa, uint32_t *val);
xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id);
void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value);
int xtensa_fetch_all_regs(struct target *target);
int xtensa_get_gdb_reg_list(struct target *target,
struct reg **reg_list[],
int *reg_list_size,
enum target_register_class reg_class);
int xtensa_poll(struct target *target);
void xtensa_on_poll(struct target *target);
int xtensa_halt(struct target *target);
int xtensa_resume(struct target *target,
int current,
target_addr_t address,
int handle_breakpoints,
int debug_execution);
int xtensa_prepare_resume(struct target *target,
int current,
target_addr_t address,
int handle_breakpoints,
int debug_execution);
int xtensa_do_resume(struct target *target);
int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints);
int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints);
int xtensa_mmu_is_enabled(struct target *target, int *enabled);
int xtensa_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer);
int xtensa_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer);
int xtensa_write_memory(struct target *target,
target_addr_t address,
uint32_t size,
uint32_t count,
const uint8_t *buffer);
int xtensa_write_buffer(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer);
int xtensa_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum);
int xtensa_assert_reset(struct target *target);
int xtensa_deassert_reset(struct target *target);
int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint);
int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint);
void xtensa_set_permissive_mode(struct target *target, bool state);
int xtensa_fetch_user_regs_u32(struct target *target);
int xtensa_queue_write_dirty_user_regs_u32(struct target *target);
const char *xtensa_get_gdb_arch(struct target *target);
extern const struct reg_arch_type xtensa_user_reg_u32_type;
extern const struct reg_arch_type xtensa_user_reg_u128_type;
extern const struct command_registration xtensa_command_handlers[];
#endif /* OPENOCD_TARGET_XTENSA_H */

View File

@@ -0,0 +1,359 @@
/***************************************************************************
* Generic Xtensa debug module API for OpenOCD *
* Copyright (C) 2019 Espressif Systems Ltd. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xtensa_debug_module.h"
#define TAPINS_PWRCTL 0x08
#define TAPINS_PWRSTAT 0x09
#define TAPINS_NARSEL 0x1C
#define TAPINS_IDCODE 0x1E
#define TAPINS_BYPASS 0x1F
#define TAPINS_PWRCTL_LEN 8
#define TAPINS_PWRSTAT_LEN 8
#define TAPINS_NARSEL_ADRLEN 8
#define TAPINS_NARSEL_DATALEN 32
#define TAPINS_IDCODE_LEN 32
#define TAPINS_BYPASS_LEN 1
static void xtensa_dm_add_set_ir(struct xtensa_debug_module *dm, uint8_t value)
{
struct scan_field field;
uint8_t t[4] = { 0 };
memset(&field, 0, sizeof(field));
field.num_bits = dm->tap->ir_length;
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, value);
jtag_add_ir_scan(dm->tap, &field, TAP_IDLE);
}
static void xtensa_dm_add_dr_scan(struct xtensa_debug_module *dm,
int len,
const uint8_t *src,
uint8_t *dest,
tap_state_t endstate)
{
struct scan_field field;
memset(&field, 0, sizeof(field));
field.num_bits = len;
field.out_value = src;
field.in_value = dest;
jtag_add_dr_scan(dm->tap, 1, &field, endstate);
}
int xtensa_dm_init(struct xtensa_debug_module *dm, const struct xtensa_debug_module_config *cfg)
{
if (!dm || !cfg)
return ERROR_FAIL;
dm->pwr_ops = cfg->pwr_ops;
dm->dbg_ops = cfg->dbg_ops;
dm->tap = cfg->tap;
dm->queue_tdi_idle = cfg->queue_tdi_idle;
dm->queue_tdi_idle_arg = cfg->queue_tdi_idle_arg;
return ERROR_OK;
}
int xtensa_dm_queue_enable(struct xtensa_debug_module *dm)
{
return dm->dbg_ops->queue_reg_write(dm, NARADR_DCRSET, OCDDCR_ENABLEOCD);
}
int xtensa_dm_queue_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *value)
{
uint8_t regdata = (reg << 1) | 0;
uint8_t dummy[4] = { 0, 0, 0, 0 };
if (reg > NARADR_MAX) {
LOG_ERROR("Invalid DBG reg ID %d!", reg);
return ERROR_FAIL;
}
xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, &regdata, NULL, TAP_IDLE);
xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, dummy, value, TAP_IDLE);
return ERROR_OK;
}
int xtensa_dm_queue_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint32_t value)
{
uint8_t regdata = (reg << 1) | 1;
uint8_t valdata[] = { value, value >> 8, value >> 16, value >> 24 };
if (reg > NARADR_MAX) {
LOG_ERROR("Invalid DBG reg ID %d!", reg);
return ERROR_FAIL;
}
xtensa_dm_add_set_ir(dm, TAPINS_NARSEL);
xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_ADRLEN, &regdata, NULL, TAP_IDLE);
xtensa_dm_add_dr_scan(dm, TAPINS_NARSEL_DATALEN, valdata, NULL, TAP_IDLE);
return ERROR_OK;
}
int xtensa_dm_queue_pwr_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data, uint8_t clear)
{
uint8_t value_clr = clear;
uint8_t tap_insn;
int tap_insn_sz;
if (reg == DMREG_PWRCTL) {
tap_insn = TAPINS_PWRCTL;
tap_insn_sz = TAPINS_PWRCTL_LEN;
} else if (reg == DMREG_PWRSTAT) {
tap_insn = TAPINS_PWRSTAT;
tap_insn_sz = TAPINS_PWRSTAT_LEN;
} else {
LOG_ERROR("Invalid PWR reg ID %d!", reg);
return ERROR_FAIL;
}
xtensa_dm_add_set_ir(dm, tap_insn);
xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value_clr, data, TAP_IDLE);
return ERROR_OK;
}
int xtensa_dm_queue_pwr_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint8_t data)
{
uint8_t value = data;
uint8_t tap_insn;
int tap_insn_sz;
if (reg == DMREG_PWRCTL) {
tap_insn = TAPINS_PWRCTL;
tap_insn_sz = TAPINS_PWRCTL_LEN;
} else if (reg == DMREG_PWRSTAT) {
tap_insn = TAPINS_PWRSTAT;
tap_insn_sz = TAPINS_PWRSTAT_LEN;
} else {
LOG_ERROR("Invalid PWR reg ID %d!", reg);
return ERROR_FAIL;
}
xtensa_dm_add_set_ir(dm, tap_insn);
xtensa_dm_add_dr_scan(dm, tap_insn_sz, &value, NULL, TAP_IDLE);
return ERROR_OK;
}
int xtensa_dm_device_id_read(struct xtensa_debug_module *dm)
{
uint8_t id_buf[sizeof(uint32_t)];
dm->dbg_ops->queue_reg_read(dm, NARADR_OCDID, id_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res != ERROR_OK)
return res;
dm->device_id = buf_get_u32(id_buf, 0, 32);
return ERROR_OK;
}
int xtensa_dm_power_status_read(struct xtensa_debug_module *dm, uint32_t clear)
{
/* uint8_t id_buf[sizeof(uint32_t)]; */
/* TODO: JTAG does not work when PWRCTL_JTAGDEBUGUSE is not set.
* It is set in xtensa_examine(), need to move reading of NARADR_OCDID out of this function */
/* dm->dbg_ops->queue_reg_read(dm, NARADR_OCDID, id_buf);
*Read reset state */
dm->pwr_ops->queue_reg_read(dm, DMREG_PWRSTAT, &dm->power_status.stat, clear);
dm->pwr_ops->queue_reg_read(dm, DMREG_PWRSTAT, &dm->power_status.stath, clear);
xtensa_dm_queue_tdi_idle(dm);
return jtag_execute_queue();
}
int xtensa_dm_core_status_read(struct xtensa_debug_module *dm)
{
uint8_t dsr_buf[sizeof(uint32_t)];
xtensa_dm_queue_enable(dm);
dm->dbg_ops->queue_reg_read(dm, NARADR_DSR, dsr_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res != ERROR_OK)
return res;
dm->core_status.dsr = buf_get_u32(dsr_buf, 0, 32);
return res;
}
int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bits)
{
dm->dbg_ops->queue_reg_write(dm, NARADR_DSR, bits);
xtensa_dm_queue_tdi_idle(dm);
return jtag_execute_queue();
}
int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg)
{
/*Turn off trace unit so we can start a new trace. */
dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXCTRL, 0);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res != ERROR_OK)
return res;
/*Set up parameters */
dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXADDR, 0);
if (cfg->stopmask != XTENSA_STOPMASK_DISABLED) {
dm->dbg_ops->queue_reg_write(dm, NARADR_PCMATCHCTRL,
(cfg->stopmask << PCMATCHCTRL_PCML_SHIFT));
dm->dbg_ops->queue_reg_write(dm, NARADR_TRIGGERPC, cfg->stoppc);
}
dm->dbg_ops->queue_reg_write(dm, NARADR_DELAYCNT, cfg->after);
/*Options are mostly hardcoded for now. ToDo: make this more configurable. */
dm->dbg_ops->queue_reg_write(
dm,
NARADR_TRAXCTRL,
TRAXCTRL_TREN |
((cfg->stopmask != XTENSA_STOPMASK_DISABLED) ? TRAXCTRL_PCMEN : 0) | TRAXCTRL_TMEN |
(cfg->after_is_words ? 0 : TRAXCTRL_CNTU) | (0 << TRAXCTRL_SMPER_SHIFT) | TRAXCTRL_PTOWS);
xtensa_dm_queue_tdi_idle(dm);
return jtag_execute_queue();
}
int xtensa_dm_trace_stop(struct xtensa_debug_module *dm, bool pto_enable)
{
uint8_t traxctl_buf[sizeof(uint32_t)];
uint32_t traxctl;
struct xtensa_trace_status trace_status;
dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXCTRL, traxctl_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res != ERROR_OK)
return res;
traxctl = buf_get_u32(traxctl_buf, 0, 32);
if (!pto_enable)
traxctl &= ~(TRAXCTRL_PTOWS | TRAXCTRL_PTOWT);
dm->dbg_ops->queue_reg_write(dm, NARADR_TRAXCTRL, traxctl | TRAXCTRL_TRSTP);
xtensa_dm_queue_tdi_idle(dm);
res = jtag_execute_queue();
if (res != ERROR_OK)
return res;
/*Check current status of trace hardware */
res = xtensa_dm_trace_status_read(dm, &trace_status);
if (res != ERROR_OK)
return res;
if (trace_status.stat & TRAXSTAT_TRACT) {
LOG_ERROR("Failed to stop tracing (0x%x)!", trace_status.stat);
return ERROR_FAIL;
}
return ERROR_OK;
}
int xtensa_dm_trace_status_read(struct xtensa_debug_module *dm, struct xtensa_trace_status *status)
{
uint8_t traxstat_buf[sizeof(uint32_t)];
dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXSTAT, traxstat_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res == ERROR_OK && status)
status->stat = buf_get_u32(traxstat_buf, 0, 32);
return res;
}
int xtensa_dm_trace_config_read(struct xtensa_debug_module *dm, struct xtensa_trace_config *config)
{
uint8_t traxctl_buf[sizeof(uint32_t)];
uint8_t memadrstart_buf[sizeof(uint32_t)];
uint8_t memadrend_buf[sizeof(uint32_t)];
uint8_t adr_buf[sizeof(uint32_t)];
if (!config)
return ERROR_FAIL;
dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXCTRL, traxctl_buf);
dm->dbg_ops->queue_reg_read(dm, NARADR_MEMADDRSTART, memadrstart_buf);
dm->dbg_ops->queue_reg_read(dm, NARADR_MEMADDREND, memadrend_buf);
dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXADDR, adr_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res == ERROR_OK) {
config->ctrl = buf_get_u32(traxctl_buf, 0, 32);
config->memaddr_start = buf_get_u32(memadrstart_buf, 0, 32);
config->memaddr_end = buf_get_u32(memadrend_buf, 0, 32);
config->addr = buf_get_u32(adr_buf, 0, 32);
}
return res;
}
int xtensa_dm_trace_data_read(struct xtensa_debug_module *dm, uint8_t *dest, uint32_t size)
{
if (!dest)
return ERROR_FAIL;
for (unsigned int i = 0; i < size / 4; i++)
dm->dbg_ops->queue_reg_read(dm, NARADR_TRAXDATA, &dest[i * 4]);
xtensa_dm_queue_tdi_idle(dm);
return jtag_execute_queue();
}
int xtensa_dm_perfmon_enable(struct xtensa_debug_module *dm, int counter_id,
const struct xtensa_perfmon_config *config)
{
if (!config)
return ERROR_FAIL;
uint8_t pmstat_buf[4];
uint32_t pmctrl = ((config->tracelevel) << 4) +
(config->select << 8) +
(config->mask << 16) +
(config->kernelcnt << 3);
/* enable performance monitor */
dm->dbg_ops->queue_reg_write(dm, NARADR_PMG, 0x1);
/* reset counter */
dm->dbg_ops->queue_reg_write(dm, NARADR_PM0 + counter_id, 0);
dm->dbg_ops->queue_reg_write(dm, NARADR_PMCTRL0 + counter_id, pmctrl);
dm->dbg_ops->queue_reg_read(dm, NARADR_PMSTAT0 + counter_id, pmstat_buf);
xtensa_dm_queue_tdi_idle(dm);
return jtag_execute_queue();
}
int xtensa_dm_perfmon_dump(struct xtensa_debug_module *dm, int counter_id,
struct xtensa_perfmon_result *out_result)
{
uint8_t pmstat_buf[4];
uint8_t pmcount_buf[4];
dm->dbg_ops->queue_reg_read(dm, NARADR_PMSTAT0 + counter_id, pmstat_buf);
dm->dbg_ops->queue_reg_read(dm, NARADR_PM0 + counter_id, pmcount_buf);
xtensa_dm_queue_tdi_idle(dm);
int res = jtag_execute_queue();
if (res == ERROR_OK) {
uint32_t stat = buf_get_u32(pmstat_buf, 0, 32);
uint64_t result = buf_get_u32(pmcount_buf, 0, 32);
/* TODO: if counter # counter_id+1 has 'select' set to 1, use its value as the
* high 32 bits of the counter. */
if (out_result) {
out_result->overflow = ((stat & 1) != 0);
out_result->value = result;
}
}
return res;
}

View File

@@ -0,0 +1,385 @@
/***************************************************************************
* Xtensa debug module API *
* Copyright (C) 2019 Espressif Systems Ltd. *
* <alexey@espressif.com> *
* *
* Derived from original ESP8266 target. *
* Copyright (C) 2015 by Angus Gratton *
* gus@projectgus.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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_TARGET_XTENSA_DEBUG_MODULE_H
#define OPENOCD_TARGET_XTENSA_DEBUG_MODULE_H
#include <jtag/jtag.h>
#include <helper/bits.h>
#include <target/target.h>
/* Virtual IDs for using with xtensa_power_ops API */
#define DMREG_PWRCTL 0x00
#define DMREG_PWRSTAT 0x01
/*
From the manual:
To properly use Debug registers through JTAG, software must ensure that:
- Tap is out of reset
- Xtensa Debug Module is out of reset
- Other bits of PWRCTL are set to their desired values, and finally
- JtagDebugUse transitions from 0 to 1
The bit must continue to be 1 in order for JTAG accesses to the Debug
Module to happen correctly. When it is set, any write to this bit clears it.
Either don't access it, or re-write it to 1 so JTAG accesses continue.
*/
#define PWRCTL_JTAGDEBUGUSE BIT(7)
#define PWRCTL_DEBUGRESET BIT(6)
#define PWRCTL_CORERESET BIT(4)
#define PWRCTL_DEBUGWAKEUP BIT(2)
#define PWRCTL_MEMWAKEUP BIT(1)
#define PWRCTL_COREWAKEUP BIT(0)
#define PWRSTAT_DEBUGWASRESET BIT(6)
#define PWRSTAT_COREWASRESET BIT(4)
#define PWRSTAT_CORESTILLNEEDED BIT(3)
#define PWRSTAT_DEBUGDOMAINON BIT(2)
#define PWRSTAT_MEMDOMAINON BIT(1)
#define PWRSTAT_COREDOMAINON BIT(0)
/* *** NAR addresses (also used as IDs for debug registers in xtensa_debug_ops API) ***
*TRAX registers */
#define NARADR_TRAXID 0x00
#define NARADR_TRAXCTRL 0x01
#define NARADR_TRAXSTAT 0x02
#define NARADR_TRAXDATA 0x03
#define NARADR_TRAXADDR 0x04
#define NARADR_TRIGGERPC 0x05
#define NARADR_PCMATCHCTRL 0x06
#define NARADR_DELAYCNT 0x07
#define NARADR_MEMADDRSTART 0x08
#define NARADR_MEMADDREND 0x09
/*Performance monitor registers */
#define NARADR_PMG 0x20
#define NARADR_INTPC 0x24
#define NARADR_PM0 0x28
/*... */
#define NARADR_PM7 0x2F
#define NARADR_PMCTRL0 0x30
/*... */
#define NARADR_PMCTRL7 0x37
#define NARADR_PMSTAT0 0x38
/*... */
#define NARADR_PMSTAT7 0x3F
/*OCD registers */
#define NARADR_OCDID 0x40
#define NARADR_DCRCLR 0x42
#define NARADR_DCRSET 0x43
#define NARADR_DSR 0x44
#define NARADR_DDR 0x45
#define NARADR_DDREXEC 0x46
#define NARADR_DIR0EXEC 0x47
#define NARADR_DIR0 0x48
#define NARADR_DIR1 0x49
/*... */
#define NARADR_DIR7 0x4F
/*Misc registers */
#define NARADR_PWRCTL 0x58
#define NARADR_PWRSTAT 0x59
#define NARADR_ERISTAT 0x5A
/*CoreSight registers */
#define NARADR_ITCTRL 0x60
#define NARADR_CLAIMSET 0x68
#define NARADR_CLAIMCLR 0x69
#define NARADR_LOCKACCESS 0x6c
#define NARADR_LOCKSTATUS 0x6d
#define NARADR_AUTHSTATUS 0x6e
#define NARADR_DEVID 0x72
#define NARADR_DEVTYPE 0x73
#define NARADR_PERID4 0x74
/*... */
#define NARADR_PERID7 0x77
#define NARADR_PERID0 0x78
/*... */
#define NARADR_PERID3 0x7b
#define NARADR_COMPID0 0x7c
/*... */
#define NARADR_COMPID3 0x7f
#define NARADR_MAX NARADR_COMPID3
/*OCD registers, bit definitions */
#define OCDDCR_ENABLEOCD BIT(0)
#define OCDDCR_DEBUGINTERRUPT BIT(1)
#define OCDDCR_INTERRUPTALLCONDS BIT(2)
#define OCDDCR_BREAKINEN BIT(16)
#define OCDDCR_BREAKOUTEN BIT(17)
#define OCDDCR_DEBUGSWACTIVE BIT(20)
#define OCDDCR_RUNSTALLINEN BIT(21)
#define OCDDCR_DEBUGMODEOUTEN BIT(22)
#define OCDDCR_BREAKOUTITO BIT(24)
#define OCDDCR_BREAKACKITO BIT(25)
#define OCDDSR_EXECDONE BIT(0)
#define OCDDSR_EXECEXCEPTION BIT(1)
#define OCDDSR_EXECBUSY BIT(2)
#define OCDDSR_EXECOVERRUN BIT(3)
#define OCDDSR_STOPPED BIT(4)
#define OCDDSR_COREWROTEDDR BIT(10)
#define OCDDSR_COREREADDDR BIT(11)
#define OCDDSR_HOSTWROTEDDR BIT(14)
#define OCDDSR_HOSTREADDDR BIT(15)
#define OCDDSR_DEBUGPENDBREAK BIT(16)
#define OCDDSR_DEBUGPENDHOST BIT(17)
#define OCDDSR_DEBUGPENDTRAX BIT(18)
#define OCDDSR_DEBUGINTBREAK BIT(20)
#define OCDDSR_DEBUGINTHOST BIT(21)
#define OCDDSR_DEBUGINTTRAX BIT(22)
#define OCDDSR_RUNSTALLTOGGLE BIT(23)
#define OCDDSR_RUNSTALLSAMPLE BIT(24)
#define OCDDSR_BREACKOUTACKITI BIT(25)
#define OCDDSR_BREAKINITI BIT(26)
#define OCDDSR_DBGMODPOWERON BIT(31)
#define DEBUGCAUSE_IC BIT(0) /* ICOUNT exception */
#define DEBUGCAUSE_IB BIT(1) /* IBREAK exception */
#define DEBUGCAUSE_DB BIT(2) /* DBREAK exception */
#define DEBUGCAUSE_BI BIT(3) /* BREAK instruction encountered */
#define DEBUGCAUSE_BN BIT(4) /* BREAK.N instruction encountered */
#define DEBUGCAUSE_DI BIT(5) /* Debug Interrupt */
#define TRAXCTRL_TREN BIT(0) /* Trace enable. Tracing starts on 0->1 */
#define TRAXCTRL_TRSTP BIT(1) /* Trace Stop. Make 1 to stop trace. */
#define TRAXCTRL_PCMEN BIT(2) /* PC match enable */
#define TRAXCTRL_PTIEN BIT(4) /* Processor-trigger enable */
#define TRAXCTRL_CTIEN BIT(5) /* Cross-trigger enable */
#define TRAXCTRL_TMEN BIT(7) /* Tracemem Enable. Always set. */
#define TRAXCTRL_CNTU BIT(9) /* Post-stop-trigger countdown units; selects when DelayCount-- happens.
*0 - every 32-bit word written to tracemem, 1 - every cpu instruction */
#define TRAXCTRL_TSEN BIT(11) /* Undocumented/deprecated? */
#define TRAXCTRL_SMPER_SHIFT 12 /* Send sync every 2^(9-smper) messages. 7=reserved, 0=no sync msg */
#define TRAXCTRL_SMPER_MASK 0x07 /* Synchronization message period */
#define TRAXCTRL_PTOWT BIT(16) /* Processor Trigger Out (OCD halt) enabled when stop triggered */
#define TRAXCTRL_PTOWS BIT(17) /* Processor Trigger Out (OCD halt) enabled when trace stop completes */
#define TRAXCTRL_CTOWT BIT(20) /* Cross-trigger Out enabled when stop triggered */
#define TRAXCTRL_CTOWS BIT(21) /* Cross-trigger Out enabled when trace stop completes */
#define TRAXCTRL_ITCTO BIT(22) /* Integration mode: cross-trigger output */
#define TRAXCTRL_ITCTIA BIT(23) /* Integration mode: cross-trigger ack */
#define TRAXCTRL_ITATV BIT(24) /* replaces ATID when in integration mode: ATVALID output */
#define TRAXCTRL_ATID_MASK 0x7F /* ARB source ID */
#define TRAXCTRL_ATID_SHIFT 24
#define TRAXCTRL_ATEN BIT(31) /* ATB interface enable */
#define TRAXSTAT_TRACT BIT(0) /* Trace active flag. */
#define TRAXSTAT_TRIG BIT(1) /* Trace stop trigger. Clears on TREN 1->0 */
#define TRAXSTAT_PCMTG BIT(2) /* Stop trigger caused by PC match. Clears on TREN 1->0 */
#define TRAXSTAT_PJTR BIT(3) /* JTAG transaction result. 1=err in preceding jtag transaction. */
#define TRAXSTAT_PTITG BIT(4) /* Stop trigger caused by Processor Trigger Input.Clears on TREN 1->0 */
#define TRAXSTAT_CTITG BIT(5) /* Stop trigger caused by Cross-Trigger Input. Clears on TREN 1->0 */
#define TRAXSTAT_MEMSZ_SHIFT 8 /* Traceram size inducator. Usable trace ram is 2^MEMSZ bytes. */
#define TRAXSTAT_MEMSZ_MASK 0x1F
#define TRAXSTAT_PTO BIT(16) /* Processor Trigger Output: current value */
#define TRAXSTAT_CTO BIT(17) /* Cross-Trigger Output: current value */
#define TRAXSTAT_ITCTOA BIT(22) /* Cross-Trigger Out Ack: current value */
#define TRAXSTAT_ITCTI BIT(23) /* Cross-Trigger Input: current value */
#define TRAXSTAT_ITATR BIT(24) /* ATREADY Input: current value */
#define TRAXADDR_TADDR_SHIFT 0 /* Trax memory address, in 32-bit words. */
#define TRAXADDR_TADDR_MASK 0x1FFFFF /* Actually is only as big as the trace buffer size max addr. */
#define TRAXADDR_TWRAP_SHIFT 21 /* Amount of times TADDR has overflown */
#define TRAXADDR_TWRAP_MASK 0x3FF
#define TRAXADDR_TWSAT BIT(31) /* 1 if TWRAP has overflown, clear by disabling tren.*/
#define PCMATCHCTRL_PCML_SHIFT 0 /* Amount of lower bits to ignore in pc trigger register */
#define PCMATCHCTRL_PCML_MASK 0x1F
#define PCMATCHCTRL_PCMS BIT(31) /* PC Match Sense, 0-match when procs PC is in-range, 1-match when
*out-of-range */
#define XTENSA_MAX_PERF_COUNTERS 2
#define XTENSA_MAX_PERF_SELECT 32
#define XTENSA_MAX_PERF_MASK 0xffff
#define XTENSA_STOPMASK_DISABLED UINT32_MAX
struct xtensa_debug_module;
struct xtensa_debug_ops {
/** enable operation */
int (*queue_enable)(struct xtensa_debug_module *dm);
/** register read. */
int (*queue_reg_read)(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data);
/** register write. */
int (*queue_reg_write)(struct xtensa_debug_module *dm, unsigned int reg, uint32_t data);
};
struct xtensa_power_ops {
/** register read. */
int (*queue_reg_read)(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data,
uint8_t clear);
/** register write. */
int (*queue_reg_write)(struct xtensa_debug_module *dm, unsigned int reg, uint8_t data);
};
typedef uint8_t xtensa_pwrstat_t;
typedef uint32_t xtensa_ocdid_t;
typedef uint32_t xtensa_dsr_t;
typedef uint32_t xtensa_traxstat_t;
struct xtensa_power_status {
xtensa_pwrstat_t stat;
xtensa_pwrstat_t stath;
/* TODO: do not need to keep previous status to detect that core or debug module has been
* reset, */
/* we can clear PWRSTAT_DEBUGWASRESET and PWRSTAT_COREWASRESET after reading will do
* the job; */
/* upon next reet those bits will be set again. So we can get rid of
* xtensa_dm_power_status_cache_reset() and xtensa_dm_power_status_cache(). */
xtensa_pwrstat_t prev_stat;
};
struct xtensa_core_status {
xtensa_dsr_t dsr;
};
struct xtensa_trace_config {
uint32_t ctrl;
uint32_t memaddr_start;
uint32_t memaddr_end;
uint32_t addr;
};
struct xtensa_trace_status {
xtensa_traxstat_t stat;
};
struct xtensa_trace_start_config {
uint32_t stoppc;
bool after_is_words;
uint32_t after;
uint32_t stopmask; /* UINT32_MAX: disable PC match option */
};
struct xtensa_perfmon_config {
int select;
uint32_t mask;
int kernelcnt;
int tracelevel;
};
struct xtensa_perfmon_result {
uint64_t value;
bool overflow;
};
struct xtensa_debug_module_config {
const struct xtensa_power_ops *pwr_ops;
const struct xtensa_debug_ops *dbg_ops;
struct jtag_tap *tap;
void (*queue_tdi_idle)(struct target *target);
void *queue_tdi_idle_arg;
};
struct xtensa_debug_module {
const struct xtensa_power_ops *pwr_ops;
const struct xtensa_debug_ops *dbg_ops;
struct jtag_tap *tap;
void (*queue_tdi_idle)(struct target *target);
void *queue_tdi_idle_arg;
struct xtensa_power_status power_status;
struct xtensa_core_status core_status;
xtensa_ocdid_t device_id;
};
int xtensa_dm_init(struct xtensa_debug_module *dm, const struct xtensa_debug_module_config *cfg);
int xtensa_dm_queue_enable(struct xtensa_debug_module *dm);
int xtensa_dm_queue_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *value);
int xtensa_dm_queue_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint32_t value);
int xtensa_dm_queue_pwr_reg_read(struct xtensa_debug_module *dm, unsigned int reg, uint8_t *data, uint8_t clear);
int xtensa_dm_queue_pwr_reg_write(struct xtensa_debug_module *dm, unsigned int reg, uint8_t data);
static inline void xtensa_dm_queue_tdi_idle(struct xtensa_debug_module *dm)
{
if (dm->queue_tdi_idle)
dm->queue_tdi_idle(dm->queue_tdi_idle_arg);
}
int xtensa_dm_power_status_read(struct xtensa_debug_module *dm, uint32_t clear);
static inline void xtensa_dm_power_status_cache_reset(struct xtensa_debug_module *dm)
{
dm->power_status.prev_stat = 0;
}
static inline void xtensa_dm_power_status_cache(struct xtensa_debug_module *dm)
{
dm->power_status.prev_stat = dm->power_status.stath;
}
static inline xtensa_pwrstat_t xtensa_dm_power_status_get(struct xtensa_debug_module *dm)
{
return dm->power_status.stat;
}
int xtensa_dm_core_status_read(struct xtensa_debug_module *dm);
int xtensa_dm_core_status_clear(struct xtensa_debug_module *dm, xtensa_dsr_t bits);
int xtensa_dm_core_status_check(struct xtensa_debug_module *dm);
static inline xtensa_dsr_t xtensa_dm_core_status_get(struct xtensa_debug_module *dm)
{
return dm->core_status.dsr;
}
int xtensa_dm_device_id_read(struct xtensa_debug_module *dm);
static inline xtensa_ocdid_t xtensa_dm_device_id_get(struct xtensa_debug_module *dm)
{
return dm->device_id;
}
int xtensa_dm_trace_start(struct xtensa_debug_module *dm, struct xtensa_trace_start_config *cfg);
int xtensa_dm_trace_stop(struct xtensa_debug_module *dm, bool pto_enable);
int xtensa_dm_trace_config_read(struct xtensa_debug_module *dm, struct xtensa_trace_config *config);
int xtensa_dm_trace_status_read(struct xtensa_debug_module *dm, struct xtensa_trace_status *status);
int xtensa_dm_trace_data_read(struct xtensa_debug_module *dm, uint8_t *dest, uint32_t size);
static inline bool xtensa_dm_is_online(struct xtensa_debug_module *dm)
{
int res = xtensa_dm_device_id_read(dm);
if (res != ERROR_OK)
return false;
return (dm->device_id != 0xffffffff && dm->device_id != 0);
}
static inline bool xtensa_dm_tap_was_reset(struct xtensa_debug_module *dm)
{
return !(dm->power_status.prev_stat & PWRSTAT_DEBUGWASRESET) &&
dm->power_status.stat & PWRSTAT_DEBUGWASRESET;
}
static inline bool xtensa_dm_core_was_reset(struct xtensa_debug_module *dm)
{
return !(dm->power_status.prev_stat & PWRSTAT_COREWASRESET) &&
dm->power_status.stat & PWRSTAT_COREWASRESET;
}
static inline bool xtensa_dm_core_is_stalled(struct xtensa_debug_module *dm)
{
return dm->core_status.dsr & OCDDSR_RUNSTALLSAMPLE;
}
static inline bool xtensa_dm_is_powered(struct xtensa_debug_module *dm)
{
return dm->core_status.dsr & OCDDSR_DBGMODPOWERON;
}
int xtensa_dm_perfmon_enable(struct xtensa_debug_module *dm, int counter_id,
const struct xtensa_perfmon_config *config);
int xtensa_dm_perfmon_dump(struct xtensa_debug_module *dm, int counter_id,
struct xtensa_perfmon_result *out_result);
#endif /* OPENOCD_TARGET_XTENSA_DEBUG_MODULE_H */

View File

@@ -0,0 +1,278 @@
/***************************************************************************
* Generic Xtensa target API for OpenOCD *
* Copyright (C) 2016-2019 Espressif Systems Ltd. *
* Author: Angus Gratton gus@projectgus.com *
* Author: Jeroen Domburg <jeroen@espressif.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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_TARGET_XTENSA_REGS_H
#define OPENOCD_TARGET_XTENSA_REGS_H
struct reg_arch_type;
enum xtensa_reg_id {
XT_REG_IDX_PC = 0,
XT_REG_IDX_AR0,
XT_REG_IDX_AR1,
XT_REG_IDX_AR2,
XT_REG_IDX_AR3,
XT_REG_IDX_AR4,
XT_REG_IDX_AR5,
XT_REG_IDX_AR6,
XT_REG_IDX_AR7,
XT_REG_IDX_AR8,
XT_REG_IDX_AR9,
XT_REG_IDX_AR10,
XT_REG_IDX_AR11,
XT_REG_IDX_AR12,
XT_REG_IDX_AR13,
XT_REG_IDX_AR14,
XT_REG_IDX_AR15,
XT_REG_IDX_AR16,
XT_REG_IDX_AR17,
XT_REG_IDX_AR18,
XT_REG_IDX_AR19,
XT_REG_IDX_AR20,
XT_REG_IDX_AR21,
XT_REG_IDX_AR22,
XT_REG_IDX_AR23,
XT_REG_IDX_AR24,
XT_REG_IDX_AR25,
XT_REG_IDX_AR26,
XT_REG_IDX_AR27,
XT_REG_IDX_AR28,
XT_REG_IDX_AR29,
XT_REG_IDX_AR30,
XT_REG_IDX_AR31,
XT_REG_IDX_AR32,
XT_REG_IDX_AR33,
XT_REG_IDX_AR34,
XT_REG_IDX_AR35,
XT_REG_IDX_AR36,
XT_REG_IDX_AR37,
XT_REG_IDX_AR38,
XT_REG_IDX_AR39,
XT_REG_IDX_AR40,
XT_REG_IDX_AR41,
XT_REG_IDX_AR42,
XT_REG_IDX_AR43,
XT_REG_IDX_AR44,
XT_REG_IDX_AR45,
XT_REG_IDX_AR46,
XT_REG_IDX_AR47,
XT_REG_IDX_AR48,
XT_REG_IDX_AR49,
XT_REG_IDX_AR50,
XT_REG_IDX_AR51,
XT_REG_IDX_AR52,
XT_REG_IDX_AR53,
XT_REG_IDX_AR54,
XT_REG_IDX_AR55,
XT_REG_IDX_AR56,
XT_REG_IDX_AR57,
XT_REG_IDX_AR58,
XT_REG_IDX_AR59,
XT_REG_IDX_AR60,
XT_REG_IDX_AR61,
XT_REG_IDX_AR62,
XT_REG_IDX_AR63,
XT_REG_IDX_LBEG,
XT_REG_IDX_LEND,
XT_REG_IDX_LCOUNT,
XT_REG_IDX_SAR,
XT_REG_IDX_WINDOWBASE,
XT_REG_IDX_WINDOWSTART,
XT_REG_IDX_CONFIGID0,
XT_REG_IDX_CONFIGID1,
XT_REG_IDX_PS,
XT_REG_IDX_THREADPTR,
XT_REG_IDX_BR,
XT_REG_IDX_SCOMPARE1,
XT_REG_IDX_ACCLO,
XT_REG_IDX_ACCHI,
XT_REG_IDX_M0,
XT_REG_IDX_M1,
XT_REG_IDX_M2,
XT_REG_IDX_M3,
XT_REG_IDX_F0,
XT_REG_IDX_F1,
XT_REG_IDX_F2,
XT_REG_IDX_F3,
XT_REG_IDX_F4,
XT_REG_IDX_F5,
XT_REG_IDX_F6,
XT_REG_IDX_F7,
XT_REG_IDX_F8,
XT_REG_IDX_F9,
XT_REG_IDX_F10,
XT_REG_IDX_F11,
XT_REG_IDX_F12,
XT_REG_IDX_F13,
XT_REG_IDX_F14,
XT_REG_IDX_F15,
XT_REG_IDX_FCR,
XT_REG_IDX_FSR,
XT_REG_IDX_MMID,
XT_REG_IDX_IBREAKENABLE,
XT_REG_IDX_MEMCTL,
XT_REG_IDX_ATOMCTL,
XT_REG_IDX_IBREAKA0,
XT_REG_IDX_IBREAKA1,
XT_REG_IDX_DBREAKA0,
XT_REG_IDX_DBREAKA1,
XT_REG_IDX_DBREAKC0,
XT_REG_IDX_DBREAKC1,
XT_REG_IDX_EPC1,
XT_REG_IDX_EPC2,
XT_REG_IDX_EPC3,
XT_REG_IDX_EPC4,
XT_REG_IDX_EPC5,
XT_REG_IDX_EPC6,
XT_REG_IDX_EPC7,
XT_REG_IDX_DEPC,
XT_REG_IDX_EPS2,
XT_REG_IDX_EPS3,
XT_REG_IDX_EPS4,
XT_REG_IDX_EPS5,
XT_REG_IDX_EPS6,
XT_REG_IDX_EPS7,
XT_REG_IDX_EXCSAVE1,
XT_REG_IDX_EXCSAVE2,
XT_REG_IDX_EXCSAVE3,
XT_REG_IDX_EXCSAVE4,
XT_REG_IDX_EXCSAVE5,
XT_REG_IDX_EXCSAVE6,
XT_REG_IDX_EXCSAVE7,
XT_REG_IDX_CPENABLE,
XT_REG_IDX_INTERRUPT,
XT_REG_IDX_INTSET,
XT_REG_IDX_INTCLEAR,
XT_REG_IDX_INTENABLE,
XT_REG_IDX_VECBASE,
XT_REG_IDX_EXCCAUSE,
XT_REG_IDX_DEBUGCAUSE,
XT_REG_IDX_CCOUNT,
XT_REG_IDX_PRID,
XT_REG_IDX_ICOUNT,
XT_REG_IDX_ICOUNTLEVEL,
XT_REG_IDX_EXCVADDR,
XT_REG_IDX_CCOMPARE0,
XT_REG_IDX_CCOMPARE1,
XT_REG_IDX_CCOMPARE2,
XT_REG_IDX_MISC0,
XT_REG_IDX_MISC1,
XT_REG_IDX_MISC2,
XT_REG_IDX_MISC3,
XT_REG_IDX_LITBASE,
XT_REG_IDX_PTEVADDR,
XT_REG_IDX_RASID,
XT_REG_IDX_ITLBCFG,
XT_REG_IDX_DTLBCFG,
XT_REG_IDX_MEPC,
XT_REG_IDX_MEPS,
XT_REG_IDX_MESAVE,
XT_REG_IDX_MESR,
XT_REG_IDX_MECR,
XT_REG_IDX_MEVADDR,
XT_REG_IDX_A0,
XT_REG_IDX_A1,
XT_REG_IDX_A2,
XT_REG_IDX_A3,
XT_REG_IDX_A4,
XT_REG_IDX_A5,
XT_REG_IDX_A6,
XT_REG_IDX_A7,
XT_REG_IDX_A8,
XT_REG_IDX_A9,
XT_REG_IDX_A10,
XT_REG_IDX_A11,
XT_REG_IDX_A12,
XT_REG_IDX_A13,
XT_REG_IDX_A14,
XT_REG_IDX_A15,
XT_REG_IDX_PWRCTL,
XT_REG_IDX_PWRSTAT,
XT_REG_IDX_ERISTAT,
XT_REG_IDX_CS_ITCTRL,
XT_REG_IDX_CS_CLAIMSET,
XT_REG_IDX_CS_CLAIMCLR,
XT_REG_IDX_CS_LOCKACCESS,
XT_REG_IDX_CS_LOCKSTATUS,
XT_REG_IDX_CS_AUTHSTATUS,
XT_REG_IDX_FAULT_INFO,
XT_REG_IDX_TRAX_ID,
XT_REG_IDX_TRAX_CTRL,
XT_REG_IDX_TRAX_STAT,
XT_REG_IDX_TRAX_DATA,
XT_REG_IDX_TRAX_ADDR,
XT_REG_IDX_TRAX_PCTRIGGER,
XT_REG_IDX_TRAX_PCMATCH,
XT_REG_IDX_TRAX_DELAY,
XT_REG_IDX_TRAX_MEMSTART,
XT_REG_IDX_TRAX_MEMEND,
XT_REG_IDX_PMG,
XT_REG_IDX_PMPC,
XT_REG_IDX_PM0,
XT_REG_IDX_PM1,
XT_REG_IDX_PMCTRL0,
XT_REG_IDX_PMCTRL1,
XT_REG_IDX_PMSTAT0,
XT_REG_IDX_PMSTAT1,
XT_REG_IDX_OCD_ID,
XT_REG_IDX_OCD_DCRCLR,
XT_REG_IDX_OCD_DCRSET,
XT_REG_IDX_OCD_DSR,
XT_REG_IDX_OCD_DDR,
XT_NUM_REGS,
/* chip-specific user registers go after ISA-defined ones */
XT_USR_REG_START = XT_NUM_REGS
};
typedef uint32_t xtensa_reg_val_t;
enum xtensa_reg_type {
XT_REG_GENERAL = 0, /* General-purpose register; part of the windowed register set */
XT_REG_USER = 1, /* User register, needs RUR to read */
XT_REG_SPECIAL = 2, /* Special register, needs RSR to read */
XT_REG_DEBUG = 3, /* Register used for the debug interface. Don't mess with this. */
XT_REG_RELGEN = 4, /* Relative general address. Points to the absolute addresses plus the window
*index */
XT_REG_FR = 5, /* Floating-point register */
};
enum xtensa_reg_flags {
XT_REGF_NOREAD = 0x01, /* Register is write-only */
XT_REGF_COPROC0 = 0x02 /* Can't be read if coproc0 isn't enabled */
};
struct xtensa_reg_desc {
const char *name;
unsigned int reg_num; /* ISA register num (meaning depends on register type) */
enum xtensa_reg_type type;
enum xtensa_reg_flags flags;
};
struct xtensa_user_reg_desc {
const char *name;
/* ISA register num (meaning depends on register type) */
unsigned int reg_num;
enum xtensa_reg_flags flags;
uint32_t size;
const struct reg_arch_type *type;
};
extern const struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS];
#endif /* OPENOCD_TARGET_XTENSA_REGS_H */