1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * ESP32-S3 target API for OpenOCD *
5 * Copyright (C) 2020 Espressif Systems Ltd. *
6 ***************************************************************************/
12 #include <helper/time_support.h>
13 #include <target/target.h>
14 #include <target/target_type.h>
15 #include <target/smp.h>
16 #include <target/semihosting_common.h>
18 #include "esp_xtensa_smp.h"
21 This is a JTAG driver for the ESP32_S3, the are two Tensilica cores inside
22 the ESP32_S3 chip. For more information please have a look into ESP32_S3 target
26 /* ESP32_S3 memory map */
27 #define ESP32_S3_RTC_DATA_LOW 0x50000000
28 #define ESP32_S3_RTC_DATA_HIGH 0x50002000
29 #define ESP32_S3_EXTRAM_DATA_LOW 0x3D000000
30 #define ESP32_S3_EXTRAM_DATA_HIGH 0x3E000000
31 #define ESP32_S3_SYS_RAM_LOW 0x60000000UL
32 #define ESP32_S3_SYS_RAM_HIGH (ESP32_S3_SYS_RAM_LOW + 0x10000000UL)
33 #define ESP32_S3_RTC_SLOW_MEM_BASE ESP32_S3_RTC_DATA_LOW
36 #define ESP32_S3_WDT_WKEY_VALUE 0x50D83AA1
37 #define ESP32_S3_TIMG0_BASE 0x6001F000
38 #define ESP32_S3_TIMG1_BASE 0x60020000
39 #define ESP32_S3_TIMGWDT_CFG0_OFF 0x48
40 #define ESP32_S3_TIMGWDT_PROTECT_OFF 0x64
41 #define ESP32_S3_TIMG0WDT_CFG0 (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
42 #define ESP32_S3_TIMG1WDT_CFG0 (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
43 #define ESP32_S3_TIMG0WDT_PROTECT (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
44 #define ESP32_S3_TIMG1WDT_PROTECT (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
45 #define ESP32_S3_RTCCNTL_BASE 0x60008000
46 #define ESP32_S3_RTCWDT_CFG_OFF 0x98
47 #define ESP32_S3_RTCWDT_PROTECT_OFF 0xB0
48 #define ESP32_S3_SWD_CONF_OFF 0xB0
49 #define ESP32_S3_SWD_WPROTECT_OFF 0xB4
50 #define ESP32_S3_RTCWDT_CFG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_CFG_OFF)
51 #define ESP32_S3_RTCWDT_PROTECT (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_PROTECT_OFF)
52 #define ESP32_S3_SWD_CONF_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_CONF_OFF)
53 #define ESP32_S3_SWD_WPROTECT_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_WPROTECT_OFF)
54 #define ESP32_S3_SWD_AUTO_FEED_EN_M BIT(31)
55 #define ESP32_S3_SWD_WKEY_VALUE 0x8F1D312AU
57 #define ESP32_S3_TRACEMEM_BLOCK_SZ 0x4000
59 /* ESP32_S3 dport regs */
60 #define ESP32_S3_DR_REG_SYSTEM_BASE 0x600c0000
61 #define ESP32_S3_SYSTEM_CORE_1_CONTROL_0_REG (ESP32_S3_DR_REG_SYSTEM_BASE + 0x014)
62 #define ESP32_S3_SYSTEM_CONTROL_CORE_1_CLKGATE_EN BIT(1)
64 /* ESP32_S3 RTC regs */
65 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG (ESP32_S3_RTCCNTL_BASE + 0xBC)
66 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF 0x0
68 struct esp32s3_common
{
69 struct esp_xtensa_smp_common esp_xtensa_smp
;
72 /* Reset ESP32-S3's peripherals.
73 * 1. OpenOCD makes sure the target is halted; if not, tries to halt it.
74 * If that fails, tries to reset it (via OCD) and then halt.
75 * 2. OpenOCD loads the stub code into RTC_SLOW_MEM.
76 * 3. Executes the stub code from address 0x50000004.
77 * 4. The stub code changes the reset vector to 0x50000000, and triggers
78 * a system reset using RTC_CNTL_SW_SYS_RST bit.
79 * 5. Once the PRO CPU is out of reset, it executes the stub code from address 0x50000000.
80 * The stub code disables the watchdog, re-enables JTAG and the APP CPU,
81 * restores the reset vector, and enters an infinite loop.
82 * 6. OpenOCD waits until it can talk to the OCD module again, then halts the target.
83 * 7. OpenOCD restores the contents of RTC_SLOW_MEM.
85 * End result: all the peripherals except RTC_CNTL are reset, CPU's PC is undefined,
86 * PRO CPU is halted, APP CPU is in reset.
89 static const uint8_t esp32s3_reset_stub_code
[] = {
90 #include "../../../contrib/loaders/reset/espressif/esp32s3/cpu_reset_handler_code.inc"
93 static int esp32s3_soc_reset(struct target
*target
)
96 struct target_list
*head
;
97 struct xtensa
*xtensa
;
100 /* In order to write to peripheral registers, target must be halted first */
101 if (target
->state
!= TARGET_HALTED
) {
102 LOG_DEBUG("Target not halted before SoC reset, trying to halt it first");
104 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
105 if (res
!= ERROR_OK
) {
106 LOG_DEBUG("Couldn't halt target before SoC reset, trying to do reset-halt");
107 res
= xtensa_assert_reset(target
);
108 if (res
!= ERROR_OK
) {
110 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
116 bool reset_halt_save
= target
->reset_halt
;
117 target
->reset_halt
= true;
118 res
= xtensa_deassert_reset(target
);
119 target
->reset_halt
= reset_halt_save
;
120 if (res
!= ERROR_OK
) {
122 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
129 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
130 if (res
!= ERROR_OK
) {
131 LOG_ERROR("Couldn't halt target before SoC reset");
138 foreach_smp_target(head
, target
->smp_targets
) {
139 xtensa
= target_to_xtensa(head
->target
);
140 /* if any of the cores is stalled unstall them */
141 if (xtensa_dm_core_is_stalled(&xtensa
->dbg_mod
)) {
142 LOG_TARGET_DEBUG(head
->target
, "Unstall CPUs before SW reset!");
143 res
= target_write_u32(target
,
144 ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG
,
145 ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF
);
146 if (res
!= ERROR_OK
) {
147 LOG_TARGET_ERROR(head
->target
, "Failed to unstall CPUs before SW reset!");
150 break; /* both cores are unstalled now, so exit the loop */
155 LOG_DEBUG("Loading stub code into RTC RAM");
156 uint8_t slow_mem_save
[sizeof(esp32s3_reset_stub_code
)];
158 /* Save contents of RTC_SLOW_MEM which we are about to overwrite */
159 res
= target_read_buffer(target
, ESP32_S3_RTC_SLOW_MEM_BASE
, sizeof(slow_mem_save
), slow_mem_save
);
160 if (res
!= ERROR_OK
) {
161 LOG_ERROR("Failed to save contents of RTC_SLOW_MEM (%d)!", res
);
165 /* Write stub code into RTC_SLOW_MEM */
166 res
= target_write_buffer(target
,
167 ESP32_S3_RTC_SLOW_MEM_BASE
,
168 sizeof(esp32s3_reset_stub_code
),
169 esp32s3_reset_stub_code
);
170 if (res
!= ERROR_OK
) {
171 LOG_ERROR("Failed to write stub (%d)!", res
);
175 LOG_DEBUG("Resuming the target");
176 xtensa
= target_to_xtensa(target
);
177 xtensa
->suppress_dsr_errors
= true;
178 res
= xtensa_resume(target
, 0, ESP32_S3_RTC_SLOW_MEM_BASE
+ 4, 0, 0);
179 xtensa
->suppress_dsr_errors
= false;
180 if (res
!= ERROR_OK
) {
181 LOG_ERROR("Failed to run stub (%d)!", res
);
184 LOG_DEBUG("resume done, waiting for the target to come alive");
186 /* Wait for SoC to reset */
188 int64_t timeout
= timeval_ms() + 100;
189 bool get_timeout
= false;
190 while (target
->state
!= TARGET_RESET
&& target
->state
!= TARGET_RUNNING
) {
193 if (timeval_ms() >= timeout
) {
194 LOG_TARGET_ERROR(target
,
195 "Timed out waiting for CPU to be reset, target state=%d",
202 /* Halt the CPU again */
203 LOG_DEBUG("halting the target");
205 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
206 if (res
== ERROR_OK
) {
207 LOG_DEBUG("restoring RTC_SLOW_MEM");
208 res
= target_write_buffer(target
, ESP32_S3_RTC_SLOW_MEM_BASE
, sizeof(slow_mem_save
), slow_mem_save
);
210 LOG_TARGET_ERROR(target
, "Failed to restore contents of RTC_SLOW_MEM (%d)!", res
);
212 LOG_TARGET_ERROR(target
, "Timed out waiting for CPU to be halted after SoC reset");
215 return get_timeout
? ERROR_TARGET_TIMEOUT
: res
;
218 static int esp32s3_disable_wdts(struct target
*target
)
221 int res
= target_write_u32(target
, ESP32_S3_TIMG0WDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
222 if (res
!= ERROR_OK
) {
223 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_PROTECT (%d)!", res
);
226 res
= target_write_u32(target
, ESP32_S3_TIMG0WDT_CFG0
, 0);
227 if (res
!= ERROR_OK
) {
228 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_CFG0 (%d)!", res
);
232 res
= target_write_u32(target
, ESP32_S3_TIMG1WDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
233 if (res
!= ERROR_OK
) {
234 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_PROTECT (%d)!", res
);
237 res
= target_write_u32(target
, ESP32_S3_TIMG1WDT_CFG0
, 0);
238 if (res
!= ERROR_OK
) {
239 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_CFG0 (%d)!", res
);
243 res
= target_write_u32(target
, ESP32_S3_RTCWDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
244 if (res
!= ERROR_OK
) {
245 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_PROTECT (%d)!", res
);
248 res
= target_write_u32(target
, ESP32_S3_RTCWDT_CFG
, 0);
249 if (res
!= ERROR_OK
) {
250 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_CFG (%d)!", res
);
253 /* Enable SWD auto-feed */
254 res
= target_write_u32(target
, ESP32_S3_SWD_WPROTECT_REG
, ESP32_S3_SWD_WKEY_VALUE
);
255 if (res
!= ERROR_OK
) {
256 LOG_ERROR("Failed to write ESP32_S3_SWD_WPROTECT_REG (%d)!", res
);
259 uint32_t swd_conf_reg
= 0;
260 res
= target_read_u32(target
, ESP32_S3_SWD_CONF_REG
, &swd_conf_reg
);
261 if (res
!= ERROR_OK
) {
262 LOG_ERROR("Failed to read ESP32_S3_SWD_CONF_REG (%d)!", res
);
265 swd_conf_reg
|= ESP32_S3_SWD_AUTO_FEED_EN_M
;
266 res
= target_write_u32(target
, ESP32_S3_SWD_CONF_REG
, swd_conf_reg
);
267 if (res
!= ERROR_OK
) {
268 LOG_ERROR("Failed to write ESP32_S3_SWD_CONF_REG (%d)!", res
);
274 static int esp32s3_on_halt(struct target
*target
)
276 int ret
= esp32s3_disable_wdts(target
);
278 ret
= esp_xtensa_smp_on_halt(target
);
282 static int esp32s3_arch_state(struct target
*target
)
287 static int esp32s3_virt2phys(struct target
*target
,
288 target_addr_t
virtual, target_addr_t
*physical
)
297 static int esp32s3_target_init(struct command_context
*cmd_ctx
, struct target
*target
)
299 return esp_xtensa_smp_target_init(cmd_ctx
, target
);
302 static const struct xtensa_debug_ops esp32s3_dbg_ops
= {
303 .queue_enable
= xtensa_dm_queue_enable
,
304 .queue_reg_read
= xtensa_dm_queue_reg_read
,
305 .queue_reg_write
= xtensa_dm_queue_reg_write
308 static const struct xtensa_power_ops esp32s3_pwr_ops
= {
309 .queue_reg_read
= xtensa_dm_queue_pwr_reg_read
,
310 .queue_reg_write
= xtensa_dm_queue_pwr_reg_write
313 static const struct esp_xtensa_smp_chip_ops esp32s3_chip_ops
= {
314 .reset
= esp32s3_soc_reset
,
315 .on_halt
= esp32s3_on_halt
318 static const struct esp_semihost_ops esp32s3_semihost_ops
= {
319 .prepare
= esp32s3_disable_wdts
322 static int esp32s3_target_create(struct target
*target
, Jim_Interp
*interp
)
324 struct xtensa_debug_module_config esp32s3_dm_cfg
= {
325 .dbg_ops
= &esp32s3_dbg_ops
,
326 .pwr_ops
= &esp32s3_pwr_ops
,
328 .queue_tdi_idle
= NULL
,
329 .queue_tdi_idle_arg
= NULL
332 struct esp32s3_common
*esp32s3
= calloc(1, sizeof(struct esp32s3_common
));
334 LOG_ERROR("Failed to alloc memory for arch info!");
338 int ret
= esp_xtensa_smp_init_arch_info(target
,
339 &esp32s3
->esp_xtensa_smp
,
342 &esp32s3_semihost_ops
);
343 if (ret
!= ERROR_OK
) {
344 LOG_ERROR("Failed to init arch info!");
349 /* Assume running target. If different, the first poll will fix this. */
350 target
->state
= TARGET_RUNNING
;
351 target
->debug_reason
= DBG_REASON_NOTHALTED
;
355 static const struct command_registration esp32s3_command_handlers
[] = {
358 .chain
= esp_xtensa_smp_command_handlers
,
363 .chain
= esp32_apptrace_command_handlers
,
368 .chain
= smp_command_handlers
,
373 .help
= "ARM Command Group",
375 .chain
= semihosting_common_handlers
377 COMMAND_REGISTRATION_DONE
380 /** Holds methods for Xtensa targets. */
381 struct target_type esp32s3_target
= {
384 .poll
= esp_xtensa_smp_poll
,
385 .arch_state
= esp32s3_arch_state
,
388 .resume
= esp_xtensa_smp_resume
,
389 .step
= esp_xtensa_smp_step
,
391 .assert_reset
= esp_xtensa_smp_assert_reset
,
392 .deassert_reset
= esp_xtensa_smp_deassert_reset
,
393 .soft_reset_halt
= esp_xtensa_smp_soft_reset_halt
,
395 .virt2phys
= esp32s3_virt2phys
,
396 .mmu
= xtensa_mmu_is_enabled
,
397 .read_memory
= xtensa_read_memory
,
398 .write_memory
= xtensa_write_memory
,
400 .read_buffer
= xtensa_read_buffer
,
401 .write_buffer
= xtensa_write_buffer
,
403 .checksum_memory
= xtensa_checksum_memory
,
405 .get_gdb_arch
= xtensa_get_gdb_arch
,
406 .get_gdb_reg_list
= xtensa_get_gdb_reg_list
,
408 .run_algorithm
= xtensa_run_algorithm
,
409 .start_algorithm
= xtensa_start_algorithm
,
410 .wait_algorithm
= xtensa_wait_algorithm
,
412 .add_breakpoint
= esp_xtensa_breakpoint_add
,
413 .remove_breakpoint
= esp_xtensa_breakpoint_remove
,
415 .add_watchpoint
= esp_xtensa_smp_watchpoint_add
,
416 .remove_watchpoint
= esp_xtensa_smp_watchpoint_remove
,
418 .target_create
= esp32s3_target_create
,
419 .init_target
= esp32s3_target_init
,
420 .examine
= xtensa_examine
,
421 .deinit_target
= esp_xtensa_target_deinit
,
423 .commands
= esp32s3_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)