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_IRAM_LOW 0x40370000
28 #define ESP32_S3_IRAM_HIGH 0x403E0000
29 #define ESP32_S3_IROM_MASK_LOW 0x40000000
30 #define ESP32_S3_IROM_MASK_HIGH 0x40060000
31 #define ESP32_S3_DRAM_LOW 0x3FC88000
32 #define ESP32_S3_DRAM_HIGH 0x3FD00000
33 #define ESP32_S3_RTC_IRAM_LOW 0x600FE000
34 #define ESP32_S3_RTC_IRAM_HIGH 0x60100000
35 #define ESP32_S3_RTC_DRAM_LOW 0x600FE000
36 #define ESP32_S3_RTC_DRAM_HIGH 0x60100000
37 #define ESP32_S3_RTC_DATA_LOW 0x50000000
38 #define ESP32_S3_RTC_DATA_HIGH 0x50002000
39 #define ESP32_S3_EXTRAM_DATA_LOW 0x3D000000
40 #define ESP32_S3_EXTRAM_DATA_HIGH 0x3E000000
41 #define ESP32_S3_SYS_RAM_LOW 0x60000000UL
42 #define ESP32_S3_SYS_RAM_HIGH (ESP32_S3_SYS_RAM_LOW + 0x10000000UL)
43 #define ESP32_S3_RTC_SLOW_MEM_BASE ESP32_S3_RTC_DATA_LOW
46 #define ESP32_S3_WDT_WKEY_VALUE 0x50D83AA1
47 #define ESP32_S3_TIMG0_BASE 0x6001F000
48 #define ESP32_S3_TIMG1_BASE 0x60020000
49 #define ESP32_S3_TIMGWDT_CFG0_OFF 0x48
50 #define ESP32_S3_TIMGWDT_PROTECT_OFF 0x64
51 #define ESP32_S3_TIMG0WDT_CFG0 (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
52 #define ESP32_S3_TIMG1WDT_CFG0 (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_CFG0_OFF)
53 #define ESP32_S3_TIMG0WDT_PROTECT (ESP32_S3_TIMG0_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
54 #define ESP32_S3_TIMG1WDT_PROTECT (ESP32_S3_TIMG1_BASE + ESP32_S3_TIMGWDT_PROTECT_OFF)
55 #define ESP32_S3_RTCCNTL_BASE 0x60008000
56 #define ESP32_S3_RTCWDT_CFG_OFF 0x98
57 #define ESP32_S3_RTCWDT_PROTECT_OFF 0xB0
58 #define ESP32_S3_SWD_CONF_OFF 0xB0
59 #define ESP32_S3_SWD_WPROTECT_OFF 0xB4
60 #define ESP32_S3_RTCWDT_CFG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_CFG_OFF)
61 #define ESP32_S3_RTCWDT_PROTECT (ESP32_S3_RTCCNTL_BASE + ESP32_S3_RTCWDT_PROTECT_OFF)
62 #define ESP32_S3_SWD_CONF_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_CONF_OFF)
63 #define ESP32_S3_SWD_WPROTECT_REG (ESP32_S3_RTCCNTL_BASE + ESP32_S3_SWD_WPROTECT_OFF)
64 #define ESP32_S3_SWD_AUTO_FEED_EN_M BIT(31)
65 #define ESP32_S3_SWD_WKEY_VALUE 0x8F1D312AU
67 #define ESP32_S3_TRACEMEM_BLOCK_SZ 0x4000
69 /* ESP32_S3 dport regs */
70 #define ESP32_S3_DR_REG_SYSTEM_BASE 0x600c0000
71 #define ESP32_S3_SYSTEM_CORE_1_CONTROL_0_REG (ESP32_S3_DR_REG_SYSTEM_BASE + 0x014)
72 #define ESP32_S3_SYSTEM_CONTROL_CORE_1_CLKGATE_EN BIT(1)
74 /* ESP32_S3 RTC regs */
75 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG (ESP32_S3_RTCCNTL_BASE + 0xBC)
76 #define ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF 0x0
78 struct esp32s3_common
{
79 struct esp_xtensa_smp_common esp_xtensa_smp
;
82 /* Reset ESP32-S3's peripherals.
83 * 1. OpenOCD makes sure the target is halted; if not, tries to halt it.
84 * If that fails, tries to reset it (via OCD) and then halt.
85 * 2. OpenOCD loads the stub code into RTC_SLOW_MEM.
86 * 3. Executes the stub code from address 0x50000004.
87 * 4. The stub code changes the reset vector to 0x50000000, and triggers
88 * a system reset using RTC_CNTL_SW_SYS_RST bit.
89 * 5. Once the PRO CPU is out of reset, it executes the stub code from address 0x50000000.
90 * The stub code disables the watchdog, re-enables JTAG and the APP CPU,
91 * restores the reset vector, and enters an infinite loop.
92 * 6. OpenOCD waits until it can talk to the OCD module again, then halts the target.
93 * 7. OpenOCD restores the contents of RTC_SLOW_MEM.
95 * End result: all the peripherals except RTC_CNTL are reset, CPU's PC is undefined,
96 * PRO CPU is halted, APP CPU is in reset.
99 static const uint8_t esp32s3_reset_stub_code
[] = {
100 #include "../../../contrib/loaders/reset/espressif/esp32s3/cpu_reset_handler_code.inc"
103 static int esp32s3_soc_reset(struct target
*target
)
106 struct target_list
*head
;
107 struct xtensa
*xtensa
;
110 /* In order to write to peripheral registers, target must be halted first */
111 if (target
->state
!= TARGET_HALTED
) {
112 LOG_DEBUG("Target not halted before SoC reset, trying to halt it first");
114 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
115 if (res
!= ERROR_OK
) {
116 LOG_DEBUG("Couldn't halt target before SoC reset, trying to do reset-halt");
117 res
= xtensa_assert_reset(target
);
118 if (res
!= ERROR_OK
) {
120 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
126 bool reset_halt_save
= target
->reset_halt
;
127 target
->reset_halt
= true;
128 res
= xtensa_deassert_reset(target
);
129 target
->reset_halt
= reset_halt_save
;
130 if (res
!= ERROR_OK
) {
132 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
139 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
140 if (res
!= ERROR_OK
) {
141 LOG_ERROR("Couldn't halt target before SoC reset");
148 foreach_smp_target(head
, target
->smp_targets
) {
149 xtensa
= target_to_xtensa(head
->target
);
150 /* if any of the cores is stalled unstall them */
151 if (xtensa_dm_core_is_stalled(&xtensa
->dbg_mod
)) {
152 LOG_TARGET_DEBUG(head
->target
, "Unstall CPUs before SW reset!");
153 res
= target_write_u32(target
,
154 ESP32_S3_RTC_CNTL_SW_CPU_STALL_REG
,
155 ESP32_S3_RTC_CNTL_SW_CPU_STALL_DEF
);
156 if (res
!= ERROR_OK
) {
157 LOG_TARGET_ERROR(head
->target
, "Failed to unstall CPUs before SW reset!");
160 break; /* both cores are unstalled now, so exit the loop */
165 LOG_DEBUG("Loading stub code into RTC RAM");
166 uint8_t slow_mem_save
[sizeof(esp32s3_reset_stub_code
)];
168 /* Save contents of RTC_SLOW_MEM which we are about to overwrite */
169 res
= target_read_buffer(target
, ESP32_S3_RTC_SLOW_MEM_BASE
, sizeof(slow_mem_save
), slow_mem_save
);
170 if (res
!= ERROR_OK
) {
171 LOG_ERROR("Failed to save contents of RTC_SLOW_MEM (%d)!", res
);
175 /* Write stub code into RTC_SLOW_MEM */
176 res
= target_write_buffer(target
,
177 ESP32_S3_RTC_SLOW_MEM_BASE
,
178 sizeof(esp32s3_reset_stub_code
),
179 esp32s3_reset_stub_code
);
180 if (res
!= ERROR_OK
) {
181 LOG_ERROR("Failed to write stub (%d)!", res
);
185 LOG_DEBUG("Resuming the target");
186 xtensa
= target_to_xtensa(target
);
187 xtensa
->suppress_dsr_errors
= true;
188 res
= xtensa_resume(target
, 0, ESP32_S3_RTC_SLOW_MEM_BASE
+ 4, 0, 0);
189 xtensa
->suppress_dsr_errors
= false;
190 if (res
!= ERROR_OK
) {
191 LOG_ERROR("Failed to run stub (%d)!", res
);
194 LOG_DEBUG("resume done, waiting for the target to come alive");
196 /* Wait for SoC to reset */
198 int64_t timeout
= timeval_ms() + 100;
199 bool get_timeout
= false;
200 while (target
->state
!= TARGET_RESET
&& target
->state
!= TARGET_RUNNING
) {
203 if (timeval_ms() >= timeout
) {
204 LOG_TARGET_ERROR(target
,
205 "Timed out waiting for CPU to be reset, target state=%d",
212 /* Halt the CPU again */
213 LOG_DEBUG("halting the target");
215 res
= target_wait_state(target
, TARGET_HALTED
, 1000);
216 if (res
== ERROR_OK
) {
217 LOG_DEBUG("restoring RTC_SLOW_MEM");
218 res
= target_write_buffer(target
, ESP32_S3_RTC_SLOW_MEM_BASE
, sizeof(slow_mem_save
), slow_mem_save
);
220 LOG_TARGET_ERROR(target
, "Failed to restore contents of RTC_SLOW_MEM (%d)!", res
);
222 LOG_TARGET_ERROR(target
, "Timed out waiting for CPU to be halted after SoC reset");
225 return get_timeout
? ERROR_TARGET_TIMEOUT
: res
;
228 static int esp32s3_disable_wdts(struct target
*target
)
231 int res
= target_write_u32(target
, ESP32_S3_TIMG0WDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
232 if (res
!= ERROR_OK
) {
233 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_PROTECT (%d)!", res
);
236 res
= target_write_u32(target
, ESP32_S3_TIMG0WDT_CFG0
, 0);
237 if (res
!= ERROR_OK
) {
238 LOG_ERROR("Failed to write ESP32_S3_TIMG0WDT_CFG0 (%d)!", res
);
242 res
= target_write_u32(target
, ESP32_S3_TIMG1WDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
243 if (res
!= ERROR_OK
) {
244 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_PROTECT (%d)!", res
);
247 res
= target_write_u32(target
, ESP32_S3_TIMG1WDT_CFG0
, 0);
248 if (res
!= ERROR_OK
) {
249 LOG_ERROR("Failed to write ESP32_S3_TIMG1WDT_CFG0 (%d)!", res
);
253 res
= target_write_u32(target
, ESP32_S3_RTCWDT_PROTECT
, ESP32_S3_WDT_WKEY_VALUE
);
254 if (res
!= ERROR_OK
) {
255 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_PROTECT (%d)!", res
);
258 res
= target_write_u32(target
, ESP32_S3_RTCWDT_CFG
, 0);
259 if (res
!= ERROR_OK
) {
260 LOG_ERROR("Failed to write ESP32_S3_RTCWDT_CFG (%d)!", res
);
263 /* Enable SWD auto-feed */
264 res
= target_write_u32(target
, ESP32_S3_SWD_WPROTECT_REG
, ESP32_S3_SWD_WKEY_VALUE
);
265 if (res
!= ERROR_OK
) {
266 LOG_ERROR("Failed to write ESP32_S3_SWD_WPROTECT_REG (%d)!", res
);
269 uint32_t swd_conf_reg
= 0;
270 res
= target_read_u32(target
, ESP32_S3_SWD_CONF_REG
, &swd_conf_reg
);
271 if (res
!= ERROR_OK
) {
272 LOG_ERROR("Failed to read ESP32_S3_SWD_CONF_REG (%d)!", res
);
275 swd_conf_reg
|= ESP32_S3_SWD_AUTO_FEED_EN_M
;
276 res
= target_write_u32(target
, ESP32_S3_SWD_CONF_REG
, swd_conf_reg
);
277 if (res
!= ERROR_OK
) {
278 LOG_ERROR("Failed to write ESP32_S3_SWD_CONF_REG (%d)!", res
);
284 static int esp32s3_on_halt(struct target
*target
)
286 return esp32s3_disable_wdts(target
);
289 static int esp32s3_arch_state(struct target
*target
)
294 static int esp32s3_virt2phys(struct target
*target
,
295 target_addr_t
virtual, target_addr_t
*physical
)
304 static int esp32s3_target_init(struct command_context
*cmd_ctx
, struct target
*target
)
306 return esp_xtensa_smp_target_init(cmd_ctx
, target
);
309 static const struct xtensa_debug_ops esp32s3_dbg_ops
= {
310 .queue_enable
= xtensa_dm_queue_enable
,
311 .queue_reg_read
= xtensa_dm_queue_reg_read
,
312 .queue_reg_write
= xtensa_dm_queue_reg_write
315 static const struct xtensa_power_ops esp32s3_pwr_ops
= {
316 .queue_reg_read
= xtensa_dm_queue_pwr_reg_read
,
317 .queue_reg_write
= xtensa_dm_queue_pwr_reg_write
320 static const struct esp_xtensa_smp_chip_ops esp32s3_chip_ops
= {
321 .reset
= esp32s3_soc_reset
,
322 .on_halt
= esp32s3_on_halt
325 static const struct esp_semihost_ops esp32s3_semihost_ops
= {
326 .prepare
= esp32s3_disable_wdts
329 static int esp32s3_target_create(struct target
*target
, Jim_Interp
*interp
)
331 struct xtensa_debug_module_config esp32s3_dm_cfg
= {
332 .dbg_ops
= &esp32s3_dbg_ops
,
333 .pwr_ops
= &esp32s3_pwr_ops
,
335 .queue_tdi_idle
= NULL
,
336 .queue_tdi_idle_arg
= NULL
339 struct esp32s3_common
*esp32s3
= calloc(1, sizeof(struct esp32s3_common
));
341 LOG_ERROR("Failed to alloc memory for arch info!");
345 int ret
= esp_xtensa_smp_init_arch_info(target
,
346 &esp32s3
->esp_xtensa_smp
,
349 &esp32s3_semihost_ops
);
350 if (ret
!= ERROR_OK
) {
351 LOG_ERROR("Failed to init arch info!");
356 /* Assume running target. If different, the first poll will fix this. */
357 target
->state
= TARGET_RUNNING
;
358 target
->debug_reason
= DBG_REASON_NOTHALTED
;
362 static const struct command_registration esp32s3_command_handlers
[] = {
365 .chain
= esp_xtensa_smp_command_handlers
,
370 .chain
= smp_command_handlers
,
375 .help
= "ARM Command Group",
377 .chain
= semihosting_common_handlers
379 COMMAND_REGISTRATION_DONE
382 /** Holds methods for Xtensa targets. */
383 struct target_type esp32s3_target
= {
386 .poll
= esp_xtensa_smp_poll
,
387 .arch_state
= esp32s3_arch_state
,
390 .resume
= esp_xtensa_smp_resume
,
391 .step
= esp_xtensa_smp_step
,
393 .assert_reset
= esp_xtensa_smp_assert_reset
,
394 .deassert_reset
= esp_xtensa_smp_deassert_reset
,
395 .soft_reset_halt
= esp_xtensa_smp_soft_reset_halt
,
397 .virt2phys
= esp32s3_virt2phys
,
398 .mmu
= xtensa_mmu_is_enabled
,
399 .read_memory
= xtensa_read_memory
,
400 .write_memory
= xtensa_write_memory
,
402 .read_buffer
= xtensa_read_buffer
,
403 .write_buffer
= xtensa_write_buffer
,
405 .checksum_memory
= xtensa_checksum_memory
,
407 .get_gdb_arch
= xtensa_get_gdb_arch
,
408 .get_gdb_reg_list
= xtensa_get_gdb_reg_list
,
410 .add_breakpoint
= esp_xtensa_breakpoint_add
,
411 .remove_breakpoint
= esp_xtensa_breakpoint_remove
,
413 .add_watchpoint
= esp_xtensa_smp_watchpoint_add
,
414 .remove_watchpoint
= esp_xtensa_smp_watchpoint_remove
,
416 .target_create
= esp32s3_target_create
,
417 .init_target
= esp32s3_target_init
,
418 .examine
= xtensa_examine
,
419 .deinit_target
= esp_xtensa_target_deinit
,
421 .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)