Merge branch 'fix/esp32_iram_as_8bit_access_from_isr1_v5.5' into 'release/v5.5'

fix(xtensa): Fix ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY mode for ISR1 (v5.5)

See merge request espressif/esp-idf!46417
This commit is contained in:
Jiang Jiang Jian
2026-04-24 15:27:46 +08:00
5 changed files with 141 additions and 8 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,14 +8,35 @@
Test for LoadStore exception handlers. This test performs unaligned load and store in 32bit aligned addresses
*/
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ARCH_XTENSA && CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
#include <esp_types.h>
#include <stdio.h>
#include <esp_heap_caps.h>
#include "sdkconfig.h"
#include "esp_random.h"
#include "esp_intr_alloc.h"
#include "xtensa_api.h"
#include "esp_rom_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
#include "unity.h"
#if CONFIG_IDF_TARGET_ARCH_XTENSA && CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
#define SW_ISR_NUM_L1 7 // CPU interrupt number for internal SW0 (level 1)
#define SW_ISR_NUM_L3 29 // CPU interrupt number for internal SW1 (level 3)
typedef struct {
uint8_t b8;
uint16_t b16;
uint8_t b8_2;
uint32_t b32;
} iram_data_t;
static volatile iram_data_t *s_iram;
static volatile int isr_hits;
TEST_CASE("LoadStore Exception handler", "[freertos]")
{
int32_t val0 = 0xDEADBEEF;
@@ -125,4 +146,75 @@ TEST_CASE("LoadStore Exception handler", "[freertos]")
TEST_ASSERT_TRUE(heap_caps_check_integrity_all(true));
heap_caps_free(arr);
}
static void IRAM_ATTR level_isr(void *arg)
{
const int cpu_intr_num = *(const int *)arg;
// Clear the SW interrupt source
xt_set_intclear(1 << cpu_intr_num);
// Schedule another pending level interrupt while still inside this ISR
// to keep dispatch_c_isr in the interrupt loop handling. The pending
// interrupt will be handled after this ISR returns.
if (isr_hits == 0) {
xt_set_intset(1 << cpu_intr_num);
}
// 8/16-bit accesses to s_iram will trigger LoadStore/Alignment exceptions which changes the EXCSAVE_1 value
s_iram->b16++;
s_iram->b8 = 0x5A;
s_iram->b8_2 = 0xA5;
isr_hits++;
}
static void run_sw_isr_level(int int_level)
{
memset((void *)s_iram, 0, sizeof(iram_data_t));
isr_hits = 0;
intr_handle_t handle;
int cpu_intr_num = (int_level == 1) ? SW_ISR_NUM_L1 : SW_ISR_NUM_L3;
TEST_ASSERT_EQUAL(ESP_OK, esp_intr_alloc((int_level == 1) ? ETS_INTERNAL_SW0_INTR_SOURCE : ETS_INTERNAL_SW1_INTR_SOURCE,
(int_level == 1) ? ESP_INTR_FLAG_LEVEL1 : ESP_INTR_FLAG_LEVEL3,
level_isr,
(void *)&cpu_intr_num,
&handle));
// Trigger the first interrupt; ISR will queue one more while running
xt_set_intset(1 << cpu_intr_num);
// Wait for the ISR to be invoked twice
TickType_t start = xTaskGetTickCount();
while (isr_hits < 2 && (xTaskGetTickCount() - start) < pdMS_TO_TICKS(500)) {
vTaskDelay(1);
}
TEST_ASSERT_EQUAL(2, isr_hits);
TEST_ASSERT_EQUAL_HEX8(0x5A, s_iram->b8);
TEST_ASSERT_EQUAL_HEX8(0xA5, s_iram->b8_2);
TEST_ASSERT_EQUAL_UINT16(2, s_iram->b16);
TEST_ASSERT_EQUAL_UINT32(0, s_iram->b32);
esp_intr_free(handle);
}
TEST_CASE("LoadStore: 8/16-bit field access in IRAM from ISRs when pending interrupts are present", "[freertos]")
{
s_iram = heap_caps_calloc(1, sizeof(*s_iram), MALLOC_CAP_IRAM_8BIT);
TEST_ASSERT_NOT_NULL(s_iram);
esp_rom_printf("Running test in level-1 ISR...\n");
run_sw_isr_level(1);
esp_rom_printf("test passed\n");
esp_rom_printf("Running test in level-3 ISR...\n");
run_sw_isr_level(3);
esp_rom_printf("test passed\n");
heap_caps_free((void *)s_iram);
vTaskDelay(pdMS_TO_TICKS(100)); // Wait for memory to be freed, to avoid affecting other tests.
}
#endif // CONFIG_IDF_TARGET_ARCH_XTENSA && CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
@@ -24,6 +24,8 @@ from pytest_embedded_idf.utils import idf_parametrize
),
),
),
# IRAM as 8-bit accessible memory
('iram_as_8bit_access_mem', 'esp32'),
],
indirect=['config', 'target'],
)
@@ -0,0 +1,4 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_FREERTOS_UNICORE=y
CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY=y
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y