kopia lustrzana https://github.com/espressif/esp-idf
feat(system): esp32p4: support panic tests
rodzic
13b55386bf
commit
cb82161dae
|
@ -208,10 +208,8 @@ tools/test_apps/system/no_embedded_paths:
|
||||||
reason: the other targets are not tested yet
|
reason: the other targets are not tested yet
|
||||||
|
|
||||||
tools/test_apps/system/panic:
|
tools/test_apps/system/panic:
|
||||||
disable:
|
enable:
|
||||||
- if: IDF_TARGET in ["esp32p4"]
|
- if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32p4"] # preview targets
|
||||||
temporary: true
|
|
||||||
reason: target(s) not supported yet # TODO: IDF-7511
|
|
||||||
|
|
||||||
tools/test_apps/system/ram_loadable_app:
|
tools/test_apps/system/ram_loadable_app:
|
||||||
disable_test:
|
disable_test:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_ESP_SYSTEM_HW_STACK_GUARD=n
|
|
@ -1,5 +1,5 @@
|
||||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,12 @@ void test_int_wdt(void);
|
||||||
|
|
||||||
void test_task_wdt_cpu0(void);
|
void test_task_wdt_cpu0(void);
|
||||||
|
|
||||||
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
void test_hw_stack_guard_cpu0(void);
|
void test_hw_stack_guard_cpu0(void);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
void test_hw_stack_guard_cpu1(void);
|
||||||
|
#endif // CONFIG_FREERTOS_UNICORE
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
|
|
||||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||||
void test_panic_extram_stack(void);
|
void test_panic_extram_stack(void);
|
||||||
|
|
|
@ -31,9 +31,7 @@
|
||||||
static const char* get_test_name(void)
|
static const char* get_test_name(void)
|
||||||
{
|
{
|
||||||
static char test_name_str[BOOT_CMD_MAX_LEN] = {0};
|
static char test_name_str[BOOT_CMD_MAX_LEN] = {0};
|
||||||
|
bool print_prompt = true;
|
||||||
printf("Enter test name: ");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
/* Not using blocking fgets(stdin) here, as QEMU doesn't yet implement RX timeout interrupt,
|
/* Not using blocking fgets(stdin) here, as QEMU doesn't yet implement RX timeout interrupt,
|
||||||
* which is required for the UART driver and blocking stdio to work.
|
* which is required for the UART driver and blocking stdio to work.
|
||||||
|
@ -42,16 +40,24 @@ static const char* get_test_name(void)
|
||||||
char *p = test_name_str;
|
char *p = test_name_str;
|
||||||
const char *end = test_name_str + sizeof(test_name_str) - 1;
|
const char *end = test_name_str + sizeof(test_name_str) - 1;
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
|
if (print_prompt) {
|
||||||
|
printf("Enter test name: ");
|
||||||
|
fflush(stdout);
|
||||||
|
print_prompt = false;
|
||||||
|
}
|
||||||
c = getchar();
|
c = getchar();
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
} else if ((c == '\r' || c == '\n') && p != test_name_str) {
|
} else if (c == '\r' || c == '\n') {
|
||||||
/* terminate the line */
|
/* terminate the line */
|
||||||
puts("\n\r");
|
puts("\n\r");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
*p = '\0';
|
print_prompt = true;
|
||||||
break;
|
if (p != test_name_str) {
|
||||||
} else {
|
*p = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (c >= '0' && c <= 'z') {
|
||||||
/* echo the received character */
|
/* echo the received character */
|
||||||
putchar(c);
|
putchar(c);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -83,7 +89,12 @@ void app_main(void)
|
||||||
HANDLE_TEST(test_name, test_abort_cache_disabled);
|
HANDLE_TEST(test_name, test_abort_cache_disabled);
|
||||||
HANDLE_TEST(test_name, test_int_wdt);
|
HANDLE_TEST(test_name, test_int_wdt);
|
||||||
HANDLE_TEST(test_name, test_task_wdt_cpu0);
|
HANDLE_TEST(test_name, test_task_wdt_cpu0);
|
||||||
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
HANDLE_TEST(test_name, test_hw_stack_guard_cpu0);
|
HANDLE_TEST(test_name, test_hw_stack_guard_cpu0);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
HANDLE_TEST(test_name, test_hw_stack_guard_cpu1);
|
||||||
|
#endif // CONFIG_FREERTOS_UNICORE
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||||
HANDLE_TEST(test_name, test_panic_extram_stack);
|
HANDLE_TEST(test_name, test_panic_extram_stack);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,6 +63,8 @@ void test_task_wdt_cpu0(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
|
|
||||||
__attribute__((optimize("-O0")))
|
__attribute__((optimize("-O0")))
|
||||||
static void test_hw_stack_guard_cpu(void* arg)
|
static void test_hw_stack_guard_cpu(void* arg)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +80,18 @@ void test_hw_stack_guard_cpu0(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
void test_hw_stack_guard_cpu1(void)
|
||||||
|
{
|
||||||
|
xTaskCreatePinnedToCore(test_hw_stack_guard_cpu, "HWSG1", 512, NULL, 1, NULL, 1);
|
||||||
|
while (true) {
|
||||||
|
vTaskDelay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_FREERTOS_UNICORE
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||||
|
|
||||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||||
|
|
||||||
static void stack_in_extram(void* arg) {
|
static void stack_in_extram(void* arg) {
|
||||||
|
|
|
@ -17,7 +17,8 @@ TARGETS_TESTED = [
|
||||||
pytest.mark.esp32s3,
|
pytest.mark.esp32s3,
|
||||||
pytest.mark.esp32c2,
|
pytest.mark.esp32c2,
|
||||||
pytest.mark.esp32c6,
|
pytest.mark.esp32c6,
|
||||||
pytest.mark.esp32h2
|
pytest.mark.esp32h2,
|
||||||
|
pytest.mark.esp32p4,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Most tests run on all targets and with all configs.
|
# Most tests run on all targets and with all configs.
|
||||||
|
@ -34,7 +35,11 @@ CONFIGS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Some tests only run on dual-core targets, they use the config below.
|
# Some tests only run on dual-core targets, they use the config below.
|
||||||
TARGETS_DUAL_CORE = [pytest.mark.esp32, pytest.mark.esp32s3]
|
TARGETS_DUAL_CORE = [
|
||||||
|
pytest.mark.esp32,
|
||||||
|
pytest.mark.esp32s3,
|
||||||
|
pytest.mark.esp32p4,
|
||||||
|
]
|
||||||
CONFIGS_DUAL_CORE = [
|
CONFIGS_DUAL_CORE = [
|
||||||
pytest.param('coredump_flash_bin_crc', marks=TARGETS_DUAL_CORE),
|
pytest.param('coredump_flash_bin_crc', marks=TARGETS_DUAL_CORE),
|
||||||
pytest.param('coredump_flash_elf_sha', marks=TARGETS_DUAL_CORE),
|
pytest.param('coredump_flash_elf_sha', marks=TARGETS_DUAL_CORE),
|
||||||
|
@ -58,6 +63,7 @@ TARGETS_HW_STACK_GUARD = [
|
||||||
pytest.mark.esp32c3,
|
pytest.mark.esp32c3,
|
||||||
pytest.mark.esp32c6,
|
pytest.mark.esp32c6,
|
||||||
pytest.mark.esp32h2,
|
pytest.mark.esp32h2,
|
||||||
|
pytest.mark.esp32p4,
|
||||||
]
|
]
|
||||||
|
|
||||||
CONFIGS_HW_STACK_GUARD = [
|
CONFIGS_HW_STACK_GUARD = [
|
||||||
|
@ -68,6 +74,14 @@ CONFIGS_HW_STACK_GUARD = [
|
||||||
pytest.param('panic', marks=TARGETS_HW_STACK_GUARD),
|
pytest.param('panic', marks=TARGETS_HW_STACK_GUARD),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
CONFIGS_HW_STACK_GUARD_DUAL_CORE = [
|
||||||
|
pytest.param('coredump_flash_bin_crc', marks=[pytest.mark.esp32p4]),
|
||||||
|
pytest.param('coredump_uart_bin_crc', marks=[pytest.mark.esp32p4]),
|
||||||
|
pytest.param('coredump_uart_elf_crc', marks=[pytest.mark.esp32p4]),
|
||||||
|
pytest.param('gdbstub', marks=[pytest.mark.esp32p4]),
|
||||||
|
pytest.param('panic', marks=[pytest.mark.esp32p4]),
|
||||||
|
]
|
||||||
|
|
||||||
# Panic abort information will start with this string.
|
# Panic abort information will start with this string.
|
||||||
PANIC_ABORT_PREFIX = 'Panic reason: '
|
PANIC_ABORT_PREFIX = 'Panic reason: '
|
||||||
|
|
||||||
|
@ -148,15 +162,16 @@ def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> N
|
||||||
'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:'
|
'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:'
|
||||||
)
|
)
|
||||||
dut.expect_exact('CPU 1: Infinite loop')
|
dut.expect_exact('CPU 1: Infinite loop')
|
||||||
|
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
|
||||||
if dut.is_xtensa:
|
if dut.is_xtensa:
|
||||||
# see comment in test_task_wdt_cpu0
|
# see comment in test_task_wdt_cpu0
|
||||||
dut.expect_none('register dump:')
|
dut.expect_none('register dump:')
|
||||||
dut.expect_exact('Print CPU 1 backtrace')
|
dut.expect_exact('Print CPU 1 backtrace')
|
||||||
dut.expect_backtrace()
|
dut.expect_backtrace()
|
||||||
# On Xtensa, we get incorrect backtrace from GDB in this test
|
|
||||||
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
|
|
||||||
else:
|
else:
|
||||||
assert False, 'No dual-core RISC-V chips yet, check this test case later'
|
# on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace
|
||||||
|
dut.expect_reg_dump(core=1)
|
||||||
|
dut.expect_stack_dump()
|
||||||
|
|
||||||
dut.expect_elf_sha256()
|
dut.expect_elf_sha256()
|
||||||
dut.expect_none('Guru Meditation')
|
dut.expect_none('Guru Meditation')
|
||||||
|
@ -204,9 +219,9 @@ def test_int_wdt(
|
||||||
dut.expect_stack_dump()
|
dut.expect_stack_dump()
|
||||||
|
|
||||||
if target in TARGETS_DUAL_CORE_NAMES:
|
if target in TARGETS_DUAL_CORE_NAMES:
|
||||||
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
|
|
||||||
dut.expect_reg_dump(1)
|
dut.expect_reg_dump(1)
|
||||||
dut.expect_backtrace()
|
if dut.is_xtensa:
|
||||||
|
dut.expect_backtrace()
|
||||||
|
|
||||||
dut.expect_elf_sha256()
|
dut.expect_elf_sha256()
|
||||||
dut.expect_none('Guru Meditation')
|
dut.expect_none('Guru Meditation')
|
||||||
|
@ -228,9 +243,9 @@ def test_int_wdt_cache_disabled(
|
||||||
dut.expect_stack_dump()
|
dut.expect_stack_dump()
|
||||||
|
|
||||||
if target in TARGETS_DUAL_CORE_NAMES:
|
if target in TARGETS_DUAL_CORE_NAMES:
|
||||||
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
|
|
||||||
dut.expect_reg_dump(1)
|
dut.expect_reg_dump(1)
|
||||||
dut.expect_backtrace()
|
if dut.is_xtensa:
|
||||||
|
dut.expect_backtrace()
|
||||||
|
|
||||||
dut.expect_elf_sha256()
|
dut.expect_elf_sha256()
|
||||||
dut.expect_none('Guru Meditation')
|
dut.expect_none('Guru Meditation')
|
||||||
|
@ -251,6 +266,8 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non
|
||||||
elif dut.target in ['esp32s2']:
|
elif dut.target in ['esp32s2']:
|
||||||
# Cache error interrupt is not enabled, IDF-1558
|
# Cache error interrupt is not enabled, IDF-1558
|
||||||
dut.expect_gme('IllegalInstruction')
|
dut.expect_gme('IllegalInstruction')
|
||||||
|
elif dut.target in ['esp32p4']: # TODO IDF-7515
|
||||||
|
dut.expect_gme('Instruction access fault')
|
||||||
else:
|
else:
|
||||||
dut.expect_gme('Cache disabled but cached memory region accessed')
|
dut.expect_gme('Cache disabled but cached memory region accessed')
|
||||||
dut.expect_reg_dump(0)
|
dut.expect_reg_dump(0)
|
||||||
|
@ -832,15 +849,36 @@ def test_gdbstub_coredump(dut: PanicTestDut) -> None:
|
||||||
return # don't expect "Rebooting" output below
|
return # don't expect "Rebooting" output below
|
||||||
|
|
||||||
|
|
||||||
|
def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None:
|
||||||
|
dut.expect_exact(f'Guru Meditation Error: Core {cpu} panic\'ed (Stack protection fault).')
|
||||||
|
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
|
||||||
|
dut.expect_exact(f'Detected in task "HWSG{cpu}"')
|
||||||
|
addr = dut.expect('at 0x([0-9a-fA-F]{8})')
|
||||||
|
assert addr.group(1) != b'00000000'
|
||||||
|
addr = dut.expect('Stack pointer: 0x([0-9a-fA-F]{8})')
|
||||||
|
assert addr.group(1) != b'00000000'
|
||||||
|
addr = dut.expect(r'Stack bounds: 0x([0-9a-fA-F]{8})')
|
||||||
|
assert addr.group(1) != b'00000000'
|
||||||
|
start_addr = int(addr.group(1), 16)
|
||||||
|
addr = dut.expect(r' - 0x([0-9a-fA-F]{8})')
|
||||||
|
assert addr.group(1) != b'00000000'
|
||||||
|
end_addr = int(addr.group(1), 16)
|
||||||
|
assert end_addr > start_addr
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True)
|
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True)
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None:
|
def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None:
|
||||||
dut.run_test_func(test_func_name)
|
dut.run_test_func(test_func_name)
|
||||||
dut.expect_exact('Guru Meditation Error: Core 0 panic\'ed (Stack protection fault).')
|
test_hw_stack_guard_cpu(dut, 0)
|
||||||
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
|
common_test(dut, config)
|
||||||
dut.expect(r'Detected in task(.*)at 0x')
|
|
||||||
dut.expect_exact('Stack pointer: 0x')
|
|
||||||
dut.expect(r'Stack bounds: 0x(.*) - 0x')
|
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True)
|
||||||
|
@pytest.mark.generic
|
||||||
|
def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None:
|
||||||
|
dut.run_test_func(test_func_name)
|
||||||
|
test_hw_stack_guard_cpu(dut, 1)
|
||||||
common_test(dut, config)
|
common_test(dut, config)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, Dict, List, Optional, TextIO, Union
|
from typing import Any
|
||||||
|
from typing import Dict
|
||||||
|
from typing import List
|
||||||
|
from typing import Optional
|
||||||
|
from typing import TextIO
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import pexpect
|
import pexpect
|
||||||
from panic_utils import NoGdbProcessError, attach_logger, quote_string, sha256, verify_valid_gdb_subprocess
|
from panic_utils import attach_logger
|
||||||
|
from panic_utils import NoGdbProcessError
|
||||||
|
from panic_utils import quote_string
|
||||||
|
from panic_utils import sha256
|
||||||
|
from panic_utils import verify_valid_gdb_subprocess
|
||||||
from pygdbmi.gdbcontroller import GdbController
|
from pygdbmi.gdbcontroller import GdbController
|
||||||
from pytest_embedded_idf.app import IdfApp
|
from pytest_embedded_idf.app import IdfApp
|
||||||
from pytest_embedded_idf.dut import IdfDut
|
from pytest_embedded_idf.dut import IdfDut
|
||||||
|
@ -53,7 +62,7 @@ class PanicTestDut(IdfDut):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_multi_core(self) -> bool:
|
def is_multi_core(self) -> bool:
|
||||||
return self.target in ['esp32', 'esp32s3']
|
return self.target in ['esp32', 'esp32s3', 'esp32p4']
|
||||||
|
|
||||||
def run_test_func(self, test_func_name: str) -> None:
|
def run_test_func(self, test_func_name: str) -> None:
|
||||||
self.expect_exact('Enter test name:')
|
self.expect_exact('Enter test name:')
|
||||||
|
|
Ładowanie…
Reference in New Issue