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"
20 #define ESP32_S2_RTC_DATA_LOW 0x50000000
21 #define ESP32_S2_RTC_DATA_HIGH 0x50002000
22 #define ESP32_S2_DR_REG_LOW 0x3f400000
23 #define ESP32_S2_DR_REG_HIGH 0x3f4d3FFC
24 #define ESP32_S2_SYS_RAM_LOW 0x60000000UL
25 #define ESP32_S2_SYS_RAM_HIGH (ESP32_S2_SYS_RAM_LOW + 0x20000000UL)
28 #define ESP32_S2_WDT_WKEY_VALUE 0x50d83aa1
29 #define ESP32_S2_TIMG0_BASE 0x3f41F000
30 #define ESP32_S2_TIMG1_BASE 0x3f420000
31 #define ESP32_S2_TIMGWDT_CFG0_OFF 0x48
32 #define ESP32_S2_TIMGWDT_PROTECT_OFF 0x64
33 #define ESP32_S2_TIMG0WDT_CFG0 (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_CFG0_OFF)
34 #define ESP32_S2_TIMG1WDT_CFG0 (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_CFG0_OFF)
35 #define ESP32_S2_TIMG0WDT_PROTECT (ESP32_S2_TIMG0_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF)
36 #define ESP32_S2_TIMG1WDT_PROTECT (ESP32_S2_TIMG1_BASE + ESP32_S2_TIMGWDT_PROTECT_OFF)
37 #define ESP32_S2_RTCCNTL_BASE 0x3f408000
38 #define ESP32_S2_RTCWDT_CFG_OFF 0x94
39 #define ESP32_S2_RTCWDT_PROTECT_OFF 0xAC
40 #define ESP32_S2_SWD_CONF_OFF 0xB0
41 #define ESP32_S2_SWD_WPROTECT_OFF 0xB4
42 #define ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF 0x8C
43 #define ESP32_S2_RTC_CNTL_DIG_PWC_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTC_CNTL_DIG_PWC_REG_OFF)
44 #define ESP32_S2_RTCWDT_CFG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_CFG_OFF)
45 #define ESP32_S2_RTCWDT_PROTECT (ESP32_S2_RTCCNTL_BASE + ESP32_S2_RTCWDT_PROTECT_OFF)
46 #define ESP32_S2_SWD_CONF_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_CONF_OFF)
47 #define ESP32_S2_SWD_WPROTECT_REG (ESP32_S2_RTCCNTL_BASE + ESP32_S2_SWD_WPROTECT_OFF)
48 #define ESP32_S2_SWD_AUTO_FEED_EN_M BIT(31)
49 #define ESP32_S2_SWD_WKEY_VALUE 0x8F1D312AU
50 #define ESP32_S2_OPTIONS0 (ESP32_S2_RTCCNTL_BASE + 0x0000)
51 #define ESP32_S2_SW_SYS_RST_M 0x80000000
52 #define ESP32_S2_SW_SYS_RST_V 0x1
53 #define ESP32_S2_SW_SYS_RST_S 31
54 #define ESP32_S2_SW_STALL_PROCPU_C0_M ((ESP32_S2_SW_STALL_PROCPU_C0_V) << (ESP32_S2_SW_STALL_PROCPU_C0_S))
55 #define ESP32_S2_SW_STALL_PROCPU_C0_V 0x3
56 #define ESP32_S2_SW_STALL_PROCPU_C0_S 2
57 #define ESP32_S2_SW_CPU_STALL (ESP32_S2_RTCCNTL_BASE + 0x00B8)
58 #define ESP32_S2_SW_STALL_PROCPU_C1_M ((ESP32_S2_SW_STALL_PROCPU_C1_V) << (ESP32_S2_SW_STALL_PROCPU_C1_S))
59 #define ESP32_S2_SW_STALL_PROCPU_C1_V 0x3FU
60 #define ESP32_S2_SW_STALL_PROCPU_C1_S 26
61 #define ESP32_S2_CLK_CONF (ESP32_S2_RTCCNTL_BASE + 0x0074)
62 #define ESP32_S2_CLK_CONF_DEF 0x1583218
63 #define ESP32_S2_STORE4 (ESP32_S2_RTCCNTL_BASE + 0x00BC)
64 #define ESP32_S2_STORE5 (ESP32_S2_RTCCNTL_BASE + 0x00C0)
65 #define ESP32_S2_DPORT_PMS_OCCUPY_3 0x3F4C10E0
67 #define ESP32_S2_TRACEMEM_BLOCK_SZ 0x4000
69 #define ESP32_S2_DR_REG_UART_BASE 0x3f400000
70 #define ESP32_S2_REG_UART_BASE(i) (ESP32_S2_DR_REG_UART_BASE + (i) * 0x10000)
71 #define ESP32_S2_UART_DATE_REG(i) (ESP32_S2_REG_UART_BASE(i) + 0x74)
72 struct esp32s2_common
{
73 struct esp_xtensa_common esp_xtensa
;
76 static int esp32s2_soc_reset(struct target
*target
);
77 static int esp32s2_disable_wdts(struct target
*target
);
79 static int esp32s2_assert_reset(struct target
*target
)
84 static int esp32s2_deassert_reset(struct target
*target
)
86 struct xtensa
*xtensa
= target_to_xtensa(target
);
88 LOG_TARGET_DEBUG(target
, "begin");
90 int res
= xtensa_deassert_reset(target
);
94 /* restore configured value
95 esp32s2_soc_reset() modified it, but can not restore just after SW reset for some reason (???) */
96 res
= xtensa_smpbreak_write(xtensa
, xtensa
->smp_break
);
97 if (res
!= ERROR_OK
) {
98 LOG_ERROR("Failed to restore smpbreak (%d)!", res
);
104 static int esp32s2_soft_reset_halt(struct target
*target
)
106 LOG_TARGET_DEBUG(target
, "begin");
108 /* Reset the SoC first */
109 int res
= esp32s2_soc_reset(target
);
112 return xtensa_soft_reset_halt(target
);
115 static int esp32s2_set_peri_reg_mask(struct target
*target
,
121 int res
= target_read_u32(target
, addr
, ®_val
);
124 reg_val
= (reg_val
& (~mask
)) | val
;
125 res
= target_write_u32(target
, addr
, reg_val
);
132 static int esp32s2_stall_set(struct target
*target
, bool stall
)
134 LOG_TARGET_DEBUG(target
, "begin");
136 int res
= esp32s2_set_peri_reg_mask(target
,
137 ESP32_S2_SW_CPU_STALL
,
138 ESP32_S2_SW_STALL_PROCPU_C1_M
,
139 stall
? 0x21U
<< ESP32_S2_SW_STALL_PROCPU_C1_S
: 0);
140 if (res
!= ERROR_OK
) {
141 LOG_ERROR("Failed to write ESP32_S2_SW_CPU_STALL (%d)!", res
);
144 res
= esp32s2_set_peri_reg_mask(target
,
146 ESP32_S2_SW_STALL_PROCPU_C0_M
,
147 stall
? 0x2 << ESP32_S2_SW_STALL_PROCPU_C0_S
: 0);
148 if (res
!= ERROR_OK
) {
149 LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res
);
155 static inline int esp32s2_stall(struct target
*target
)
157 return esp32s2_stall_set(target
, true);
160 static inline int esp32s2_unstall(struct target
*target
)
162 return esp32s2_stall_set(target
, false);
165 /* Reset ESP32-S2's peripherals.
166 Postconditions: all peripherals except RTC_CNTL are reset, CPU's PC is undefined, PRO CPU is halted, APP CPU is in reset
168 0. make sure target is halted; if not, try to halt it; if that fails, try to reset it (via OCD) and then halt
169 1. Resets clock related registers
171 3. trigger SoC reset using RTC_CNTL_SW_SYS_RST bit
172 4. CPU is reset and stalled at the first reset vector instruction
173 5. wait for the OCD to be reset
176 8. Disables WDTs and trace memory mapping
178 static int esp32s2_soc_reset(struct target
*target
)
181 struct xtensa
*xtensa
= target_to_xtensa(target
);
185 /* In order to write to peripheral registers, target must be halted first */
186 if (target
->state
!= TARGET_HALTED
) {
187 LOG_TARGET_DEBUG(target
, "Target not halted before SoC reset, trying to halt it first");
189 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
190 if (res
!= ERROR_OK
) {
191 LOG_TARGET_DEBUG(target
, "Couldn't halt target before SoC reset, trying to do reset-halt");
192 res
= xtensa_assert_reset(target
);
193 if (res
!= ERROR_OK
) {
196 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
202 int reset_halt_save
= target
->reset_halt
;
203 target
->reset_halt
= 1;
204 res
= xtensa_deassert_reset(target
);
205 target
->reset_halt
= reset_halt_save
;
206 if (res
!= ERROR_OK
) {
209 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
216 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
217 if (res
!= ERROR_OK
) {
218 LOG_TARGET_ERROR(target
, "Couldn't halt target before SoC reset");
224 assert(target
->state
== TARGET_HALTED
);
226 /* Set some clock-related RTC registers to the default values */
227 res
= target_write_u32(target
, ESP32_S2_STORE4
, 0);
228 if (res
!= ERROR_OK
) {
229 LOG_ERROR("Failed to write ESP32_S2_STORE4 (%d)!", res
);
232 res
= target_write_u32(target
, ESP32_S2_STORE5
, 0);
233 if (res
!= ERROR_OK
) {
234 LOG_ERROR("Failed to write ESP32_S2_STORE5 (%d)!", res
);
237 res
= target_write_u32(target
, ESP32_S2_RTC_CNTL_DIG_PWC_REG
, 0);
238 if (res
!= ERROR_OK
) {
239 LOG_ERROR("Failed to write ESP32_S2_RTC_CNTL_DIG_PWC_REG (%d)!", res
);
242 res
= target_write_u32(target
, ESP32_S2_CLK_CONF
, ESP32_S2_CLK_CONF_DEF
);
243 if (res
!= ERROR_OK
) {
244 LOG_ERROR("Failed to write ESP32_S2_CLK_CONF (%d)!", res
);
248 res
= esp32s2_stall(target
);
252 res
= xtensa_smpbreak_write(xtensa
, OCDDCR_RUNSTALLINEN
);
253 if (res
!= ERROR_OK
) {
254 LOG_ERROR("Failed to set smpbreak (%d)!", res
);
258 xtensa
->suppress_dsr_errors
= true;
259 res
= esp32s2_set_peri_reg_mask(target
,
261 ESP32_S2_SW_SYS_RST_M
,
262 BIT(ESP32_S2_SW_SYS_RST_S
));
263 xtensa
->suppress_dsr_errors
= false;
264 if (res
!= ERROR_OK
) {
265 LOG_ERROR("Failed to write ESP32_S2_OPTIONS0 (%d)!", res
);
268 /* Wait for SoC to reset */
270 int64_t timeout
= timeval_ms() + 100;
271 while (target
->state
!= TARGET_RESET
&& target
->state
!= TARGET_RUNNING
) {
274 if (timeval_ms() >= timeout
) {
275 LOG_TARGET_ERROR(target
, "Timed out waiting for CPU to be reset, target state=%d",
277 return ERROR_TARGET_TIMEOUT
;
282 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
283 if (res
!= ERROR_OK
) {
284 LOG_TARGET_ERROR(target
, "Couldn't halt target before SoC reset");
288 res
= esp32s2_unstall(target
);
292 res
= esp32s2_disable_wdts(target
);
295 /* Disable trace memory mapping */
296 res
= target_write_u32(target
, ESP32_S2_DPORT_PMS_OCCUPY_3
, 0);
297 if (res
!= ERROR_OK
) {
298 LOG_ERROR("Failed to write ESP32_S2_DPORT_PMS_OCCUPY_3 (%d)!", res
);
304 static int esp32s2_disable_wdts(struct target
*target
)
307 int res
= target_write_u32(target
, ESP32_S2_TIMG0WDT_PROTECT
, ESP32_S2_WDT_WKEY_VALUE
);
308 if (res
!= ERROR_OK
) {
309 LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_PROTECT (%d)!", res
);
312 res
= target_write_u32(target
, ESP32_S2_TIMG0WDT_CFG0
, 0);
313 if (res
!= ERROR_OK
) {
314 LOG_ERROR("Failed to write ESP32_S2_TIMG0WDT_CFG0 (%d)!", res
);
318 res
= target_write_u32(target
, ESP32_S2_TIMG1WDT_PROTECT
, ESP32_S2_WDT_WKEY_VALUE
);
319 if (res
!= ERROR_OK
) {
320 LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_PROTECT (%d)!", res
);
323 res
= target_write_u32(target
, ESP32_S2_TIMG1WDT_CFG0
, 0);
324 if (res
!= ERROR_OK
) {
325 LOG_ERROR("Failed to write ESP32_S2_TIMG1WDT_CFG0 (%d)!", res
);
329 res
= target_write_u32(target
, ESP32_S2_RTCWDT_PROTECT
, ESP32_S2_WDT_WKEY_VALUE
);
330 if (res
!= ERROR_OK
) {
331 LOG_ERROR("Failed to write ESP32_S2_RTCWDT_PROTECT (%d)!", res
);
334 res
= target_write_u32(target
, ESP32_S2_RTCWDT_CFG
, 0);
335 if (res
!= ERROR_OK
) {
336 LOG_ERROR("Failed to write ESP32_S2_RTCWDT_CFG (%d)!", res
);
339 /* Enable SWD auto-feed */
340 res
= target_write_u32(target
, ESP32_S2_SWD_WPROTECT_REG
, ESP32_S2_SWD_WKEY_VALUE
);
341 if (res
!= ERROR_OK
) {
342 LOG_ERROR("Failed to write ESP32_S2_SWD_WPROTECT_REG (%d)!", res
);
345 uint32_t swd_conf_reg
= 0;
346 res
= target_read_u32(target
, ESP32_S2_SWD_CONF_REG
, &swd_conf_reg
);
347 if (res
!= ERROR_OK
) {
348 LOG_ERROR("Failed to read ESP32_S2_SWD_CONF_REG (%d)!", res
);
351 swd_conf_reg
|= ESP32_S2_SWD_AUTO_FEED_EN_M
;
352 res
= target_write_u32(target
, ESP32_S2_SWD_CONF_REG
, swd_conf_reg
);
353 if (res
!= ERROR_OK
) {
354 LOG_ERROR("Failed to write ESP32_S2_SWD_CONF_REG (%d)!", res
);
360 static int esp32s2_arch_state(struct target
*target
)
365 static int esp32s2_on_halt(struct target
*target
)
367 int ret
= esp32s2_disable_wdts(target
);
369 ret
= esp_xtensa_on_halt(target
);
373 static int esp32s2_step(struct target
*target
, int current
, target_addr_t address
, int handle_breakpoints
)
375 int ret
= xtensa_step(target
, current
, address
, handle_breakpoints
);
376 if (ret
== ERROR_OK
) {
377 esp32s2_on_halt(target
);
378 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
383 static int esp32s2_poll(struct target
*target
)
385 enum target_state old_state
= target
->state
;
386 int ret
= esp_xtensa_poll(target
);
390 if (old_state
!= TARGET_HALTED
&& target
->state
== TARGET_HALTED
) {
391 /* Call any event callbacks that are applicable */
392 if (old_state
== TARGET_DEBUG_RUNNING
) {
393 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
395 if (esp_xtensa_semihosting(target
, &ret
) == SEMIHOSTING_HANDLED
) {
396 struct esp_xtensa_common
*esp_xtensa
= target_to_esp_xtensa(target
);
397 if (ret
== ERROR_OK
&& esp_xtensa
->semihost
.need_resume
) {
398 esp_xtensa
->semihost
.need_resume
= false;
399 /* Resume xtensa_resume will handle BREAK instruction. */
400 ret
= target_resume(target
, 1, 0, 1, 0);
401 if (ret
!= ERROR_OK
) {
402 LOG_ERROR("Failed to resume target");
408 esp32s2_on_halt(target
);
409 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
416 static int esp32s2_virt2phys(struct target
*target
,
417 target_addr_t
virtual, target_addr_t
*physical
)
423 static int esp32s2_target_init(struct command_context
*cmd_ctx
, struct target
*target
)
425 int ret
= esp_xtensa_target_init(cmd_ctx
, target
);
429 return esp_xtensa_semihosting_init(target
);
432 static const struct xtensa_debug_ops esp32s2_dbg_ops
= {
433 .queue_enable
= xtensa_dm_queue_enable
,
434 .queue_reg_read
= xtensa_dm_queue_reg_read
,
435 .queue_reg_write
= xtensa_dm_queue_reg_write
438 static const struct xtensa_power_ops esp32s2_pwr_ops
= {
439 .queue_reg_read
= xtensa_dm_queue_pwr_reg_read
,
440 .queue_reg_write
= xtensa_dm_queue_pwr_reg_write
443 static const struct esp_semihost_ops esp32s2_semihost_ops
= {
444 .prepare
= esp32s2_disable_wdts
447 static int esp32s2_target_create(struct target
*target
, Jim_Interp
*interp
)
449 struct xtensa_debug_module_config esp32s2_dm_cfg
= {
450 .dbg_ops
= &esp32s2_dbg_ops
,
451 .pwr_ops
= &esp32s2_pwr_ops
,
453 .queue_tdi_idle
= NULL
,
454 .queue_tdi_idle_arg
= NULL
457 /* creates xtensa object */
458 struct esp32s2_common
*esp32
= calloc(1, sizeof(*esp32
));
460 LOG_ERROR("Failed to alloc memory for arch info!");
464 int ret
= esp_xtensa_init_arch_info(target
, &esp32
->esp_xtensa
, &esp32s2_dm_cfg
, &esp32s2_semihost_ops
);
465 if (ret
!= ERROR_OK
) {
466 LOG_ERROR("Failed to init arch info!");
471 /* Assume running target. If different, the first poll will fix this */
472 target
->state
= TARGET_RUNNING
;
473 target
->debug_reason
= DBG_REASON_NOTHALTED
;
477 static const struct command_registration esp32s2_command_handlers
[] = {
479 .chain
= xtensa_command_handlers
,
484 .chain
= esp32_apptrace_command_handlers
,
489 .help
= "ARM Command Group",
491 .chain
= semihosting_common_handlers
493 COMMAND_REGISTRATION_DONE
496 /* Holds methods for Xtensa targets. */
497 struct target_type esp32s2_target
= {
500 .poll
= esp32s2_poll
,
501 .arch_state
= esp32s2_arch_state
,
504 .resume
= xtensa_resume
,
505 .step
= esp32s2_step
,
507 .assert_reset
= esp32s2_assert_reset
,
508 .deassert_reset
= esp32s2_deassert_reset
,
509 .soft_reset_halt
= esp32s2_soft_reset_halt
,
511 .virt2phys
= esp32s2_virt2phys
,
512 .mmu
= xtensa_mmu_is_enabled
,
513 .read_memory
= xtensa_read_memory
,
514 .write_memory
= xtensa_write_memory
,
516 .read_buffer
= xtensa_read_buffer
,
517 .write_buffer
= xtensa_write_buffer
,
519 .checksum_memory
= xtensa_checksum_memory
,
521 .get_gdb_arch
= xtensa_get_gdb_arch
,
522 .get_gdb_reg_list
= xtensa_get_gdb_reg_list
,
524 .run_algorithm
= xtensa_run_algorithm
,
525 .start_algorithm
= xtensa_start_algorithm
,
526 .wait_algorithm
= xtensa_wait_algorithm
,
528 .add_breakpoint
= esp_xtensa_breakpoint_add
,
529 .remove_breakpoint
= esp_xtensa_breakpoint_remove
,
531 .add_watchpoint
= xtensa_watchpoint_add
,
532 .remove_watchpoint
= xtensa_watchpoint_remove
,
534 .target_create
= esp32s2_target_create
,
535 .init_target
= esp32s2_target_init
,
536 .examine
= xtensa_examine
,
537 .deinit_target
= esp_xtensa_target_deinit
,
539 .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)