1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * ESP32-S2 target for OpenOCD *
5 * Copyright (C) 2019 Espressif Systems Ltd. *
6 ***************************************************************************/
12 #include <helper/time_support.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"
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
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
88 #define ESP32_S2_TRACEMEM_BLOCK_SZ 0x4000
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
;
97 static int esp32s2_soc_reset(struct target
*target
);
98 static int esp32s2_disable_wdts(struct target
*target
);
100 static int esp32s2_assert_reset(struct target
*target
)
105 static int esp32s2_deassert_reset(struct target
*target
)
107 struct xtensa
*xtensa
= target_to_xtensa(target
);
109 LOG_TARGET_DEBUG(target
, "begin");
111 int res
= xtensa_deassert_reset(target
);
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
);
125 int esp32s2_soft_reset_halt(struct target
*target
)
127 LOG_TARGET_DEBUG(target
, "begin");
129 /* Reset the SoC first */
130 int res
= esp32s2_soc_reset(target
);
133 return xtensa_soft_reset_halt(target
);
136 static int esp32s2_set_peri_reg_mask(struct target
*target
,
142 int res
= target_read_u32(target
, addr
, ®_val
);
145 reg_val
= (reg_val
& (~mask
)) | val
;
146 res
= target_write_u32(target
, addr
, reg_val
);
153 static int esp32s2_stall_set(struct target
*target
, bool stall
)
155 LOG_TARGET_DEBUG(target
, "begin");
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
);
165 res
= esp32s2_set_peri_reg_mask(target
,
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
);
176 static inline int esp32s2_stall(struct target
*target
)
178 return esp32s2_stall_set(target
, true);
181 static inline int esp32s2_unstall(struct target
*target
)
183 return esp32s2_stall_set(target
, false);
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
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
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
197 8. Disables WDTs and trace memory mapping
199 static int esp32s2_soc_reset(struct target
*target
)
202 struct xtensa
*xtensa
= target_to_xtensa(target
);
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");
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
) {
217 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
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
) {
230 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
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");
245 assert(target
->state
== TARGET_HALTED
);
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
);
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
);
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
);
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
);
269 res
= esp32s2_stall(target
);
273 res
= xtensa_smpbreak_write(xtensa
, OCDDCR_RUNSTALLINEN
);
274 if (res
!= ERROR_OK
) {
275 LOG_ERROR("Failed to set smpbreak (%d)!", res
);
279 xtensa
->suppress_dsr_errors
= true;
280 res
= esp32s2_set_peri_reg_mask(target
,
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
);
289 /* Wait for SoC to reset */
291 int64_t timeout
= timeval_ms() + 100;
292 while (target
->state
!= TARGET_RESET
&& target
->state
!= TARGET_RUNNING
) {
295 if (timeval_ms() >= timeout
) {
296 LOG_TARGET_ERROR(target
, "Timed out waiting for CPU to be reset, target state=%d",
298 return ERROR_TARGET_TIMEOUT
;
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");
309 res
= esp32s2_unstall(target
);
313 res
= esp32s2_disable_wdts(target
);
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
);
325 static int esp32s2_disable_wdts(struct target
*target
)
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
381 static int esp32s2_arch_state(struct target
*target
)
386 static int esp32s2_on_halt(struct target
*target
)
388 return esp32s2_disable_wdts(target
);
391 static int esp32s2_step(struct target
*target
, int current
, target_addr_t address
, int handle_breakpoints
)
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
);
401 static int esp32s2_poll(struct target
*target
)
403 enum target_state old_state
= target
->state
;
404 int ret
= esp_xtensa_poll(target
);
406 if (old_state
!= TARGET_HALTED
&& target
->state
== TARGET_HALTED
) {
407 /* Call any event callbacks that are applicable */
408 if (old_state
== TARGET_DEBUG_RUNNING
) {
409 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
411 if (esp_xtensa_semihosting(target
, &ret
) == SEMIHOSTING_HANDLED
) {
412 struct esp_xtensa_common
*esp_xtensa
= target_to_esp_xtensa(target
);
413 if (ret
== ERROR_OK
&& esp_xtensa
->semihost
.need_resume
) {
414 esp_xtensa
->semihost
.need_resume
= false;
415 /* Resume xtensa_resume will handle BREAK instruction. */
416 ret
= target_resume(target
, 1, 0, 1, 0);
417 if (ret
!= ERROR_OK
) {
418 LOG_ERROR("Failed to resume target");
424 esp32s2_on_halt(target
);
425 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
432 static int esp32s2_virt2phys(struct target
*target
,
433 target_addr_t
virtual, target_addr_t
*physical
)
439 static int esp32s2_target_init(struct command_context
*cmd_ctx
, struct target
*target
)
441 int ret
= esp_xtensa_target_init(cmd_ctx
, target
);
445 return esp_xtensa_semihosting_init(target
);
448 static const struct xtensa_debug_ops esp32s2_dbg_ops
= {
449 .queue_enable
= xtensa_dm_queue_enable
,
450 .queue_reg_read
= xtensa_dm_queue_reg_read
,
451 .queue_reg_write
= xtensa_dm_queue_reg_write
454 static const struct xtensa_power_ops esp32s2_pwr_ops
= {
455 .queue_reg_read
= xtensa_dm_queue_pwr_reg_read
,
456 .queue_reg_write
= xtensa_dm_queue_pwr_reg_write
459 static const struct esp_semihost_ops esp32s2_semihost_ops
= {
460 .prepare
= esp32s2_disable_wdts
463 static int esp32s2_target_create(struct target
*target
, Jim_Interp
*interp
)
465 struct xtensa_debug_module_config esp32s2_dm_cfg
= {
466 .dbg_ops
= &esp32s2_dbg_ops
,
467 .pwr_ops
= &esp32s2_pwr_ops
,
469 .queue_tdi_idle
= NULL
,
470 .queue_tdi_idle_arg
= NULL
473 /* creates xtensa object */
474 struct esp32s2_common
*esp32
= calloc(1, sizeof(*esp32
));
476 LOG_ERROR("Failed to alloc memory for arch info!");
480 int ret
= esp_xtensa_init_arch_info(target
, &esp32
->esp_xtensa
, &esp32s2_dm_cfg
, &esp32s2_semihost_ops
);
481 if (ret
!= ERROR_OK
) {
482 LOG_ERROR("Failed to init arch info!");
487 /* Assume running target. If different, the first poll will fix this */
488 target
->state
= TARGET_RUNNING
;
489 target
->debug_reason
= DBG_REASON_NOTHALTED
;
493 static const struct command_registration esp32s2_command_handlers
[] = {
495 .chain
= xtensa_command_handlers
,
500 .help
= "ARM Command Group",
502 .chain
= semihosting_common_handlers
504 COMMAND_REGISTRATION_DONE
507 /* Holds methods for Xtensa targets. */
508 struct target_type esp32s2_target
= {
511 .poll
= esp32s2_poll
,
512 .arch_state
= esp32s2_arch_state
,
515 .resume
= xtensa_resume
,
516 .step
= esp32s2_step
,
518 .assert_reset
= esp32s2_assert_reset
,
519 .deassert_reset
= esp32s2_deassert_reset
,
520 .soft_reset_halt
= esp32s2_soft_reset_halt
,
522 .virt2phys
= esp32s2_virt2phys
,
523 .mmu
= xtensa_mmu_is_enabled
,
524 .read_memory
= xtensa_read_memory
,
525 .write_memory
= xtensa_write_memory
,
527 .read_buffer
= xtensa_read_buffer
,
528 .write_buffer
= xtensa_write_buffer
,
530 .checksum_memory
= xtensa_checksum_memory
,
532 .get_gdb_arch
= xtensa_get_gdb_arch
,
533 .get_gdb_reg_list
= xtensa_get_gdb_reg_list
,
535 .add_breakpoint
= esp_xtensa_breakpoint_add
,
536 .remove_breakpoint
= esp_xtensa_breakpoint_remove
,
538 .add_watchpoint
= xtensa_watchpoint_add
,
539 .remove_watchpoint
= xtensa_watchpoint_remove
,
541 .target_create
= esp32s2_target_create
,
542 .init_target
= esp32s2_target_init
,
543 .examine
= xtensa_examine
,
544 .deinit_target
= esp_xtensa_target_deinit
,
546 .commands
= esp32s2_command_handlers
,
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)