OpenOCD
esp_xtensa.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Espressif Xtensa target API for OpenOCD *
5  * Copyright (C) 2019 Espressif Systems Ltd. *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <target/smp.h>
15 #include <target/register.h>
16 #include "esp.h"
17 #include "esp_xtensa.h"
18 #include "esp_xtensa_apptrace.h"
19 #include "esp_semihosting.h"
20 #include "esp_xtensa_algorithm.h"
21 
22 #define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_) \
23  do { \
24  uint32_t __internal_val = (_e_); \
25  if (!xtensa_data_addr_valid(target, __internal_val)) { \
26  LOG_ERROR("No valid stub data entry found (0x%" PRIx32 ")!", __internal_val); \
27  return; \
28  } \
29  } while (0)
30 
31 #define ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(_e_) \
32  do { \
33  uint32_t __internal_val = (_e_); \
34  if (__internal_val == 0) { \
35  LOG_ERROR("No valid stub code entry found (0x%" PRIx32 ")!", __internal_val); \
36  return; \
37  } \
38  } while (0)
39 
40 static void esp_xtensa_dbgstubs_info_update(struct target *target);
41 static void esp_xtensa_dbgstubs_addr_check(struct target *target);
42 
44 {
45  struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
46 
47  if (esp_xtensa->esp.dbg_stubs.base == 0)
48  return ERROR_OK;
49 
50  LOG_TARGET_INFO(target, "Restore debug stubs address %" PRIx32, esp_xtensa->esp.dbg_stubs.base);
52  if (res != ERROR_OK) {
53  LOG_ERROR("Failed to write trace status (%d)!", res);
54  return res;
55  }
56  return ERROR_OK;
57 }
59 {
60  /* debug stubs can be used in HALTED state only, so it is OK to get info about them here */
62  return ERROR_OK;
63 }
64 
66  struct esp_xtensa_common *esp_xtensa,
67  struct xtensa_debug_module_config *dm_cfg,
68  const struct esp_semihost_ops *semihost_ops)
69 {
70  int ret = xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg);
71  if (ret != ERROR_OK)
72  return ret;
73  ret = esp_common_init(&esp_xtensa->esp, &xtensa_algo_hw);
74  if (ret != ERROR_OK)
75  return ret;
76 
77  esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops;
78  esp_xtensa->apptrace.hw = &esp_xtensa_apptrace_hw;
79  return ERROR_OK;
80 }
81 
82 int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target *target)
83 {
84  return xtensa_target_init(cmd_ctx, target);
85 }
86 
88 {
89  LOG_DEBUG("start");
90 
93  if (ret != ERROR_OK)
94  return;
95  }
97  free(target_to_esp_xtensa(target)); /* same as free(xtensa) */
98 }
99 
101 {
102  return ERROR_OK;
103 }
104 
106 {
109 
110  int ret = xtensa_poll(target);
111 
113  LOG_TARGET_DEBUG(target, "Clear debug stubs info");
115  }
118  return ret;
119 }
120 
122 {
123  struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
124  uint32_t vec_addr = 0;
125 
126  if (esp_xtensa->esp.dbg_stubs.base != 0)
127  return;
128 
129  int res = esp_xtensa_apptrace_status_reg_read(target, &vec_addr);
130  if (res != ERROR_OK) {
131  LOG_ERROR("Failed to read debug stubs address location (%d)!", res);
132  return;
133  }
134  if (xtensa_data_addr_valid(target, vec_addr)) {
135  LOG_TARGET_INFO(target, "Detected debug stubs @ %" PRIx32, vec_addr);
137  if (res != ERROR_OK)
138  LOG_ERROR("Failed to clear debug stubs address location (%d)!", res);
139  esp_xtensa->esp.dbg_stubs.base = vec_addr;
140  }
141 }
142 
144 {
145  struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
146 
147  if (esp_xtensa->esp.dbg_stubs.base == 0 || esp_xtensa->esp.dbg_stubs.entries_count != 0)
148  return;
149 
150  int res = esp_dbgstubs_table_read(target, &esp_xtensa->esp.dbg_stubs);
151  if (res != ERROR_OK)
152  return;
153  if (esp_xtensa->esp.dbg_stubs.entries_count == 0)
154  return;
155 
156  /* read debug stubs descriptor */
159  sizeof(struct esp_dbg_stubs_desc),
160  (uint8_t *)&esp_xtensa->esp.dbg_stubs.desc);
161  if (res != ERROR_OK) {
162  LOG_ERROR("Failed to read debug stubs descriptor (%d)!", res);
163  return;
164  }
169 }
170 
172 {
174  /* flash breakpoints will be handled in another patch */
175 }
176 
178 {
180  /* flash breakpoints will be handled in another patch */
181 }
182 
183 int esp_xtensa_profiling(struct target *target, uint32_t *samples,
184  uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
185 {
186  struct timeval timeout, now;
188  int retval = ERROR_OK;
189  int res;
190 
191  /* Vary samples per pass to avoid sampling a periodic function periodically */
192  #define MIN_PASS 200
193  #define MAX_PASS 1000
194 
196  timeval_add_time(&timeout, seconds, 0);
197 
198  uint8_t buf[sizeof(uint32_t) * MAX_PASS];
199 
200  /* Capture one sample to verify the register is present and working */
203  if (res != ERROR_OK) {
204  LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go");
205  return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
206  } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) {
207  LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go");
208  return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
209  }
210 
211  LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can...");
212 
213  /* Make sure the target is running */
215  if (target->state == TARGET_HALTED)
216  retval = target_resume(target, 1, 0, 0, 0);
217 
218  if (retval != ERROR_OK) {
219  LOG_TARGET_ERROR(target, "Error while resuming target");
220  return retval;
221  }
222 
223  uint32_t sample_count = 0;
224 
225  for (;;) {
226  uint32_t remaining = max_num_samples - sample_count;
227  uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS;
228  this_pass = this_pass > remaining ? remaining : this_pass;
229  for (uint32_t i = 0; i < this_pass; ++i)
230  xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t));
232  if (res != ERROR_OK) {
233  LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!");
234  return res;
235  }
236 
237  for (uint32_t i = 0; i < this_pass; ++i) {
238  uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32);
239  samples[sample_count++] = sample32;
240  }
241  gettimeofday(&now, NULL);
242  if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) {
243  LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count);
244  break;
245  }
246  }
247 
248  *num_samples = sample_count;
249  return retval;
250 
251  #undef MIN_PASS
252  #undef MAX_PASS
253 }
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:104
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs)
Definition: esp.c:27
int esp_common_init(struct esp_common *esp, const struct esp_algorithm_hw *algo_hw)
Definition: esp.c:17
@ ESP_DBG_STUB_DESC
Definition: esp.h:31
#define ESP_XTENSA_DBGSTUBS_UPDATE_CODE_ENTRY(_e_)
Definition: esp_xtensa.c:31
static void esp_xtensa_dbgstubs_info_update(struct target *target)
Definition: esp_xtensa.c:143
static void esp_xtensa_dbgstubs_addr_check(struct target *target)
Definition: esp_xtensa.c:121
int esp_xtensa_init_arch_info(struct target *target, struct esp_xtensa_common *esp_xtensa, struct xtensa_debug_module_config *dm_cfg, const struct esp_semihost_ops *semihost_ops)
Definition: esp_xtensa.c:65
int esp_xtensa_poll(struct target *target)
Definition: esp_xtensa.c:105
#define ESP_XTENSA_DBGSTUBS_UPDATE_DATA_ENTRY(_e_)
Definition: esp_xtensa.c:22
int esp_xtensa_arch_state(struct target *target)
Definition: esp_xtensa.c:100
void esp_xtensa_target_deinit(struct target *target)
Definition: esp_xtensa.c:87
int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target *target)
Definition: esp_xtensa.c:82
int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint)
Definition: esp_xtensa.c:177
#define MIN_PASS
static int esp_xtensa_dbgstubs_restore(struct target *target)
Definition: esp_xtensa.c:43
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint)
Definition: esp_xtensa.c:171
int esp_xtensa_on_halt(struct target *target)
Definition: esp_xtensa.c:58
int esp_xtensa_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
Definition: esp_xtensa.c:183
#define MAX_PASS
static struct esp_xtensa_common * target_to_esp_xtensa(struct target *target)
Definition: esp_xtensa.h:24
const struct esp_algorithm_hw xtensa_algo_hw
int esp_xtensa_apptrace_status_reg_write(struct target *target, uint32_t stat)
int esp_xtensa_apptrace_status_reg_read(struct target *target, uint32_t *stat)
struct esp32_apptrace_hw esp_xtensa_apptrace_hw
#define LOG_TARGET_INFO(target, fmt_str,...)
Definition: log.h:152
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:158
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:149
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
int gettimeofday(struct timeval *tv, struct timezone *tz)
struct esp_dbg_stubs dbg_stubs
Definition: esp.h:81
Debug stubs descriptor.
Definition: esp.h:47
uint32_t min_stack_addr
Pre-compiled target buffer's addr for stack.
Definition: esp.h:58
uint32_t data_free
Address of free-like function to free buffer allocated with data_alloc.
Definition: esp.h:62
uint32_t tramp_addr
Address of pre-compiled target buffer for stub trampoline.
Definition: esp.h:51
uint32_t data_alloc
Address of malloc-like function to allocate buffer on target.
Definition: esp.h:60
uint32_t entries[ESP_DBG_STUB_ENTRY_MAX]
Table contents.
Definition: esp.h:72
struct esp_dbg_stubs_desc desc
Debug stubs decsriptor.
Definition: esp.h:76
uint32_t entries_count
Number of table entries.
Definition: esp.h:74
uint32_t base
Address.
Definition: esp.h:70
struct esp_semihost_ops * ops
Semihost calls handling operations.
const struct esp32_apptrace_hw * hw
struct esp_semihost_data semihost
Definition: esp_xtensa.h:20
struct xtensa xtensa
Definition: esp_xtensa.h:18
struct esp_xtensa_apptrace_info apptrace
Definition: esp_xtensa.h:21
struct esp_common esp
Definition: esp_xtensa.h:19
Definition: target.h:116
enum target_state state
Definition: target.h:157
Definition: psoc6.c:83
Represents a generic Xtensa core.
Definition: xtensa.h:241
struct xtensa_debug_module dbg_mod
Definition: xtensa.h:245
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
Definition: target.c:2290
int target_poll(struct target *target)
Definition: target.c:477
int target_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution)
Make the target (re)start executing using its saved execution context (possibly with some modificatio...
Definition: target.c:556
static bool target_was_examined(const struct target *target)
Definition: target.h:436
@ TARGET_DEBUG_RUNNING
Definition: target.h:58
@ TARGET_HALTED
Definition: target.h:56
int timeval_compare(const struct timeval *x, const struct timeval *y)
Definition: time_support.c:55
int timeval_add_time(struct timeval *result, long sec, long usec)
Definition: time_support.c:41
#define NULL
Definition: usb.h:16
int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint)
Definition: xtensa.c:2554
void xtensa_target_deinit(struct target *target)
Definition: xtensa.c:3485
int xtensa_poll(struct target *target)
Definition: xtensa.c:2304
int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint)
Definition: xtensa.c:2598
int xtensa_target_init(struct command_context *cmd_ctx, struct target *target)
Definition: xtensa.c:3419
int xtensa_init_arch_info(struct target *target, struct xtensa *xtensa, const struct xtensa_debug_module_config *dm_cfg)
Definition: xtensa.c:3375
static struct xtensa * target_to_xtensa(struct target *target)
Definition: xtensa.h:290
static bool xtensa_data_addr_valid(struct target *target, uint32_t addr)
Definition: xtensa.h:314
static int xtensa_queue_dbg_reg_read(struct xtensa *xtensa, enum xtensa_dm_reg reg, uint8_t *data)
Definition: xtensa.h:327
static int xtensa_dm_queue_execute(struct xtensa_debug_module *dm)
@ XDMREG_DEBUGPC
static xtensa_pwrstat_t xtensa_dm_power_status_get(struct xtensa_debug_module *dm)
#define PWRSTAT_COREWASRESET(x)