a11d05f0f22566866fe6d91adbfaac72c4764be1
[openocd.git] / src / target / espressif / esp32s2.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * ESP32-S2 target 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 <helper/time_support.h>
13 #include "assert.h"
14 #include <target/target.h>
15 #include <target/target_type.h>
16 #include <target/semihosting_common.h>
17 #include "esp_xtensa.h"
18 #include "esp_xtensa_semihosting.h"
19
20 /* Overall memory map
21 * TODO: read memory configuration from target registers */
22 #define ESP32_S2_IROM_MASK_LOW 0x40000000
23 #define ESP32_S2_IROM_MASK_HIGH 0x40020000
24 #define ESP32_S2_IRAM_LOW 0x40020000
25 #define ESP32_S2_IRAM_HIGH 0x40070000
26 #define ESP32_S2_DRAM_LOW 0x3ffb0000
27 #define ESP32_S2_DRAM_HIGH 0x40000000
28 #define ESP32_S2_RTC_IRAM_LOW 0x40070000
29 #define ESP32_S2_RTC_IRAM_HIGH 0x40072000
30 #define ESP32_S2_RTC_DRAM_LOW 0x3ff9e000
31 #define ESP32_S2_RTC_DRAM_HIGH 0x3ffa0000
32 #define ESP32_S2_RTC_DATA_LOW 0x50000000
33 #define ESP32_S2_RTC_DATA_HIGH 0x50002000
34 #define ESP32_S2_EXTRAM_DATA_LOW 0x3f500000
35 #define ESP32_S2_EXTRAM_DATA_HIGH 0x3ff80000
36 #define ESP32_S2_DR_REG_LOW 0x3f400000
37 #define ESP32_S2_DR_REG_HIGH 0x3f4d3FFC
38 #define ESP32_S2_SYS_RAM_LOW 0x60000000UL
39 #define ESP32_S2_SYS_RAM_HIGH (ESP32_S2_SYS_RAM_LOW + 0x20000000UL)
40 /* ESP32-S2 DROM mapping is not contiguous. */
41 /* IDF declares this as 0x3F000000..0x3FF80000, but there are peripheral registers mapped to
42 * 0x3f400000..0x3f4d3FFC. */
43 #define ESP32_S2_DROM0_LOW ESP32_S2_DROM_LOW
44 #define ESP32_S2_DROM0_HIGH ESP32_S2_DR_REG_LOW
45 #define ESP32_S2_DROM1_LOW ESP32_S2_DR_REG_HIGH
46 #define ESP32_S2_DROM1_HIGH ESP32_S2_DROM_HIGH
47
48 /* ESP32 WDT */
49 #define ESP32_S2_WDT_WKEY_VALUE 0x50d83aa1
50 #define ESP32_S2_TIMG0_BASE 0x3f41F000
51 #define ESP32_S2_TIMG1_BASE 0x3f420000
52 #define ESP32_S2_TIMGWDT_CFG0_OFF 0x48
53 #define ESP32_S2_TIMGWDT_PROTECT_OFF 0x64
54 #define ESP32_S2_TIMG0WDT_CFG0 (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_CFG0_OFF)
55 #define ESP32_S2_TIMG1WDT_CFG0 (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_CFG0_OFF)
56 #define ESP32_S2_TIMG0WDT_PROTECT (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF)
57 #define ESP32_S2_TIMG1WDT_PROTECT (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF)
58 #define ESP32_S2_RTCCNTL_BASE 0x3f408000
59 #define ESP32_S2_RTCWDT_CFG_OFF 0x94
60 #define ESP32_S2_RTCWDT_PROTECT_OFF 0xAC
61 #define ESP32_S2_SWD_CONF_OFF 0xB0
62 #define ESP32_S2_SWD_WPROTECT_OFF 0xB4
63 #define ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF 0x8C
64 #define ESP32_S2_RTC_CNTL_DIG_PWC_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF)
65 #define ESP32_S2_RTCWDT_CFG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_CFG_OFF)
66 #define ESP32_S2_RTCWDT_PROTECT (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_PROTECT_OFF)
67 #define ESP32_S2_SWD_CONF_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_CONF_OFF)
68 #define ESP32_S2_SWD_WPROTECT_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_WPROTECT_OFF)
69 #define ESP32_S2_SWD_AUTO_FEED_EN_M BIT(31)
70 #define ESP32_S2_SWD_WKEY_VALUE 0x8F1D312AU
71 #define ESP32_S2_OPTIONS0 (ESP32_S2_RTCCNTL_BASE + 0x0000)
72 #define ESP32_S2_SW_SYS_RST_M 0x80000000
73 #define ESP32_S2_SW_SYS_RST_V 0x1
74 #define ESP32_S2_SW_SYS_RST_S 31
75 #define ESP32_S2_SW_STALL_PROCPU_C0_M ((ESP32_S2_SW_STALL_PROCPU_C0_V) << (ESP32_S2_SW_STALL_PROCPU_C0_S))
76 #define ESP32_S2_SW_STALL_PROCPU_C0_V 0x3
77 #define ESP32_S2_SW_STALL_PROCPU_C0_S 2
78 #define ESP32_S2_SW_CPU_STALL (ESP32_S2_RTCCNTL_BASE + 0x00B8)
79 #define ESP32_S2_SW_STALL_PROCPU_C1_M ((ESP32_S2_SW_STALL_PROCPU_C1_V) << (ESP32_S2_SW_STALL_PROCPU_C1_S))
80 #define ESP32_S2_SW_STALL_PROCPU_C1_V 0x3FU
81 #define ESP32_S2_SW_STALL_PROCPU_C1_S 26
82 #define ESP32_S2_CLK_CONF (ESP32_S2_RTCCNTL_BASE + 0x0074)
83 #define ESP32_S2_CLK_CONF_DEF 0x1583218
84 #define ESP32_S2_STORE4 (ESP32_S2_RTCCNTL_BASE + 0x00BC)
85 #define ESP32_S2_STORE5 (ESP32_S2_RTCCNTL_BASE + 0x00C0)
86 #define ESP32_S2_DPORT_PMS_OCCUPY_3 0x3F4C10E0
87
88 #define ESP32_S2_TRACEMEM_BLOCK_SZ 0x4000
89
90 #define ESP32_S2_DR_REG_UART_BASE 0x3f400000
91 #define ESP32_S2_REG_UART_BASE(i) (ESP32_S2_DR_REG_UART_BASE + (i) * 0x10000)
92 #define ESP32_S2_UART_DATE_REG(i) (ESP32_S2_REG_UART_BASE(i) + 0x74)
93 struct esp32s2_common {
94 struct esp_xtensa_common esp_xtensa;
95 };
96
97 static int esp32s2_soc_reset(struct target *target);
98 static int esp32s2_disable_wdts(struct target *target);
99
100 static int esp32s2_assert_reset(struct target *target)
101 {
102 return ERROR_OK;
103 }
104
105 static int esp32s2_deassert_reset(struct target *target)
106 {
107 struct xtensa *xtensa = target_to_xtensa(target);
108
109 LOG_TARGET_DEBUG(target, "begin");
110
111 int res = xtensa_deassert_reset(target);
112 if (res != ERROR_OK)
113 return res;
114
115 /* restore configured value
116 esp32s2_soc_reset() modified it, but can not restore just after SW reset for some reason (???) */
117 res = xtensa_smpbreak_write(xtensa, xtensa->smp_break);
118 if (res != ERROR_OK) {
119 LOG_ERROR("Failed to restore smpbreak (%d)!", res);
120 return res;
121 }
122 return ERROR_OK;
123 }
124
125 static int esp32s2_soft_reset_halt(struct target *target)
126 {
127 LOG_TARGET_DEBUG(target, "begin");
128
129 /* Reset the SoC first */
130 int res = esp32s2_soc_reset(target);
131 if (res != ERROR_OK)
132 return res;
133 return xtensa_soft_reset_halt(target);
134 }
135
136 static int esp32s2_set_peri_reg_mask(struct target *target,
137 target_addr_t addr,
138 uint32_t mask,
139 uint32_t val)
140 {
141 uint32_t reg_val;
142 int res = target_read_u32(target, addr, &reg_val);
143 if (res != ERROR_OK)
144 return res;
145 reg_val = (reg_val & (~mask)) | val;
146 res = target_write_u32(target, addr, reg_val);
147 if (res != ERROR_OK)
148 return res;
149
150 return ERROR_OK;
151 }
152
153 static int esp32s2_stall_set(struct target *target, bool stall)
154 {
155 LOG_TARGET_DEBUG(target, "begin");
156
157 int res = esp32s2_set_peri_reg_mask(target,
158 ESP32_S2_SW_CPU_STALL,
159 ESP32_S2_SW_STALL_PROCPU_C1_M,
160 stall ? 0x21U << ESP32_S2_SW_STALL_PROCPU_C1_S : 0);
161 if (res != ERROR_OK) {
162 LOG_ERROR("Failed to write ESP32_S2_SW_CPU_STALL (%d)!", res);
163 return res;
164 }
165 res = esp32s2_set_peri_reg_mask(target,
166 ESP32_S2_OPTIONS0,
167 ESP32_S2_SW_STALL_PROCPU_C0_M,
168 stall ? 0x2 << ESP32_S2_SW_STALL_PROCPU_C0_S : 0);
169 if (res != ERROR_OK) {
170 LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res);
171 return res;
172 }
173 return ERROR_OK;
174 }
175
176 static inline int esp32s2_stall(struct target *target)
177 {
178 return esp32s2_stall_set(target, true);
179 }
180
181 static inline int esp32s2_unstall(struct target *target)
182 {
183 return esp32s2_stall_set(target, false);
184 }
185
186 /* Reset ESP32-S2's peripherals.
187 Postconditions: all peripherals except RTC_CNTL are reset, CPU's PC is undefined, PRO CPU is halted, APP CPU is in reset
188 How this works:
189 0. make sure target is halted; if not, try to halt it; if that fails, try to reset it (via OCD) and then halt
190 1. Resets clock related registers
191 2. Stalls CPU
192 3. trigger SoC reset using RTC_CNTL_SW_SYS_RST bit
193 4. CPU is reset and stalled at the first reset vector instruction
194 5. wait for the OCD to be reset
195 6. halt the target
196 7. Unstalls CPU
197 8. Disables WDTs and trace memory mapping
198 */
199 static int esp32s2_soc_reset(struct target *target)
200 {
201 int res;
202 struct xtensa *xtensa = target_to_xtensa(target);
203
204 LOG_DEBUG("start");
205
206 /* In order to write to peripheral registers, target must be halted first */
207 if (target->state != TARGET_HALTED) {
208 LOG_TARGET_DEBUG(target, "Target not halted before SoC reset, trying to halt it first");
209 xtensa_halt(target);
210 res = target_wait_state(target, TARGET_HALTED, 1000);
211 if (res != ERROR_OK) {
212 LOG_TARGET_DEBUG(target, "Couldn't halt target before SoC reset, trying to do reset-halt");
213 res = xtensa_assert_reset(target);
214 if (res != ERROR_OK) {
215 LOG_TARGET_ERROR(
216 target,
217 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
218 res);
219 return res;
220 }
221 alive_sleep(10);
222 xtensa_poll(target);
223 int reset_halt_save = target->reset_halt;
224 target->reset_halt = 1;
225 res = xtensa_deassert_reset(target);
226 target->reset_halt = reset_halt_save;
227 if (res != ERROR_OK) {
228 LOG_TARGET_ERROR(
229 target,
230 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
231 res);
232 return res;
233 }
234 alive_sleep(10);
235 xtensa_poll(target);
236 xtensa_halt(target);
237 res = target_wait_state(target, TARGET_HALTED, 1000);
238 if (res != ERROR_OK) {
239 LOG_TARGET_ERROR(target, "Couldn't halt target before SoC reset");
240 return res;
241 }
242 }
243 }
244
245 assert(target->state == TARGET_HALTED);
246
247 /* Set some clock-related RTC registers to the default values */
248 res = target_write_u32(target, ESP32_S2_STORE4, 0);
249 if (res != ERROR_OK) {
250 LOG_ERROR("Failed to write ESP32_S2_STORE4 (%d)!", res);
251 return res;
252 }
253 res = target_write_u32(target, ESP32_S2_STORE5, 0);
254 if (res != ERROR_OK) {
255 LOG_ERROR("Failed to write ESP32_S2_STORE5 (%d)!", res);
256 return res;
257 }
258 res = target_write_u32(target, ESP32_S2_RTC_CNTL_DIG_PWC_REG, 0);
259 if (res != ERROR_OK) {
260 LOG_ERROR("Failed to write ESP32_S2_RTC_CNTL_DIG_PWC_REG (%d)!", res);
261 return res;
262 }
263 res = target_write_u32(target, ESP32_S2_CLK_CONF, ESP32_S2_CLK_CONF_DEF);
264 if (res != ERROR_OK) {
265 LOG_ERROR("Failed to write ESP32_S2_CLK_CONF (%d)!", res);
266 return res;
267 }
268 /* Stall CPU */
269 res = esp32s2_stall(target);
270 if (res != ERROR_OK)
271 return res;
272 /* enable stall */
273 res = xtensa_smpbreak_write(xtensa, OCDDCR_RUNSTALLINEN);
274 if (res != ERROR_OK) {
275 LOG_ERROR("Failed to set smpbreak (%d)!", res);
276 return res;
277 }
278 /* Reset CPU */
279 xtensa->suppress_dsr_errors = true;
280 res = esp32s2_set_peri_reg_mask(target,
281 ESP32_S2_OPTIONS0,
282 ESP32_S2_SW_SYS_RST_M,
283 BIT(ESP32_S2_SW_SYS_RST_S));
284 xtensa->suppress_dsr_errors = false;
285 if (res != ERROR_OK) {
286 LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res);
287 return res;
288 }
289 /* Wait for SoC to reset */
290 alive_sleep(100);
291 int64_t timeout = timeval_ms() + 100;
292 while (target->state != TARGET_RESET && target->state != TARGET_RUNNING) {
293 alive_sleep(10);
294 xtensa_poll(target);
295 if (timeval_ms() >= timeout) {
296 LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state=%d",
297 target->state);
298 return ERROR_TARGET_TIMEOUT;
299 }
300 }
301
302 xtensa_halt(target);
303 res = target_wait_state(target, TARGET_HALTED, 1000);
304 if (res != ERROR_OK) {
305 LOG_TARGET_ERROR(target, "Couldn't halt target before SoC reset");
306 return res;
307 }
308 /* Unstall CPU */
309 res = esp32s2_unstall(target);
310 if (res != ERROR_OK)
311 return res;
312 /* Disable WDTs */
313 res = esp32s2_disable_wdts(target);
314 if (res != ERROR_OK)
315 return res;
316 /* Disable trace memory mapping */
317 res = target_write_u32(target, ESP32_S2_DPORT_PMS_OCCUPY_3, 0);
318 if (res != ERROR_OK) {
319 LOG_ERROR("Failed to write ESP32_S2_DPORT_PMS_OCCUPY_3 (%d)!", res);
320 return res;
321 }
322 return ERROR_OK;
323 }
324
325 static int esp32s2_disable_wdts(struct target *target)
326 {
327 /* TIMG1 WDT */
328 int res = target_write_u32(target, ESP32_S2_TIMG0WDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE);
329 if (res != ERROR_OK) {
330 LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_PROTECT (%d)!", res);
331 return res;
332 }
333 res = target_write_u32(target, ESP32_S2_TIMG0WDT_CFG0, 0);
334 if (res != ERROR_OK) {
335 LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_CFG0 (%d)!", res);
336 return res;
337 }
338 /* TIMG2 WDT */
339 res = target_write_u32(target, ESP32_S2_TIMG1WDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE);
340 if (res != ERROR_OK) {
341 LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_PROTECT (%d)!", res);
342 return res;
343 }
344 res = target_write_u32(target, ESP32_S2_TIMG1WDT_CFG0, 0);
345 if (res != ERROR_OK) {
346 LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_CFG0 (%d)!", res);
347 return res;
348 }
349 /* RTC WDT */
350 res = target_write_u32(target, ESP32_S2_RTCWDT_PROTECT, ESP32_S2_WDT_WKEY_VALUE);
351 if (res != ERROR_OK) {
352 LOG_ERROR("Failed to write ESP32_S2_RTCWDT_PROTECT (%d)!", res);
353 return res;
354 }
355 res = target_write_u32(target, ESP32_S2_RTCWDT_CFG, 0);
356 if (res != ERROR_OK) {
357 LOG_ERROR("Failed to write ESP32_S2_RTCWDT_CFG (%d)!", res);
358 return res;
359 }
360 /* Enable SWD auto-feed */
361 res = target_write_u32(target, ESP32_S2_SWD_WPROTECT_REG, ESP32_S2_SWD_WKEY_VALUE);
362 if (res != ERROR_OK) {
363 LOG_ERROR("Failed to write ESP32_S2_SWD_WPROTECT_REG (%d)!", res);
364 return res;
365 }
366 uint32_t swd_conf_reg = 0;
367 res = target_read_u32(target, ESP32_S2_SWD_CONF_REG, &swd_conf_reg);
368 if (res != ERROR_OK) {
369 LOG_ERROR("Failed to read ESP32_S2_SWD_CONF_REG (%d)!", res);
370 return res;
371 }
372 swd_conf_reg |= ESP32_S2_SWD_AUTO_FEED_EN_M;
373 res = target_write_u32(target, ESP32_S2_SWD_CONF_REG, swd_conf_reg);
374 if (res != ERROR_OK) {
375 LOG_ERROR("Failed to write ESP32_S2_SWD_CONF_REG (%d)!", res);
376 return res;
377 }
378 return ERROR_OK;
379 }
380
381 static int esp32s2_arch_state(struct target *target)
382 {
383 return ERROR_OK;
384 }
385
386 static int esp32s2_on_halt(struct target *target)
387 {
388 return esp32s2_disable_wdts(target);
389 }
390
391 static int esp32s2_step(struct target *target, int current, target_addr_t address, int handle_breakpoints)
392 {
393 int ret = xtensa_step(target, current, address, handle_breakpoints);
394 if (ret == ERROR_OK) {
395 esp32s2_on_halt(target);
396 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
397 }
398 return ret;
399 }
400
401 static int esp32s2_poll(struct target *target)
402 {
403 enum target_state old_state = target->state;
404 int ret = esp_xtensa_poll(target);
405 if (ret != ERROR_OK)
406 return ret;
407
408 if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
409 /* Call any event callbacks that are applicable */
410 if (old_state == TARGET_DEBUG_RUNNING) {
411 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
412 } else {
413 if (esp_xtensa_semihosting(target, &ret) == SEMIHOSTING_HANDLED) {
414 struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
415 if (ret == ERROR_OK && esp_xtensa->semihost.need_resume) {
416 esp_xtensa->semihost.need_resume = false;
417 /* Resume xtensa_resume will handle BREAK instruction. */
418 ret = target_resume(target, 1, 0, 1, 0);
419 if (ret != ERROR_OK) {
420 LOG_ERROR("Failed to resume target");
421 return ret;
422 }
423 }
424 return ret;
425 }
426 esp32s2_on_halt(target);
427 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
428 }
429 }
430
431 return ret;
432 }
433
434 static int esp32s2_virt2phys(struct target *target,
435 target_addr_t virtual, target_addr_t *physical)
436 {
437 *physical = virtual;
438 return ERROR_OK;
439 }
440
441 static int esp32s2_target_init(struct command_context *cmd_ctx, struct target *target)
442 {
443 int ret = esp_xtensa_target_init(cmd_ctx, target);
444 if (ret != ERROR_OK)
445 return ret;
446
447 return esp_xtensa_semihosting_init(target);
448 }
449
450 static const struct xtensa_debug_ops esp32s2_dbg_ops = {
451 .queue_enable = xtensa_dm_queue_enable,
452 .queue_reg_read = xtensa_dm_queue_reg_read,
453 .queue_reg_write = xtensa_dm_queue_reg_write
454 };
455
456 static const struct xtensa_power_ops esp32s2_pwr_ops = {
457 .queue_reg_read = xtensa_dm_queue_pwr_reg_read,
458 .queue_reg_write = xtensa_dm_queue_pwr_reg_write
459 };
460
461 static const struct esp_semihost_ops esp32s2_semihost_ops = {
462 .prepare = esp32s2_disable_wdts
463 };
464
465 static int esp32s2_target_create(struct target *target, Jim_Interp *interp)
466 {
467 struct xtensa_debug_module_config esp32s2_dm_cfg = {
468 .dbg_ops = &esp32s2_dbg_ops,
469 .pwr_ops = &esp32s2_pwr_ops,
470 .tap = target->tap,
471 .queue_tdi_idle = NULL,
472 .queue_tdi_idle_arg = NULL
473 };
474
475 /* creates xtensa object */
476 struct esp32s2_common *esp32 = calloc(1, sizeof(*esp32));
477 if (!esp32) {
478 LOG_ERROR("Failed to alloc memory for arch info!");
479 return ERROR_FAIL;
480 }
481
482 int ret = esp_xtensa_init_arch_info(target, &esp32->esp_xtensa, &esp32s2_dm_cfg, &esp32s2_semihost_ops);
483 if (ret != ERROR_OK) {
484 LOG_ERROR("Failed to init arch info!");
485 free(esp32);
486 return ret;
487 }
488
489 /* Assume running target. If different, the first poll will fix this */
490 target->state = TARGET_RUNNING;
491 target->debug_reason = DBG_REASON_NOTHALTED;
492 return ERROR_OK;
493 }
494
495 static const struct command_registration esp32s2_command_handlers[] = {
496 {
497 .chain = xtensa_command_handlers,
498 },
499 {
500 .name = "esp",
501 .usage = "",
502 .chain = esp32_apptrace_command_handlers,
503 },
504 {
505 .name = "arm",
506 .mode = COMMAND_ANY,
507 .help = "ARM Command Group",
508 .usage = "",
509 .chain = semihosting_common_handlers
510 },
511 COMMAND_REGISTRATION_DONE
512 };
513
514 /* Holds methods for Xtensa targets. */
515 struct target_type esp32s2_target = {
516 .name = "esp32s2",
517
518 .poll = esp32s2_poll,
519 .arch_state = esp32s2_arch_state,
520
521 .halt = xtensa_halt,
522 .resume = xtensa_resume,
523 .step = esp32s2_step,
524
525 .assert_reset = esp32s2_assert_reset,
526 .deassert_reset = esp32s2_deassert_reset,
527 .soft_reset_halt = esp32s2_soft_reset_halt,
528
529 .virt2phys = esp32s2_virt2phys,
530 .mmu = xtensa_mmu_is_enabled,
531 .read_memory = xtensa_read_memory,
532 .write_memory = xtensa_write_memory,
533
534 .read_buffer = xtensa_read_buffer,
535 .write_buffer = xtensa_write_buffer,
536
537 .checksum_memory = xtensa_checksum_memory,
538
539 .get_gdb_arch = xtensa_get_gdb_arch,
540 .get_gdb_reg_list = xtensa_get_gdb_reg_list,
541
542 .add_breakpoint = esp_xtensa_breakpoint_add,
543 .remove_breakpoint = esp_xtensa_breakpoint_remove,
544
545 .add_watchpoint = xtensa_watchpoint_add,
546 .remove_watchpoint = xtensa_watchpoint_remove,
547
548 .target_create = esp32s2_target_create,
549 .init_target = esp32s2_target_init,
550 .examine = xtensa_examine,
551 .deinit_target = esp_xtensa_target_deinit,
552
553 .commands = esp32s2_command_handlers,
554 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)