target: add generic Xtensa LX support
Generic Xtensa LX support extends the original Espressif/Xtensa patch-set to support arbitrary Xtensa configurations, as defined in a core-specific .cfg file. Not yet fully-featured. Additional functionality to be added: - Xtensa NX support - DAP/SWD support - File-IO support - Generic Xtensa multi-core support Valgrind-clean, no new Clang analyzer warnings Signed-off-by: Ian Thompson <ianst@cadence.com> Change-Id: I08e7bf8fa57c25b5d0cb75a1aa7a2ac13a380c52 Reviewed-on: https://review.openocd.org/c/openocd/+/7055 Tested-by: jenkins Reviewed-by: Erhan Kurubas <erhan.kurubas@espressif.com> Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
committed by
Antonio Borneo
parent
be2e5c6c35
commit
ce5ca9f7ba
@@ -4,6 +4,8 @@ noinst_LTLIBRARIES += %D%/libxtensa.la
|
||||
%C%_libxtensa_la_SOURCES = \
|
||||
%D%/xtensa.c \
|
||||
%D%/xtensa.h \
|
||||
%D%/xtensa_chip.c \
|
||||
%D%/xtensa_chip.h \
|
||||
%D%/xtensa_debug_module.c \
|
||||
%D%/xtensa_debug_module.h \
|
||||
%D%/xtensa_regs.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Generic Xtensa target *
|
||||
* Copyright (C) 2020-2022 Cadence Design Systems, Inc. *
|
||||
* Copyright (C) 2019 Espressif Systems Ltd. *
|
||||
***************************************************************************/
|
||||
|
||||
@@ -19,41 +20,77 @@
|
||||
* Holds the interface to Xtensa cores.
|
||||
*/
|
||||
|
||||
#define XT_ISNS_SZ_MAX 3
|
||||
/* Big-endian vs. little-endian detection */
|
||||
#define XT_ISBE(X) ((X)->target->endianness == TARGET_BIG_ENDIAN)
|
||||
|
||||
#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)
|
||||
/* 24-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
|
||||
#define XT_INS_BREAK_LE(S, T) (0x004000 | (((S) & 0xF) << 8) | (((T) & 0xF) << 4))
|
||||
#define XT_INS_BREAK_BE(S, T) (0x000400 | (((S) & 0xF) << 12) | ((T) & 0xF))
|
||||
#define XT_INS_BREAK(X, S, T) (XT_ISBE(X) ? XT_INS_BREAK_BE(S, T) : XT_INS_BREAK_LE(S, T))
|
||||
|
||||
#define XT_LOCAL_MEM_REGIONS_NUM_MAX 8
|
||||
/* 16-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
|
||||
#define XT_INS_BREAKN_LE(IMM4) (0xF02D | (((IMM4) & 0xF) << 8))
|
||||
#define XT_INS_BREAKN_BE(IMM4) (0x0FD2 | (((IMM4) & 0xF) << 12))
|
||||
#define XT_INS_BREAKN(X, IMM4) (XT_ISBE(X) ? XT_INS_BREAKN_BE(IMM4) : XT_INS_BREAKN_LE(IMM4))
|
||||
|
||||
#define XT_AREGS_NUM_MAX 64
|
||||
#define XT_USER_REGS_NUM_MAX 256
|
||||
#define XT_ISNS_SZ_MAX 3
|
||||
|
||||
#define XT_MEM_ACCESS_NONE 0x0
|
||||
#define XT_MEM_ACCESS_READ 0x1
|
||||
#define XT_MEM_ACCESS_WRITE 0x2
|
||||
#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_PS_WOE_MSK BIT(18)
|
||||
|
||||
enum xtensa_mem_err_detect {
|
||||
XT_MEM_ERR_DETECT_NONE,
|
||||
XT_MEM_ERR_DETECT_PARITY,
|
||||
XT_MEM_ERR_DETECT_ECC,
|
||||
#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
|
||||
|
||||
#define XT_MAX_TIE_REG_WIDTH (512) /* TIE register file max 4096 bits */
|
||||
#define XT_QUERYPKT_RESP_MAX (XT_MAX_TIE_REG_WIDTH * 2 + 1)
|
||||
|
||||
enum xtensa_qerr_e {
|
||||
XT_QERR_INTERNAL = 0,
|
||||
XT_QERR_FAIL,
|
||||
XT_QERR_INVAL,
|
||||
XT_QERR_MEM,
|
||||
XT_QERR_NUM,
|
||||
};
|
||||
|
||||
/* An and ARn registers potentially used as scratch regs */
|
||||
enum xtensa_ar_scratch_set_e {
|
||||
XT_AR_SCRATCH_A3 = 0,
|
||||
XT_AR_SCRATCH_AR3,
|
||||
XT_AR_SCRATCH_A4,
|
||||
XT_AR_SCRATCH_AR4,
|
||||
XT_AR_SCRATCH_NUM
|
||||
};
|
||||
|
||||
struct xtensa_keyval_info_s {
|
||||
char *chrval;
|
||||
int intval;
|
||||
};
|
||||
|
||||
enum xtensa_type {
|
||||
XT_UNDEF = 0,
|
||||
XT_LX,
|
||||
};
|
||||
|
||||
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;
|
||||
uint32_t line_size;
|
||||
uint32_t size;
|
||||
int writeback;
|
||||
};
|
||||
|
||||
struct xtensa_local_mem_region_config {
|
||||
target_addr_t base;
|
||||
uint32_t size;
|
||||
enum xtensa_mem_err_detect mem_err_check;
|
||||
int access;
|
||||
};
|
||||
|
||||
@@ -66,13 +103,14 @@ struct xtensa_mmu_config {
|
||||
bool enabled;
|
||||
uint8_t itlb_entries_count;
|
||||
uint8_t dtlb_entries_count;
|
||||
bool ivarway56;
|
||||
bool dvarway56;
|
||||
};
|
||||
|
||||
struct xtensa_exception_config {
|
||||
struct xtensa_mpu_config {
|
||||
bool enabled;
|
||||
uint8_t depc_num;
|
||||
uint8_t nfgseg;
|
||||
uint32_t minsegsize;
|
||||
bool lockable;
|
||||
bool execonly;
|
||||
};
|
||||
|
||||
struct xtensa_irq_config {
|
||||
@@ -82,8 +120,8 @@ struct xtensa_irq_config {
|
||||
|
||||
struct xtensa_high_prio_irq_config {
|
||||
bool enabled;
|
||||
uint8_t level_num;
|
||||
uint8_t excm_level;
|
||||
uint8_t nmi_num;
|
||||
};
|
||||
|
||||
struct xtensa_debug_config {
|
||||
@@ -91,7 +129,7 @@ struct xtensa_debug_config {
|
||||
uint8_t irq_level;
|
||||
uint8_t ibreaks_num;
|
||||
uint8_t dbreaks_num;
|
||||
uint8_t icount_sz;
|
||||
uint8_t perfcount_num;
|
||||
};
|
||||
|
||||
struct xtensa_tracing_config {
|
||||
@@ -100,48 +138,26 @@ struct xtensa_tracing_config {
|
||||
bool reversed_mem_access;
|
||||
};
|
||||
|
||||
struct xtensa_timer_irq_config {
|
||||
bool enabled;
|
||||
uint8_t comp_num;
|
||||
};
|
||||
|
||||
struct xtensa_config {
|
||||
bool density;
|
||||
enum xtensa_type core_type;
|
||||
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);
|
||||
bool exceptions;
|
||||
struct xtensa_irq_config irq;
|
||||
struct xtensa_high_prio_irq_config high_irq;
|
||||
struct xtensa_mmu_config mmu;
|
||||
struct xtensa_mpu_config mpu;
|
||||
struct xtensa_debug_config debug;
|
||||
struct xtensa_tracing_config trace;
|
||||
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;
|
||||
struct xtensa_local_mem_config sram;
|
||||
struct xtensa_local_mem_config srom;
|
||||
};
|
||||
|
||||
typedef uint32_t xtensa_insn_t;
|
||||
@@ -175,13 +191,26 @@ struct xtensa_sw_breakpoint {
|
||||
*/
|
||||
struct xtensa {
|
||||
unsigned int common_magic;
|
||||
const struct xtensa_config *core_config;
|
||||
struct xtensa_chip_common *xtensa_chip;
|
||||
struct xtensa_config *core_config;
|
||||
struct xtensa_debug_module dbg_mod;
|
||||
struct reg_cache *core_cache;
|
||||
unsigned int regs_num;
|
||||
unsigned int total_regs_num;
|
||||
unsigned int core_regs_num;
|
||||
bool regmap_contiguous;
|
||||
unsigned int genpkt_regs_num;
|
||||
struct xtensa_reg_desc **contiguous_regs_desc;
|
||||
struct reg **contiguous_regs_list;
|
||||
/* Per-config Xtensa registers as specified via "xtreg" in xtensa-core*.cfg */
|
||||
struct xtensa_reg_desc *optregs;
|
||||
unsigned int num_optregs;
|
||||
struct reg *empty_regs;
|
||||
char qpkt_resp[XT_QUERYPKT_RESP_MAX];
|
||||
/* An array of pointers to buffers to backup registers' values while algo is run on target.
|
||||
* Size is 'regs_num'. */
|
||||
void **algo_context_backup;
|
||||
unsigned int eps_dbglevel_idx;
|
||||
unsigned int dbregs_num;
|
||||
struct target *target;
|
||||
bool reset_asserted;
|
||||
enum xtensa_stepping_isr_mode stepping_isr_mode;
|
||||
@@ -192,11 +221,18 @@ struct xtensa {
|
||||
bool permissive_mode; /* bypass memory checks */
|
||||
bool suppress_dsr_errors;
|
||||
uint32_t smp_break;
|
||||
uint32_t spill_loc;
|
||||
unsigned int spill_bytes;
|
||||
uint8_t *spill_buf;
|
||||
int8_t probe_lsddr32p;
|
||||
/* 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 proc_syscall;
|
||||
bool halt_request;
|
||||
struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM];
|
||||
bool regs_fetched; /* true after first register fetch completed successfully */
|
||||
};
|
||||
|
||||
@@ -210,7 +246,6 @@ static inline struct xtensa *target_to_xtensa(struct target *target)
|
||||
|
||||
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);
|
||||
@@ -233,11 +268,41 @@ static inline bool xtensa_data_addr_valid(struct target *target, uint32_t 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))
|
||||
if (xtensa_addr_in_mem(&xtensa->core_config->sram, addr))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int xtensa_queue_dbg_reg_read(struct xtensa *xtensa, unsigned int reg, uint8_t *data)
|
||||
{
|
||||
struct xtensa_debug_module *dm = &xtensa->dbg_mod;
|
||||
|
||||
if (!xtensa->core_config->trace.enabled &&
|
||||
(reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
|
||||
LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return dm->dbg_ops->queue_reg_read(dm, reg, data);
|
||||
}
|
||||
|
||||
static inline int xtensa_queue_dbg_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data)
|
||||
{
|
||||
struct xtensa_debug_module *dm = &xtensa->dbg_mod;
|
||||
|
||||
if (!xtensa->core_config->trace.enabled &&
|
||||
(reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
|
||||
LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return dm->dbg_ops->queue_reg_write(dm, reg, data);
|
||||
}
|
||||
|
||||
static inline int xtensa_core_status_clear(struct target *target, uint32_t bits)
|
||||
{
|
||||
struct xtensa *xtensa = target_to_xtensa(target);
|
||||
return xtensa_dm_core_status_clear(&xtensa->dbg_mod, bits);
|
||||
}
|
||||
|
||||
int xtensa_core_status_check(struct target *target);
|
||||
|
||||
int xtensa_examine(struct target *target);
|
||||
@@ -248,11 +313,15 @@ 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);
|
||||
void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx, 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);
|
||||
uint32_t xtensa_cause_get(struct target *target);
|
||||
void xtensa_cause_clear(struct target *target);
|
||||
void xtensa_cause_reset(struct target *target);
|
||||
int xtensa_poll(struct target *target);
|
||||
void xtensa_on_poll(struct target *target);
|
||||
int xtensa_halt(struct target *target);
|
||||
@@ -281,16 +350,22 @@ int xtensa_write_buffer(struct target *target, target_addr_t address, uint32_t c
|
||||
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_soft_reset_halt(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);
|
||||
int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p);
|
||||
|
||||
|
||||
COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtmmu_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_xtregfmt_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_permissive_mode_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_smpbreak_do, struct target *target);
|
||||
@@ -300,8 +375,6 @@ COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_tracestop_do, struct xtensa *xtensa);
|
||||
COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname);
|
||||
|
||||
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 */
|
||||
|
||||
170
src/target/xtensa/xtensa_chip.c
Normal file
170
src/target/xtensa/xtensa_chip.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/***************************************************************************
|
||||
* Xtensa Chip-level Target Support for OpenOCD *
|
||||
* Copyright (C) 2020-2022 Cadence Design Systems, Inc. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "assert.h"
|
||||
#include <target/target.h>
|
||||
#include <target/target_type.h>
|
||||
#include <target/arm_adi_v5.h>
|
||||
#include <rtos/rtos.h>
|
||||
#include "xtensa_chip.h"
|
||||
|
||||
int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
|
||||
struct xtensa_debug_module_config *dm_cfg)
|
||||
{
|
||||
struct xtensa_chip_common *xtensa_chip = (struct xtensa_chip_common *)arch_info;
|
||||
int ret = xtensa_init_arch_info(target, &xtensa_chip->xtensa, dm_cfg);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
/* All xtensa target structures point back to original xtensa_chip */
|
||||
xtensa_chip->xtensa.xtensa_chip = arch_info;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target *target)
|
||||
{
|
||||
return xtensa_target_init(cmd_ctx, target);
|
||||
}
|
||||
|
||||
int xtensa_chip_arch_state(struct target *target)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int xtensa_chip_poll(struct target *target)
|
||||
{
|
||||
enum target_state old_state = target->state;
|
||||
int ret = xtensa_poll(target);
|
||||
|
||||
if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
|
||||
/*Call any event callbacks that are applicable */
|
||||
if (old_state == TARGET_DEBUG_RUNNING)
|
||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
||||
else
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xtensa_chip_virt2phys(struct target *target,
|
||||
target_addr_t virtual, target_addr_t *physical)
|
||||
{
|
||||
if (physical) {
|
||||
*physical = virtual;
|
||||
return ERROR_OK;
|
||||
}
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
static const struct xtensa_debug_ops xtensa_chip_dm_dbg_ops = {
|
||||
.queue_enable = xtensa_dm_queue_enable,
|
||||
.queue_reg_read = xtensa_dm_queue_reg_read,
|
||||
.queue_reg_write = xtensa_dm_queue_reg_write
|
||||
};
|
||||
|
||||
static const struct xtensa_power_ops xtensa_chip_dm_pwr_ops = {
|
||||
.queue_reg_read = xtensa_dm_queue_pwr_reg_read,
|
||||
.queue_reg_write = xtensa_dm_queue_pwr_reg_write
|
||||
};
|
||||
|
||||
static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp)
|
||||
{
|
||||
struct xtensa_debug_module_config xtensa_chip_dm_cfg = {
|
||||
.dbg_ops = &xtensa_chip_dm_dbg_ops,
|
||||
.pwr_ops = &xtensa_chip_dm_pwr_ops,
|
||||
.tap = NULL,
|
||||
.queue_tdi_idle = NULL,
|
||||
.queue_tdi_idle_arg = NULL,
|
||||
};
|
||||
|
||||
xtensa_chip_dm_cfg.tap = target->tap;
|
||||
LOG_DEBUG("JTAG: %s:%s pos %d", target->tap->chip, target->tap->tapname, target->tap->abs_chain_position);
|
||||
|
||||
struct xtensa_chip_common *xtensa_chip = calloc(1, sizeof(struct xtensa_chip_common));
|
||||
if (!xtensa_chip) {
|
||||
LOG_ERROR("Failed to alloc chip-level memory!");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int ret = xtensa_chip_init_arch_info(target, xtensa_chip, &xtensa_chip_dm_cfg);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Failed to init arch info!");
|
||||
free(xtensa_chip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Assume running target. If different, the first poll will fix this. */
|
||||
target->state = TARGET_RUNNING;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void xtensa_chip_target_deinit(struct target *target)
|
||||
{
|
||||
struct xtensa *xtensa = target_to_xtensa(target);
|
||||
xtensa_target_deinit(target);
|
||||
free(xtensa->xtensa_chip);
|
||||
}
|
||||
|
||||
static int xtensa_chip_examine(struct target *target)
|
||||
{
|
||||
return xtensa_examine(target);
|
||||
}
|
||||
|
||||
int xtensa_chip_jim_configure(struct target *target, struct jim_getopt_info *goi)
|
||||
{
|
||||
target->has_dap = false;
|
||||
return JIM_CONTINUE;
|
||||
}
|
||||
|
||||
/** Methods for generic example of Xtensa-based chip-level targets. */
|
||||
struct target_type xtensa_chip_target = {
|
||||
.name = "xtensa",
|
||||
|
||||
.poll = xtensa_chip_poll,
|
||||
.arch_state = xtensa_chip_arch_state,
|
||||
|
||||
.halt = xtensa_halt,
|
||||
.resume = xtensa_resume,
|
||||
.step = xtensa_step,
|
||||
|
||||
.assert_reset = xtensa_assert_reset,
|
||||
.deassert_reset = xtensa_deassert_reset,
|
||||
.soft_reset_halt = xtensa_soft_reset_halt,
|
||||
|
||||
.virt2phys = xtensa_chip_virt2phys,
|
||||
.mmu = xtensa_mmu_is_enabled,
|
||||
.read_memory = xtensa_read_memory,
|
||||
.write_memory = xtensa_write_memory,
|
||||
|
||||
.read_buffer = xtensa_read_buffer,
|
||||
.write_buffer = xtensa_write_buffer,
|
||||
|
||||
.checksum_memory = xtensa_checksum_memory,
|
||||
|
||||
.get_gdb_reg_list = xtensa_get_gdb_reg_list,
|
||||
|
||||
.add_breakpoint = xtensa_breakpoint_add,
|
||||
.remove_breakpoint = xtensa_breakpoint_remove,
|
||||
|
||||
.add_watchpoint = xtensa_watchpoint_add,
|
||||
.remove_watchpoint = xtensa_watchpoint_remove,
|
||||
|
||||
.target_create = xtensa_chip_target_create,
|
||||
.target_jim_configure = xtensa_chip_jim_configure,
|
||||
.init_target = xtensa_chip_target_init,
|
||||
.examine = xtensa_chip_examine,
|
||||
.deinit_target = xtensa_chip_target_deinit,
|
||||
|
||||
.gdb_query_custom = xtensa_gdb_query_custom,
|
||||
|
||||
.commands = xtensa_command_handlers,
|
||||
};
|
||||
34
src/target/xtensa/xtensa_chip.h
Normal file
34
src/target/xtensa/xtensa_chip.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/***************************************************************************
|
||||
* Xtensa Chip-level Target Support for OpenOCD *
|
||||
* Copyright (C) 2020-2022 Cadence Design Systems, Inc. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_TARGET_XTENSA_CHIP_H
|
||||
#define OPENOCD_TARGET_XTENSA_CHIP_H
|
||||
|
||||
#include <target/target.h>
|
||||
#include "xtensa.h"
|
||||
#include "xtensa_debug_module.h"
|
||||
|
||||
struct xtensa_chip_common {
|
||||
struct xtensa xtensa;
|
||||
/* Chip-specific extensions can be added here */
|
||||
};
|
||||
|
||||
static inline struct xtensa_chip_common *target_to_xtensa_chip(struct target *target)
|
||||
{
|
||||
return container_of(target->arch_info, struct xtensa_chip_common, xtensa);
|
||||
}
|
||||
|
||||
int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
|
||||
struct xtensa_debug_module_config *dm_cfg);
|
||||
int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target *target);
|
||||
int xtensa_chip_arch_state(struct target *target);
|
||||
void xtensa_chip_queue_tdi_idle(struct target *target);
|
||||
void xtensa_chip_on_reset(struct target *target);
|
||||
bool xtensa_chip_on_halt(struct target *target);
|
||||
void xtensa_chip_on_poll(struct target *target);
|
||||
|
||||
#endif /* OPENOCD_TARGET_XTENSA_CHIP_H */
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Generic Xtensa target API for OpenOCD *
|
||||
* Copyright (C) 2020-2022 Cadence Design Systems, Inc. *
|
||||
* Copyright (C) 2016-2019 Espressif Systems Ltd. *
|
||||
* Author: Angus Gratton gus@projectgus.com *
|
||||
***************************************************************************/
|
||||
@@ -14,6 +15,7 @@ struct reg_arch_type;
|
||||
enum xtensa_reg_id {
|
||||
XT_REG_IDX_PC = 0,
|
||||
XT_REG_IDX_AR0,
|
||||
XT_REG_IDX_ARFIRST = XT_REG_IDX_AR0,
|
||||
XT_REG_IDX_AR1,
|
||||
XT_REG_IDX_AR2,
|
||||
XT_REG_IDX_AR3,
|
||||
@@ -29,152 +31,23 @@ enum xtensa_reg_id {
|
||||
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_ARLAST = 64, /* Max 64 ARs */
|
||||
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_DDR,
|
||||
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,
|
||||
@@ -191,77 +64,72 @@ enum xtensa_reg_id {
|
||||
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
|
||||
XT_NUM_REGS
|
||||
};
|
||||
|
||||
typedef uint32_t xtensa_reg_val_t;
|
||||
|
||||
#define XT_NUM_A_REGS 16
|
||||
|
||||
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 */
|
||||
* index */
|
||||
XT_REG_FR = 5, /* Floating-point register */
|
||||
XT_REG_TIE = 6, /* TIE (custom) register */
|
||||
XT_REG_OTHER = 7, /* Other (typically legacy) register */
|
||||
XT_REG_TYPE_NUM,
|
||||
|
||||
/* enum names must be one of the above types + _VAL or _MASK */
|
||||
XT_REG_GENERAL_MASK = 0xFFC0,
|
||||
XT_REG_GENERAL_VAL = 0x0100,
|
||||
XT_REG_USER_MASK = 0xFF00,
|
||||
XT_REG_USER_VAL = 0x0300,
|
||||
XT_REG_SPECIAL_MASK = 0xFF00,
|
||||
XT_REG_SPECIAL_VAL = 0x0200,
|
||||
XT_REG_DEBUG_MASK = 0xFF00,
|
||||
XT_REG_DEBUG_VAL = 0x0200,
|
||||
XT_REG_RELGEN_MASK = 0xFFE0,
|
||||
XT_REG_RELGEN_VAL = 0x0000,
|
||||
XT_REG_FR_MASK = 0xFFF0,
|
||||
XT_REG_FR_VAL = 0x0030,
|
||||
XT_REG_TIE_MASK = 0xF000,
|
||||
XT_REG_TIE_VAL = 0xF000, /* unused */
|
||||
XT_REG_OTHER_MASK = 0xFFFF,
|
||||
XT_REG_OTHER_VAL = 0xF000, /* unused */
|
||||
|
||||
XT_REG_INDEX_MASK = 0x00FF
|
||||
};
|
||||
|
||||
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 */
|
||||
XT_REGF_COPROC0 = 0x02, /* Can't be read if coproc0 isn't enabled */
|
||||
XT_REGF_MASK = 0x03
|
||||
};
|
||||
|
||||
struct xtensa_reg_desc {
|
||||
const char *name;
|
||||
bool exist;
|
||||
unsigned int reg_num; /* ISA register num (meaning depends on register type) */
|
||||
unsigned int dbreg_num; /* Debugger-visible register num (reg type encoded) */
|
||||
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;
|
||||
};
|
||||
#define _XT_MK_DBREGN(reg_num, reg_type) \
|
||||
((reg_type ## _VAL) | (reg_num))
|
||||
|
||||
extern const struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS];
|
||||
#define _XT_MK_DBREGN_MASK(reg_num, reg_mask) \
|
||||
((reg_mask) | (reg_num))
|
||||
|
||||
#define XT_MK_REG_DESC(n, r, t, f) \
|
||||
{ .name = (n), .exist = false, .reg_num = (r), \
|
||||
.dbreg_num = _XT_MK_DBREGN(r, t), .type = (t), \
|
||||
.flags = (f) }
|
||||
|
||||
extern struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS];
|
||||
|
||||
#endif /* OPENOCD_TARGET_XTENSA_REGS_H */
|
||||
|
||||
Reference in New Issue
Block a user