Skip to content

Commit b966b11

Browse files
committed
esp32: support ESP32 silicon revision 3
1. Re-enable JTAG in the reset stub, needed for ESP32 rev. 3 2. Move chip-specific register operations from OpenOCD to the stub 3. Generate the literal pool automatically
1 parent 5bcedf7 commit b966b11

File tree

2 files changed

+167
-156
lines changed

2 files changed

+167
-156
lines changed

src/target/esp32.c

Lines changed: 52 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -235,34 +235,22 @@ static int esp32_assert_reset(struct target *target)
235235
return xtensa_mcore_assert_reset(target);
236236
}
237237

238-
static int esp32_write_uint32_list(struct target *target,
239-
const target_addr_t *addrs,
240-
const uint32_t *values,
241-
size_t count)
242-
{
243-
int res;
244-
for (size_t i = 0; i < count; ++i) {
245-
res = target_write_u32(target, addrs[i], values[i]);
246-
if (res != ERROR_OK) {
247-
LOG_ERROR("%s: error writing to "TARGET_ADDR_FMT, __func__, addrs[i]);
248-
return res;
249-
}
250-
}
251-
return ERROR_OK;
252-
}
253-
254238
/* Reset ESP32's peripherals.
255-
Postconditions: all peripherals except RTC_CNTL are reset, CPU's PC is undefined, PRO CPU is halted, APP CPU is in reset
256-
How this works:
257-
0. make sure target is halted; if not, try to halt it; if that fails, try to reset it (via OCD) and then halt
258-
1. set CPU initial PC to 0x50000000 (RTC_SLOW_MEM) by clearing RTC_CNTL_{PRO,APP}CPU_STAT_VECTOR_SEL
259-
2. load stub code into RTC_SLOW_MEM; once executed, stub code will disable watchdogs and make CPU spin in an idle loop.
260-
3. trigger SoC reset using RTC_CNTL_SW_SYS_RST bit
261-
4. wait for the OCD to be reset
262-
5. halt the target and wait for it to be halted (at this point CPU is in the idle loop)
263-
6. restore initial PC and the contents of RTC_SLOW_MEM
264-
TODO: some state of RTC_CNTL is not reset during SW_SYS_RST. Need to reset that manually.
265-
*/
239+
* 1. OpenOCD makes sure the target is halted; if not, tries to halt it.
240+
* If that fails, tries to reset it (via OCD) and then halt.
241+
* 2. OpenOCD loads the stub code into RTC_SLOW_MEM.
242+
* 3. Executes the stub code from address 0x50000004.
243+
* 4. The stub code changes the reset vector to 0x50000000, and triggers
244+
* a system reset using RTC_CNTL_SW_SYS_RST bit.
245+
* 5. Once the PRO CPU is out of reset, it executes the stub code from address 0x50000000.
246+
* The stub code disables the watchdog, re-enables JTAG and the APP CPU,
247+
* restores the reset vector, and enters an infinite loop.
248+
* 6. OpenOCD waits until it can talk to the OCD module again, then halts the target.
249+
* 7. OpenOCD restores the contents of RTC_SLOW_MEM.
250+
*
251+
* End result: all the peripherals except RTC_CNTL are reset, CPU's PC is undefined,
252+
* PRO CPU is halted, APP CPU is in reset.
253+
*/
266254
static int esp32_soc_reset(struct target *active_core_target)
267255
{
268256
int res;
@@ -314,25 +302,37 @@ static int esp32_soc_reset(struct target *active_core_target)
314302

315303
/* This this the stub code compiled from esp32_cpu_reset_handler.S.
316304
To compile it, run:
317-
xtensa-esp32-elf-as -o stub.o esp32_cpu_reset_handler.S
305+
xtensa-esp32-elf-gcc -c -mtext-section-literals -o stub.o esp32_cpu_reset_handler.S
318306
xtensa-esp32-elf-objcopy -j .text -O binary stub.o stub.bin
319307
These steps are not included into OpenOCD build process so that a
320308
dependency on xtensa-esp32-elf toolchain is not introduced.
321309
*/
322-
const uint32_t esp32_post_reset_code[] = {
323-
0x00000806, 0x50d83aa1, 0x00000000, 0x3ff480a4, 0x3ff4808c, 0x3ff5f064, 0x3ff5f048,
324-
0x3ff60064,
325-
0x3ff60048, 0x41fff831, 0x0439fff9, 0x39fffa41, 0xfffa4104, 0xf4310439, 0xfff541ff,
326-
0xf6410439,
327-
0x410439ff, 0x0439fff7, 0x46007000,
310+
const uint32_t esp32_reset_stub_code[] = {
311+
0x00001e06, 0x00001406, 0x3ff48034, 0x3ff480b0,
312+
0x3ff480b4, 0x3ff48070, 0x00002210, 0x9c492000,
313+
0x3ff48000, 0x50d83aa1, 0x3ff480a4, 0x3ff5f064,
314+
0x3ff60064, 0x3ff4808c, 0x3ff5f048, 0x3ff60048,
315+
0x3ff5a1fc, 0x3ff00038, 0x3ff00030, 0x3ff0002c,
316+
0x3ff48034, 0x00003000, 0x41305550, 0x0459ffeb,
317+
0x59ffeb41, 0xffea4104, 0xea410459, 0xffea31ff,
318+
0xea310439, 0xffea41ff, 0x00000439, 0x6003eb60,
319+
0x66560461, 0x30555004, 0x41ffe731, 0x0439ffe7,
320+
0x39ffe741, 0xffe64104, 0xe6410439, 0x410459ff,
321+
0x0459ffe6, 0x59ffe641, 0xffe54104, 0xe5410459,
322+
0x410459ff, 0x130cffe5, 0xe4410439, 0x39130cff,
323+
0x41045904, 0xe331ffe3, 0x006432ff, 0x46007000,
324+
0x0000fffe,
328325
};
329326

330-
uint32_t slow_mem_save[sizeof(esp32_post_reset_code) / sizeof(uint32_t)];
327+
LOG_DEBUG("loading stub code into RTC RAM");
328+
uint32_t slow_mem_save[sizeof(esp32_reset_stub_code) / sizeof(uint32_t)];
331329

332330
const int RTC_SLOW_MEM_BASE = 0x50000000;
333331
/* Save contents of RTC_SLOW_MEM which we are about to overwrite */
334332
res =
335-
target_read_buffer(active_core_target, RTC_SLOW_MEM_BASE, sizeof(slow_mem_save),
333+
target_read_buffer(active_core_target,
334+
RTC_SLOW_MEM_BASE,
335+
sizeof(slow_mem_save),
336336
(uint8_t *)slow_mem_save);
337337
if (res != ERROR_OK) {
338338
LOG_ERROR("%s %d err=%d", __func__, __LINE__, res);
@@ -341,66 +341,30 @@ static int esp32_soc_reset(struct target *active_core_target)
341341

342342
/* Write stub code into RTC_SLOW_MEM */
343343
res =
344-
target_write_buffer(active_core_target,
345-
RTC_SLOW_MEM_BASE,
346-
sizeof(esp32_post_reset_code),
347-
(const uint8_t *)esp32_post_reset_code);
344+
target_write_buffer(active_core_target, RTC_SLOW_MEM_BASE,
345+
sizeof(esp32_reset_stub_code),
346+
(const uint8_t *)esp32_reset_stub_code);
348347
if (res != ERROR_OK) {
349348
LOG_ERROR("%s %d err=%d", __func__, __LINE__, res);
350349
return res;
351350
}
352-
/* TODO: add addreses to chip config */
353-
const int RTC_CNTL_RESET_STATE_REG = 0x3ff48034;
354-
const int RTC_CNTL_RESET_STATE_DEF = 0x3000;
355-
const int RTC_CNTL_CLK_CONF_REG = 0x3ff48070;
356-
const int RTC_CNTL_CLK_CONF_DEF = 0x2210;
357-
const int RTC_CNTL_STORE4_REG = 0x3ff480b0;
358-
const int RTC_CNTL_STORE5_REG = 0x3ff480b4;
359-
const int RTC_CNTL_OPTIONS0_REG = 0x3ff48000;
360-
const int RTC_CNTL_OPTIONS0_DEF = 0x1c492000;
361-
const int RTC_CNTL_SW_SYS_RST = 0x80000000;
362-
const int DPORT_APPCPU_CTRL_A_REG = 0x3ff0002c;
363-
const int DPORT_APPCPU_CTRL_B_REG = 0x3ff00030;
364-
const int DPORT_APPCPU_CLKGATE_EN = 0x1;
365-
const int DPORT_APPCPU_CTRL_D_REG = 0x3ff00038;
366-
367-
/* Set a list of registers to these values */
368-
const target_addr_t addrs_pre[] = {
369-
/* Set entry point to RTC_SLOW_MEM */
370-
RTC_CNTL_RESET_STATE_REG,
371-
/* Reset SoC clock to XTAL, in case it was running from PLL */
372-
RTC_CNTL_CLK_CONF_REG,
373-
/* Reset RTC_CNTL_STORE{4,5}_REG, which are related to clock state */
374-
RTC_CNTL_STORE4_REG,
375-
RTC_CNTL_STORE5_REG,
376-
/* Perform reset */
377-
RTC_CNTL_OPTIONS0_REG
378-
};
379-
const uint32_t values_pre[] = {
380-
/* Set entry point to RTC_SLOW_MEM */
381-
0,
382-
/* Reset SoC clock to XTAL, in case it was running from PLL */
383-
RTC_CNTL_CLK_CONF_DEF,
384-
/* Reset RTC_CNTL_STORE{4,5}_REG, which are related to clock state */
385-
0,
386-
0,
387-
/* Perform reset */
388-
RTC_CNTL_OPTIONS0_DEF | RTC_CNTL_SW_SYS_RST
389-
};
390-
res = esp32_write_uint32_list(active_core_target,
391-
addrs_pre,
392-
values_pre,
393-
sizeof(addrs_pre) / sizeof(target_addr_t));
351+
352+
LOG_DEBUG("resuming the target");
353+
struct xtensa *xtensa = target_to_xtensa(active_core_target);
354+
xtensa->suppress_dsr_errors = true;
355+
res = xtensa_resume(active_core_target, 0, RTC_SLOW_MEM_BASE + 4, 0, 0);
394356
if (res != ERROR_OK) {
395-
LOG_WARNING("%s esp32_write_uint32_list (reg_value_pairs_pre) err=%d", __func__,
396-
res);
357+
LOG_WARNING("%s xtensa_resume err=%d", __func__, res);
397358
return res;
398359
}
360+
xtensa->suppress_dsr_errors = false;
361+
LOG_DEBUG("resume done, waiting for the target to come alive");
399362

400363
/* Wait for SoC to reset */
364+
alive_sleep(100);
401365
int timeout = 100;
402-
while (active_core_target->state != TARGET_RESET &&
403-
active_core_target->state != TARGET_RUNNING && --timeout > 0) {
366+
while (active_core_target->state != TARGET_RESET && active_core_target->state !=
367+
TARGET_RUNNING && --timeout > 0) {
404368
alive_sleep(10);
405369
xtensa_poll(active_core_target);
406370
}
@@ -412,45 +376,16 @@ static int esp32_soc_reset(struct target *active_core_target)
412376
}
413377

414378
/* Halt the CPU again */
379+
LOG_DEBUG("halting the target");
415380
xtensa_halt(active_core_target);
416381
res = target_wait_state(active_core_target, TARGET_HALTED, 1000);
417382
if (res != ERROR_OK) {
418383
LOG_ERROR("%s: Timed out waiting for CPU to be halted after SoC reset", __func__);
419384
return res;
420385
}
421386

422-
const target_addr_t addrs_post[] = {
423-
/* Reset entry point back to the reset vector */
424-
RTC_CNTL_RESET_STATE_REG,
425-
/* Clear APP CPU boot address */
426-
DPORT_APPCPU_CTRL_D_REG,
427-
/* Enable clock to APP CPU */
428-
DPORT_APPCPU_CTRL_B_REG,
429-
/* Take APP CPU out of reset */
430-
DPORT_APPCPU_CTRL_A_REG,
431-
};
432-
const uint32_t values_post[] = {
433-
/* Reset entry point back to the reset vector */
434-
RTC_CNTL_RESET_STATE_DEF,
435-
/* Clear APP CPU boot address */
436-
0,
437-
/* Enable clock to APP CPU */
438-
DPORT_APPCPU_CLKGATE_EN,
439-
/* Take APP CPU out of reset */
440-
0,
441-
};
442-
res = esp32_write_uint32_list(active_core_target,
443-
addrs_post,
444-
values_post,
445-
sizeof(addrs_post) / sizeof(target_addr_t));
446-
if (res != ERROR_OK) {
447-
LOG_WARNING("%s esp32_write_uint32_list (reg_value_pairs_post) err=%d",
448-
__func__,
449-
res);
450-
return res;
451-
}
452-
453387
/* Restore the original contents of RTC_SLOW_MEM */
388+
LOG_DEBUG("restoring RTC_SLOW_MEM");
454389
res =
455390
target_write_buffer(active_core_target, RTC_SLOW_MEM_BASE, sizeof(slow_mem_save),
456391
(const uint8_t *)slow_mem_save);
@@ -459,8 +394,6 @@ static int esp32_soc_reset(struct target *active_core_target)
459394
return res;
460395
}
461396

462-
LOG_DEBUG("end");
463-
464397
/* Clear memory which is used by RTOS layer to get the task count */
465398
if (active_core_target->rtos && active_core_target->rtos->type->post_reset_cleanup) {
466399
res = (*active_core_target->rtos->type->post_reset_cleanup)(active_core_target);

0 commit comments

Comments
 (0)