Skip to content

xtensa: Fixes needed to run ESP-IDF on the esp32 core - #49

Open
oguzkaganyaglioglu wants to merge 6 commits into
antmicro:masterfrom
oguzkaganyaglioglu:1028-xtensa_esp32_fixes
Open

oguzkaganyaglioglu wants to merge 6 commits into
antmicro:masterfrom
oguzkaganyaglioglu:1028-xtensa_esp32_fixes

Conversation

@oguzkaganyaglioglu

Copy link
Copy Markdown

Fixes renode/renode#1028.

Five independent commits, each building on its own:

  • Return the reset value from RER instead of aborting
  • Add RUR/WUR translators for the ESP32 F64R_LO, F64R_HI and F64S
  • Fix the time unit of the CCOMPARE deadline
  • Honour hardware unaligned access
  • Enable the FPU opcode translators for the esp32 core

Testing: with these changes and an ESP32 platform built from the TRM (interrupt matrix, timer
groups, UART, GPIO, I2C, SPI flash + cache MMU, eFuse, RTC, SHA), the real ESP32 mask ROM boots
the ESP-IDF v5.4.2 bootloader from emulated flash, which verifies and starts IDF and
Arduino-ESP32 3.3 applications: FreeRTOS scheduling with correct tick timing, float/double
printf, NVS persisting across esp_restart(), UART RX/TX, I2C to an SSD1306. Before the
changes the emulation aborts at the first RER (bootloader), and with only that fixed the
bootloader rejects the image (unaligned access) and FreeRTOS aborts at the first context switch
(F64R) or the first float operation (FPU).

The ESP32 platform itself (peripheral models, .repl, Robot tests) will be proposed separately
against renode-infrastructure / renode (#704).

External registers (ERI: debug module, TRAX, performance monitors) are not
modelled, and RER/WER used to abort the emulation. ESP-IDF reads DSRSET with
RER in xt_utils_dbgr_is_attached(), called by its 2nd stage bootloader and
by the application, so no ESP-IDF image could run on the esp32 core.

Return 0 (the reset value) for reads and ignore writes, which reports
"no debugger attached".
…I and F64S

The esp32 core's TIE defines the F64R_LO, F64R_HI and F64S user registers
(double-precision accelerator state). FreeRTOS saves and restores them on every
context switch (xthal_save_extra_nw/xthal_restore_extra_nw), so the first task
switch hit an unimplemented opcode.

Keep their values in uregs, looking the register numbers up by name in the
core's ISA; on cores without them the instructions read 0 and ignore writes,
like QEMU's no-op translators.
update_ccount() treats tlib_get_cpu_time() as microseconds
(CCOUNT = time * clock_freq_khz / 1000), but update_ccompare() converted the
CCOUNT distance back with a nanosecond factor (dcc * 1000000 / clock_freq_khz),
a leftover from QEMU's nanosecond clock. Timer interrupts therefore fired at
the wrong time relative to CCOUNT (FreeRTOS tick 1000x late or early depending
on the CPU timer frequency).

Use microseconds in both helpers.
gen_load_store_alignment() aligned every L16*/L32I/S16I/S32I address down
when the core has no unaligned-exception option, ignoring
XTENSA_OPTION_HW_ALIGNMENT (XCHAL_UNALIGNED_LOAD_HW/STORE_HW). The ESP32 core
performs unaligned accesses in hardware, so word loads from odd addresses
returned the wrong bytes. This broke, for example, the ESP-IDF bootloader's
image SHA-256 check (its padding array lives at an odd address) and any code
reading packed data.

Keep the address when the core handles misalignment in hardware and the
instruction allows it, as QEMU does; instructions that require alignment
(L32AI, S32RI, S32C1I) still align down.
The ESP32 has the single-precision FPU (XCHAL_HAVE_FP 1), but its XtensaConfig
did not list opcode translators, so only core opcodes were translated and every
FPU instruction (LSI, MADD.S, ...) aborted as unimplemented. Use the core and
FPU translators, like de233_fpu and QEMU's esp32 core.
…ister file

Cores can have 64 physical address registers (the esp32 has), but the register
API only had AR0..AR31, so a debugger could not read the other half of the
register file: GDB's windowed-ABI unwinder needs it for every caller frame
that is still live in registers, so backtraces, arguments and locals of outer
frames came out wrong once WINDOWBASE*4 passed 32.

Add AR32..AR63 and the remaining registers Xtensa GDB builds transfer (LBEG,
LEND, LCOUNT, BR, ACCLO, ACCHI, M0..M3, CPENABLE, THREADPTR, FCR, FSR,
F0..F15). They are appended after PSOWB so existing register numbers do not
change.

AR writes now go through the physical file: the live window is synced into it
first and the window is refreshed from it afterwards, so writing an AR that
backs the current window (a debugger 'set var' on a register-resident local)
is no longer overwritten by the next sync.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Xtensa: tlib fixes needed to run ESP-IDF on the esp32 core

1 participant