diff options
author | Erhan Kurubas <erhan.kurubas@espressif.com> | 2022-04-21 07:53:54 +0200 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2022-06-04 08:18:44 +0000 |
commit | 78c87f5e81f8b3ee2a72aa546f87985596cb2b9f (patch) | |
tree | d4507e98ff15487c2ffb6a2890f23cd650bc3c6e /src/target/xtensa/xtensa.h | |
parent | b470b664ca7ba3f21684848c3819d696fb3c890a (diff) | |
download | riscv-openocd-78c87f5e81f8b3ee2a72aa546f87985596cb2b9f.zip riscv-openocd-78c87f5e81f8b3ee2a72aa546f87985596cb2b9f.tar.gz riscv-openocd-78c87f5e81f8b3ee2a72aa546f87985596cb2b9f.tar.bz2 |
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
Diffstat (limited to 'src/target/xtensa/xtensa.h')
-rw-r--r-- | src/target/xtensa/xtensa.h | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h new file mode 100644 index 0000000..d8b15e1 --- /dev/null +++ b/src/target/xtensa/xtensa.h @@ -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 */ |