target/esp_xtensa: add xtensa on_halt handler
[openocd.git] / src / target / espressif / esp32.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * ESP32 target API for OpenOCD *
5 * Copyright (C) 2016-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 <target/target.h>
14 #include <target/target_type.h>
15 #include <target/smp.h>
16 #include <target/semihosting_common.h>
17 #include "assert.h"
18 #include "esp_xtensa_smp.h"
19
20 /*
21 This is a JTAG driver for the ESP32, the are two Tensilica cores inside
22 the ESP32 chip. For more information please have a look into ESP32 target
23 implementation.
24 */
25
26 /* ESP32 memory map */
27 #define ESP32_DRAM_LOW 0x3ffae000
28 #define ESP32_DRAM_HIGH 0x40000000
29 #define ESP32_IROM_MASK_LOW 0x40000000
30 #define ESP32_IROM_MASK_HIGH 0x40064f00
31 #define ESP32_IRAM_LOW 0x40070000
32 #define ESP32_IRAM_HIGH 0x400a0000
33 #define ESP32_RTC_IRAM_LOW 0x400c0000
34 #define ESP32_RTC_IRAM_HIGH 0x400c2000
35 #define ESP32_RTC_DRAM_LOW 0x3ff80000
36 #define ESP32_RTC_DRAM_HIGH 0x3ff82000
37 #define ESP32_RTC_DATA_LOW 0x50000000
38 #define ESP32_RTC_DATA_HIGH 0x50002000
39 #define ESP32_EXTRAM_DATA_LOW 0x3f800000
40 #define ESP32_EXTRAM_DATA_HIGH 0x3fc00000
41 #define ESP32_DR_REG_LOW 0x3ff00000
42 #define ESP32_DR_REG_HIGH 0x3ff71000
43 #define ESP32_SYS_RAM_LOW 0x60000000UL
44 #define ESP32_SYS_RAM_HIGH (ESP32_SYS_RAM_LOW + 0x20000000UL)
45 #define ESP32_RTC_SLOW_MEM_BASE ESP32_RTC_DATA_LOW
46
47 /* ESP32 WDT */
48 #define ESP32_WDT_WKEY_VALUE 0x50d83aa1
49 #define ESP32_TIMG0_BASE 0x3ff5f000
50 #define ESP32_TIMG1_BASE 0x3ff60000
51 #define ESP32_TIMGWDT_CFG0_OFF 0x48
52 #define ESP32_TIMGWDT_PROTECT_OFF 0x64
53 #define ESP32_TIMG0WDT_CFG0 (ESP32_TIMG0_BASE + ESP32_TIMGWDT_CFG0_OFF)
54 #define ESP32_TIMG1WDT_CFG0 (ESP32_TIMG1_BASE + ESP32_TIMGWDT_CFG0_OFF)
55 #define ESP32_TIMG0WDT_PROTECT (ESP32_TIMG0_BASE + ESP32_TIMGWDT_PROTECT_OFF)
56 #define ESP32_TIMG1WDT_PROTECT (ESP32_TIMG1_BASE + ESP32_TIMGWDT_PROTECT_OFF)
57 #define ESP32_RTCCNTL_BASE 0x3ff48000
58 #define ESP32_RTCWDT_CFG_OFF 0x8C
59 #define ESP32_RTCWDT_PROTECT_OFF 0xA4
60 #define ESP32_RTCWDT_CFG (ESP32_RTCCNTL_BASE + ESP32_RTCWDT_CFG_OFF)
61 #define ESP32_RTCWDT_PROTECT (ESP32_RTCCNTL_BASE + ESP32_RTCWDT_PROTECT_OFF)
62
63 #define ESP32_TRACEMEM_BLOCK_SZ 0x4000
64
65 /* ESP32 dport regs */
66 #define ESP32_DR_REG_DPORT_BASE ESP32_DR_REG_LOW
67 #define ESP32_DPORT_APPCPU_CTRL_B_REG (ESP32_DR_REG_DPORT_BASE + 0x030)
68 #define ESP32_DPORT_APPCPU_CLKGATE_EN BIT(0)
69 /* ESP32 RTC regs */
70 #define ESP32_RTC_CNTL_SW_CPU_STALL_REG (ESP32_RTCCNTL_BASE + 0xac)
71 #define ESP32_RTC_CNTL_SW_CPU_STALL_DEF 0x0
72
73 /* 0 - don't care, 1 - TMS low, 2 - TMS high */
74 enum esp32_flash_bootstrap {
75 FBS_DONTCARE = 0,
76 FBS_TMSLOW,
77 FBS_TMSHIGH,
78 };
79
80 struct esp32_common {
81 struct esp_xtensa_smp_common esp_xtensa_smp;
82 enum esp32_flash_bootstrap flash_bootstrap;
83 };
84
85 static inline struct esp32_common *target_to_esp32(struct target *target)
86 {
87 return container_of(target->arch_info, struct esp32_common, esp_xtensa_smp);
88 }
89
90 /* Reset ESP32 peripherals.
91 * Postconditions: all peripherals except RTC_CNTL are reset, CPU's PC is undefined, PRO CPU is halted,
92 * APP CPU is in reset
93 * How this works:
94 * 0. make sure target is halted; if not, try to halt it; if that fails, try to reset it (via OCD) and then halt
95 * 1. set CPU initial PC to 0x50000000 (ESP32_SMP_RTC_DATA_LOW) by clearing RTC_CNTL_{PRO,APP}CPU_STAT_VECTOR_SEL
96 * 2. load stub code into ESP32_SMP_RTC_DATA_LOW; once executed, stub code will disable watchdogs and
97 * make CPU spin in an idle loop.
98 * 3. trigger SoC reset using RTC_CNTL_SW_SYS_RST bit
99 * 4. wait for the OCD to be reset
100 * 5. halt the target and wait for it to be halted (at this point CPU is in the idle loop)
101 * 6. restore initial PC and the contents of ESP32_SMP_RTC_DATA_LOW
102 * TODO: some state of RTC_CNTL is not reset during SW_SYS_RST. Need to reset that manually. */
103
104 static const uint8_t esp32_reset_stub_code[] = {
105 #include "../../../contrib/loaders/reset/espressif/esp32/cpu_reset_handler_code.inc"
106 };
107
108 static int esp32_soc_reset(struct target *target)
109 {
110 int res;
111 struct target_list *head;
112 struct xtensa *xtensa;
113
114 LOG_DEBUG("start");
115 /* In order to write to peripheral registers, target must be halted first */
116 if (target->state != TARGET_HALTED) {
117 LOG_DEBUG("Target not halted before SoC reset, trying to halt it first");
118 xtensa_halt(target);
119 res = target_wait_state(target, TARGET_HALTED, 1000);
120 if (res != ERROR_OK) {
121 LOG_DEBUG("Couldn't halt target before SoC reset, trying to do reset-halt");
122 res = xtensa_assert_reset(target);
123 if (res != ERROR_OK) {
124 LOG_ERROR(
125 "Couldn't halt target before SoC reset! (xtensa_assert_reset returned %d)",
126 res);
127 return res;
128 }
129 alive_sleep(10);
130 xtensa_poll(target);
131 bool reset_halt_save = target->reset_halt;
132 target->reset_halt = true;
133 res = xtensa_deassert_reset(target);
134 target->reset_halt = reset_halt_save;
135 if (res != ERROR_OK) {
136 LOG_ERROR(
137 "Couldn't halt target before SoC reset! (xtensa_deassert_reset returned %d)",
138 res);
139 return res;
140 }
141 alive_sleep(10);
142 xtensa_poll(target);
143 xtensa_halt(target);
144 res = target_wait_state(target, TARGET_HALTED, 1000);
145 if (res != ERROR_OK) {
146 LOG_ERROR("Couldn't halt target before SoC reset");
147 return res;
148 }
149 }
150 }
151
152 if (target->smp) {
153 foreach_smp_target(head, target->smp_targets) {
154 xtensa = target_to_xtensa(head->target);
155 /* if any of the cores is stalled unstall them */
156 if (xtensa_dm_core_is_stalled(&xtensa->dbg_mod)) {
157 LOG_TARGET_DEBUG(head->target, "Unstall CPUs before SW reset!");
158 res = target_write_u32(target,
159 ESP32_RTC_CNTL_SW_CPU_STALL_REG,
160 ESP32_RTC_CNTL_SW_CPU_STALL_DEF);
161 if (res != ERROR_OK) {
162 LOG_TARGET_ERROR(head->target, "Failed to unstall CPUs before SW reset!");
163 return res;
164 }
165 break; /* both cores are unstalled now, so exit the loop */
166 }
167 }
168 }
169
170 LOG_DEBUG("Loading stub code into RTC RAM");
171 uint8_t slow_mem_save[sizeof(esp32_reset_stub_code)];
172
173 /* Save contents of RTC_SLOW_MEM which we are about to overwrite */
174 res = target_read_buffer(target, ESP32_RTC_SLOW_MEM_BASE, sizeof(slow_mem_save), slow_mem_save);
175 if (res != ERROR_OK) {
176 LOG_ERROR("Failed to save contents of RTC_SLOW_MEM (%d)!", res);
177 return res;
178 }
179
180 /* Write stub code into RTC_SLOW_MEM */
181 res = target_write_buffer(target, ESP32_RTC_SLOW_MEM_BASE, sizeof(esp32_reset_stub_code), esp32_reset_stub_code);
182 if (res != ERROR_OK) {
183 LOG_ERROR("Failed to write stub (%d)!", res);
184 return res;
185 }
186
187 LOG_DEBUG("Resuming the target");
188 xtensa = target_to_xtensa(target);
189 xtensa->suppress_dsr_errors = true;
190 res = xtensa_resume(target, 0, ESP32_RTC_SLOW_MEM_BASE + 4, 0, 0);
191 xtensa->suppress_dsr_errors = false;
192 if (res != ERROR_OK) {
193 LOG_ERROR("Failed to run stub (%d)!", res);
194 return res;
195 }
196 LOG_DEBUG("resume done, waiting for the target to come alive");
197
198 /* Wait for SoC to reset */
199 alive_sleep(100);
200 int64_t timeout = timeval_ms() + 100;
201 bool get_timeout = false;
202 while (target->state != TARGET_RESET && target->state != TARGET_RUNNING) {
203 alive_sleep(10);
204 xtensa_poll(target);
205 if (timeval_ms() >= timeout) {
206 LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be reset, target state=%d",
207 target->state);
208 get_timeout = true;
209 break;
210 }
211 }
212
213 /* Halt the CPU again */
214 LOG_DEBUG("halting the target");
215 xtensa_halt(target);
216 res = target_wait_state(target, TARGET_HALTED, 1000);
217 if (res == ERROR_OK) {
218 LOG_DEBUG("restoring RTC_SLOW_MEM");
219 res = target_write_buffer(target, ESP32_RTC_SLOW_MEM_BASE, sizeof(slow_mem_save), slow_mem_save);
220 if (res != ERROR_OK)
221 LOG_TARGET_ERROR(target, "Failed to restore contents of RTC_SLOW_MEM (%d)!", res);
222 } else {
223 LOG_TARGET_ERROR(target, "Timed out waiting for CPU to be halted after SoC reset");
224 }
225
226 return get_timeout ? ERROR_TARGET_TIMEOUT : res;
227 }
228
229 static int esp32_disable_wdts(struct target *target)
230 {
231 /* TIMG1 WDT */
232 int res = target_write_u32(target, ESP32_TIMG0WDT_PROTECT, ESP32_WDT_WKEY_VALUE);
233 if (res != ERROR_OK) {
234 LOG_ERROR("Failed to write ESP32_TIMG0WDT_PROTECT (%d)!", res);
235 return res;
236 }
237 res = target_write_u32(target, ESP32_TIMG0WDT_CFG0, 0);
238 if (res != ERROR_OK) {
239 LOG_ERROR("Failed to write ESP32_TIMG0WDT_CFG0 (%d)!", res);
240 return res;
241 }
242 /* TIMG2 WDT */
243 res = target_write_u32(target, ESP32_TIMG1WDT_PROTECT, ESP32_WDT_WKEY_VALUE);
244 if (res != ERROR_OK) {
245 LOG_ERROR("Failed to write ESP32_TIMG1WDT_PROTECT (%d)!", res);
246 return res;
247 }
248 res = target_write_u32(target, ESP32_TIMG1WDT_CFG0, 0);
249 if (res != ERROR_OK) {
250 LOG_ERROR("Failed to write ESP32_TIMG1WDT_CFG0 (%d)!", res);
251 return res;
252 }
253 /* RTC WDT */
254 res = target_write_u32(target, ESP32_RTCWDT_PROTECT, ESP32_WDT_WKEY_VALUE);
255 if (res != ERROR_OK) {
256 LOG_ERROR("Failed to write ESP32_RTCWDT_PROTECT (%d)!", res);
257 return res;
258 }
259 res = target_write_u32(target, ESP32_RTCWDT_CFG, 0);
260 if (res != ERROR_OK) {
261 LOG_ERROR("Failed to write ESP32_RTCWDT_CFG (%d)!", res);
262 return res;
263 }
264 return ERROR_OK;
265 }
266
267 static int esp32_on_halt(struct target *target)
268 {
269 int ret = esp32_disable_wdts(target);
270 if (ret == ERROR_OK)
271 ret = esp_xtensa_smp_on_halt(target);
272 return ret;
273 }
274
275 static int esp32_arch_state(struct target *target)
276 {
277 return ERROR_OK;
278 }
279
280 static int esp32_virt2phys(struct target *target,
281 target_addr_t virtual, target_addr_t *physical)
282 {
283 if (physical) {
284 *physical = virtual;
285 return ERROR_OK;
286 }
287 return ERROR_FAIL;
288 }
289
290 /* The TDI pin is also used as a flash Vcc bootstrap pin. If we reset the CPU externally, the last state of the TDI pin
291 * can allow the power to an 1.8V flash chip to be raised to 3.3V, or the other way around. Users can use the
292 * esp32 flashbootstrap command to set a level, and this routine will make sure the tdi line will return to
293 * that when the jtag port is idle. */
294
295 static void esp32_queue_tdi_idle(struct target *target)
296 {
297 struct esp32_common *esp32 = target_to_esp32(target);
298 static uint32_t value;
299 uint8_t t[4] = { 0, 0, 0, 0 };
300
301 if (esp32->flash_bootstrap == FBS_TMSLOW)
302 /* Make sure tdi is 0 at the exit of queue execution */
303 value = 0;
304 else if (esp32->flash_bootstrap == FBS_TMSHIGH)
305 /* Make sure tdi is 1 at the exit of queue execution */
306 value = 1;
307 else
308 return;
309
310 /* Scan out 1 bit, do not move from IRPAUSE after we're done. */
311 buf_set_u32(t, 0, 1, value);
312 jtag_add_plain_ir_scan(1, t, NULL, TAP_IRPAUSE);
313 }
314
315 static int esp32_target_init(struct command_context *cmd_ctx, struct target *target)
316 {
317 return esp_xtensa_smp_target_init(cmd_ctx, target);
318 }
319
320 static const struct xtensa_debug_ops esp32_dbg_ops = {
321 .queue_enable = xtensa_dm_queue_enable,
322 .queue_reg_read = xtensa_dm_queue_reg_read,
323 .queue_reg_write = xtensa_dm_queue_reg_write
324 };
325
326 static const struct xtensa_power_ops esp32_pwr_ops = {
327 .queue_reg_read = xtensa_dm_queue_pwr_reg_read,
328 .queue_reg_write = xtensa_dm_queue_pwr_reg_write
329 };
330
331 static const struct esp_xtensa_smp_chip_ops esp32_chip_ops = {
332 .reset = esp32_soc_reset,
333 .on_halt = esp32_on_halt
334 };
335
336 static const struct esp_semihost_ops esp32_semihost_ops = {
337 .prepare = esp32_disable_wdts
338 };
339
340 static int esp32_target_create(struct target *target, Jim_Interp *interp)
341 {
342 struct xtensa_debug_module_config esp32_dm_cfg = {
343 .dbg_ops = &esp32_dbg_ops,
344 .pwr_ops = &esp32_pwr_ops,
345 .tap = target->tap,
346 .queue_tdi_idle = esp32_queue_tdi_idle,
347 .queue_tdi_idle_arg = target
348 };
349
350 struct esp32_common *esp32 = calloc(1, sizeof(struct esp32_common));
351 if (!esp32) {
352 LOG_ERROR("Failed to alloc memory for arch info!");
353 return ERROR_FAIL;
354 }
355
356 int ret = esp_xtensa_smp_init_arch_info(target, &esp32->esp_xtensa_smp,
357 &esp32_dm_cfg, &esp32_chip_ops, &esp32_semihost_ops);
358 if (ret != ERROR_OK) {
359 LOG_ERROR("Failed to init arch info!");
360 free(esp32);
361 return ret;
362 }
363 esp32->flash_bootstrap = FBS_DONTCARE;
364
365 /* Assume running target. If different, the first poll will fix this. */
366 target->state = TARGET_RUNNING;
367 target->debug_reason = DBG_REASON_NOTHALTED;
368 return ERROR_OK;
369 }
370
371 static COMMAND_HELPER(esp32_cmd_flashbootstrap_do, struct esp32_common *esp32)
372 {
373 int state = -1;
374
375 if (CMD_ARGC < 1) {
376 const char *st;
377 state = esp32->flash_bootstrap;
378 if (state == FBS_DONTCARE)
379 st = "Don't care";
380 else if (state == FBS_TMSLOW)
381 st = "Low (3.3V)";
382 else if (state == FBS_TMSHIGH)
383 st = "High (1.8V)";
384 else
385 st = "None";
386 command_print(CMD, "Current idle tms state: %s", st);
387 return ERROR_OK;
388 }
389
390 if (!strcasecmp(CMD_ARGV[0], "none"))
391 state = FBS_DONTCARE;
392 else if (!strcasecmp(CMD_ARGV[0], "1.8"))
393 state = FBS_TMSHIGH;
394 else if (!strcasecmp(CMD_ARGV[0], "3.3"))
395 state = FBS_TMSLOW;
396 else if (!strcasecmp(CMD_ARGV[0], "high"))
397 state = FBS_TMSHIGH;
398 else if (!strcasecmp(CMD_ARGV[0], "low"))
399 state = FBS_TMSLOW;
400
401 if (state == -1) {
402 command_print(CMD,
403 "Argument unknown. Please pick one of none, high, low, 1.8 or 3.3");
404 return ERROR_FAIL;
405 }
406 esp32->flash_bootstrap = state;
407 return ERROR_OK;
408 }
409
410 COMMAND_HANDLER(esp32_cmd_flashbootstrap)
411 {
412 struct target *target = get_current_target(CMD_CTX);
413
414 if (target->smp) {
415 struct target_list *head;
416 struct target *curr;
417 foreach_smp_target(head, target->smp_targets) {
418 curr = head->target;
419 int ret = CALL_COMMAND_HANDLER(esp32_cmd_flashbootstrap_do,
420 target_to_esp32(curr));
421 if (ret != ERROR_OK)
422 return ret;
423 }
424 return ERROR_OK;
425 }
426 return CALL_COMMAND_HANDLER(esp32_cmd_flashbootstrap_do,
427 target_to_esp32(target));
428 }
429
430 static const struct command_registration esp32_any_command_handlers[] = {
431 {
432 .name = "flashbootstrap",
433 .handler = esp32_cmd_flashbootstrap,
434 .mode = COMMAND_ANY,
435 .help =
436 "Set the idle state of the TMS pin, which at reset also is the voltage selector for the flash chip.",
437 .usage = "none|1.8|3.3|high|low",
438 },
439 COMMAND_REGISTRATION_DONE
440 };
441
442 static const struct command_registration esp32_command_handlers[] = {
443 {
444 .chain = esp_xtensa_smp_command_handlers,
445 },
446 {
447 .name = "esp",
448 .usage = "",
449 .chain = esp32_apptrace_command_handlers,
450 },
451 {
452 .name = "esp32",
453 .usage = "",
454 .chain = smp_command_handlers,
455 },
456 {
457 .name = "esp32",
458 .usage = "",
459 .chain = esp32_any_command_handlers,
460 },
461 {
462 .name = "arm",
463 .mode = COMMAND_ANY,
464 .help = "ARM Command Group",
465 .usage = "",
466 .chain = semihosting_common_handlers
467 },
468 COMMAND_REGISTRATION_DONE
469 };
470
471 /** Holds methods for Xtensa targets. */
472 struct target_type esp32_target = {
473 .name = "esp32",
474
475 .poll = esp_xtensa_smp_poll,
476 .arch_state = esp32_arch_state,
477
478 .halt = xtensa_halt,
479 .resume = esp_xtensa_smp_resume,
480 .step = esp_xtensa_smp_step,
481
482 .assert_reset = esp_xtensa_smp_assert_reset,
483 .deassert_reset = esp_xtensa_smp_deassert_reset,
484 .soft_reset_halt = esp_xtensa_smp_soft_reset_halt,
485
486 .virt2phys = esp32_virt2phys,
487 .mmu = xtensa_mmu_is_enabled,
488 .read_memory = xtensa_read_memory,
489 .write_memory = xtensa_write_memory,
490
491 .read_buffer = xtensa_read_buffer,
492 .write_buffer = xtensa_write_buffer,
493
494 .checksum_memory = xtensa_checksum_memory,
495
496 .get_gdb_arch = xtensa_get_gdb_arch,
497 .get_gdb_reg_list = xtensa_get_gdb_reg_list,
498
499 .add_breakpoint = esp_xtensa_breakpoint_add,
500 .remove_breakpoint = esp_xtensa_breakpoint_remove,
501
502 .add_watchpoint = esp_xtensa_smp_watchpoint_add,
503 .remove_watchpoint = esp_xtensa_smp_watchpoint_remove,
504
505 .target_create = esp32_target_create,
506 .init_target = esp32_target_init,
507 .examine = xtensa_examine,
508 .deinit_target = esp_xtensa_target_deinit,
509
510 .commands = esp32_command_handlers,
511 };

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)