fix(esp_system): PSRAM stack crash in esp_restart_noos on RISC-V chips

On RISC-V chips with SPIRAM support (esp32c5, esp32c61, esp32h4, esp32p4,
esp32s31), esp_restart_noos() was disabling the cache while the current
stack pointer could still be in external RAM. Any stack access after cache
disable (function call, local variable spill) would then fault with
"Cache disabled but cached memory region accessed".

Xtensa chips (esp32, esp32s2, esp32s3) already had this guard via the
SET_STACK macro. Add the equivalent for RISC-V:

- Add rv_utils_set_sp() to riscv/rv_utils.h (plain "mv sp, %0" with a
  memory clobber; no window register management needed on RISC-V)
- In each affected system_internal.c, under
  CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM, check whether the current
  SP is in PSRAM and if so switch it to the top of internal BSS before
  any cache disable or writeback operation
- Fix xTaskCreateStaticPinnedToCore() stack size argument in the
  spiram_stack test (was passing bytes instead of word count)
- Mark the null-pointer write in func_do_exception() as volatile to
  prevent the compiler from optimizing it away
- Extend the [spiram_stack] tests to RISC-V by sharing fibonacci() and
  the task/finish helpers across architectures, guarding only the
  Xtensa-specific WINDOWBASE/WINDOWSTART prints
This commit is contained in:
Guillaume Souchere
2026-04-22 11:42:57 +02:00
parent 75edd960c2
commit 0ce211539a
7 changed files with 311 additions and 166 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -106,6 +106,17 @@ FORCE_INLINE_ATTR void *rv_utils_get_sp(void)
return sp;
}
/* Switch the stack pointer to a new address.
*
* Unlike the Xtensa SET_STACK, no window register management is required on
* RISC-V; a plain register move is sufficient. The "memory" clobber prevents
* the compiler from reordering any accesses across the switch.
*/
FORCE_INLINE_ATTR void rv_utils_set_sp(void *new_sp)
{
asm volatile ("mv sp, %0" :: "r"(new_sp) : "memory");
}
FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_get_cycle_count(void)
{
#if !SOC_CPU_HAS_CSR_PC