mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'feature/update_gdbstub_v6.0' into 'release/v6.0'
gdbstub: backport fixes (v6.0) See merge request espressif/esp-idf!46200
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
set(srcs "test_app_main.c")
|
||||
if(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
if(CONFIG_SOC_CPU_HAS_HWLOOP)
|
||||
if(CONFIG_SOC_CPU_HAS_HWLOOP)
|
||||
list(APPEND srcs "xesppie_loops.S")
|
||||
endif()
|
||||
if(CONFIG_SOC_CPU_HAS_FPU OR CONFIG_SOC_CPU_HAS_PIE)
|
||||
endif()
|
||||
if(CONFIG_SOC_CPU_HAS_FPU OR CONFIG_SOC_CPU_HAS_PIE)
|
||||
list(APPEND srcs "coproc_regs.c")
|
||||
endif()
|
||||
if(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
set(ext_comp "riscv")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#if CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
#include "riscv/rvruntime-frames.h"
|
||||
#endif
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
static SemaphoreHandle_t sem = NULL;
|
||||
@@ -74,13 +76,27 @@ pie_start:
|
||||
#if SOC_CPU_HAS_FPU
|
||||
static void test_fpu(void * arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
struct {
|
||||
float f[16];
|
||||
} fpu_regs_sample, fpu_regs;
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
RvFPUSaveArea fpu_regs_sample, fpu_regs;
|
||||
|
||||
#endif
|
||||
uint32_t *ptr = (uint32_t *)&fpu_regs_sample;
|
||||
for (int i = 0; i < sizeof(fpu_regs_sample)/sizeof(uint32_t); i++) {
|
||||
ptr[i] = i + (uintptr_t) arg;
|
||||
ptr[i] = i + (int) arg;
|
||||
}
|
||||
|
||||
/* Set FPU owner to current task by calling an instruction */
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
__asm__ volatile ("ssi f0, %0, 0" :: "a" (&fpu_regs));
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
__asm__ volatile ("fsw ft0, %0" : "=m" (fpu_regs.ft0));
|
||||
#endif
|
||||
|
||||
fpu_start:
|
||||
asm volatile ("nop");
|
||||
|
||||
@@ -88,6 +104,25 @@ fpu_start:
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
__asm__ volatile ("ssi f0, %0, 0" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f1, %0, 4" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f2, %0, 8" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f3, %0, 12" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f4, %0, 16" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f5, %0, 20" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f6, %0, 24" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f7, %0, 28" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f8, %0, 32" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f9, %0, 36" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f10, %0, 40" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f11, %0, 44" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f12, %0, 48" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f13, %0, 52" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f14, %0, 56" :: "a" (&fpu_regs));
|
||||
__asm__ volatile ("ssi f15, %0, 60" :: "a" (&fpu_regs));
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
__asm__ volatile ("fsw ft0, %0" : "=m" (fpu_regs.ft0));
|
||||
__asm__ volatile ("fsw ft1, %0" : "=m" (fpu_regs.ft1));
|
||||
__asm__ volatile ("fsw ft2, %0" : "=m" (fpu_regs.ft2));
|
||||
@@ -121,6 +156,7 @@ fpu_start:
|
||||
__asm__ volatile ("fsw ft10, %0" : "=m" (fpu_regs.ft10));
|
||||
__asm__ volatile ("fsw ft11, %0" : "=m" (fpu_regs.ft11));
|
||||
__asm__ volatile ("csrr %0, fcsr" : "=r" (fpu_regs.fcsr));
|
||||
#endif
|
||||
|
||||
if (!memcmp(&fpu_regs_sample, &fpu_regs, sizeof(fpu_regs))) {
|
||||
xSemaphoreGive((SemaphoreHandle_t) sem);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define TEST_COPROCESSOR_REGISTERS (__riscv && (SOC_CPU_HAS_FPU || SOC_CPU_HAS_PIE))
|
||||
#define TEST_COPROCESSOR_REGISTERS (SOC_CPU_HAS_FPU || SOC_CPU_HAS_PIE)
|
||||
#define TEST_HWLOOP_INSTRUCTIONS (__riscv && SOC_CPU_HAS_HWLOOP)
|
||||
|
||||
int var_1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import os
|
||||
import os.path as path
|
||||
@@ -147,7 +147,7 @@ def check_registers_numbers(dut: PanicTestDut) -> None:
|
||||
r_id += 1
|
||||
|
||||
|
||||
def set_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
def set_riscv_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
cmd = f'-thread-select {t_id}'
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
@@ -157,13 +157,39 @@ def set_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
|
||||
# Note that it's a gap between the last floating register number and fcsr register number.
|
||||
cmd = f'-data-write-register-values d 68 {32 + addition}'
|
||||
# Note that it's a gap between the last floating register number and fcsr register number.
|
||||
cmd = f'-data-write-register-values d 68 {32 + addition}'
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
|
||||
|
||||
def set_xtensa_float_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
"""Set Xtensa FPU registers via GDB.
|
||||
|
||||
Xtensa FPU register numbers:
|
||||
- f0-f15: registers 87-102
|
||||
- fcr: register 103
|
||||
- fsr: register 104
|
||||
"""
|
||||
cmd = f'-thread-select {t_id}'
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
|
||||
if dut.target == 'esp32':
|
||||
fpu_current_register = 87
|
||||
elif dut.target == 'esp32s3':
|
||||
fpu_current_register = 84
|
||||
else:
|
||||
raise ValueError(f'Unsupported target: {dut.target}')
|
||||
|
||||
for i in range(18): # 16 f* registers + fcr + fsr
|
||||
cmd = f'-data-write-register-values d {fpu_current_register} {i + addition}'
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
fpu_current_register += 1
|
||||
|
||||
|
||||
def set_pie_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
def set_riscv_pie_registers(dut: PanicTestDut, t_id: int, addition: int) -> None:
|
||||
cmd = f'-thread-select {t_id}'
|
||||
responses = dut.gdb_write(cmd)
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
@@ -212,15 +238,14 @@ def coproc_registers_test(dut: PanicTestDut, regs_type: str, set_registers: Call
|
||||
- Task coproc owner (direct registers write)
|
||||
- Other tasks (write registers to task's stack)
|
||||
"""
|
||||
coproc_tasks = [f'test_{regs_type}_1', f'test_{regs_type}_2']
|
||||
found_tasks = [False] * len(coproc_tasks)
|
||||
found_count = 0
|
||||
for t in threads:
|
||||
for index, test in enumerate(coproc_tasks):
|
||||
if test in t['details']:
|
||||
set_registers(dut, t['id'], index + 1)
|
||||
found_tasks[index] = True
|
||||
for task_num in [1, 2]:
|
||||
if f'test_{regs_type}_{task_num}' in t['details']:
|
||||
set_registers(dut, t['id'], task_num)
|
||||
found_count += 1
|
||||
|
||||
assert all(found_tasks)
|
||||
assert found_count == 2, f'Expected 2 coproc tasks, found {found_count}'
|
||||
|
||||
dut_set_variable(dut, f'test_{regs_type}_ready', 1)
|
||||
|
||||
@@ -240,28 +265,30 @@ def coproc_registers_test(dut: PanicTestDut, regs_type: str, set_registers: Call
|
||||
|
||||
threads = dut_get_threads(dut)
|
||||
|
||||
found_tasks = [False] * len(coproc_tasks)
|
||||
found_count = 0
|
||||
for t in threads:
|
||||
for index, test in enumerate(coproc_tasks):
|
||||
if test in t['details']:
|
||||
found_tasks[index] = True
|
||||
for task_num in [1, 2]:
|
||||
if f'test_{regs_type}_{task_num}' in t['details']:
|
||||
found_count += 1
|
||||
|
||||
assert not any(found_tasks)
|
||||
assert found_count == 0, f'Expected 0 coproc tasks, found {found_count}'
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
||||
@idf_parametrize('target', ['esp32', 'esp32s3', 'esp32p4'], indirect=['target'])
|
||||
def test_coproc_registers(dut: PanicTestDut) -> None:
|
||||
start_gdb(dut)
|
||||
|
||||
# enable coprocessors registers testing
|
||||
dut_enable_test(dut, 'coproc_regs')
|
||||
|
||||
check_registers_numbers(dut)
|
||||
|
||||
coproc_registers_test(dut, 'fpu', set_float_registers)
|
||||
if dut.target == 'esp32p4':
|
||||
coproc_registers_test(dut, 'pie', set_pie_registers)
|
||||
if dut.is_xtensa:
|
||||
coproc_registers_test(dut, 'fpu', set_xtensa_float_registers)
|
||||
else:
|
||||
check_registers_numbers(dut)
|
||||
coproc_registers_test(dut, 'fpu', set_riscv_float_registers)
|
||||
if dut.target == 'esp32p4':
|
||||
coproc_registers_test(dut, 'pie', set_riscv_pie_registers)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -341,14 +368,11 @@ def test_gdbstub_runtime(dut: PanicTestDut) -> None:
|
||||
assert dut.find_gdb_response('done', 'result', responses) is not None
|
||||
cmd = '-exec-continue'
|
||||
payload = run_and_break(dut, cmd)
|
||||
assert payload['reason'] == 'signal-received'
|
||||
assert payload['reason'] == 'watchpoint-trigger'
|
||||
assert int(payload['value']['new']) == int(payload['value']['old']) + 2
|
||||
assert payload['frame']['func'] == 'foo'
|
||||
assert payload['frame']['line'] == str(get_line_number('var_2--;'))
|
||||
assert payload['stopped-threads'] == 'all'
|
||||
# Uncomment this when implement send reason to gdb: GCC-313
|
||||
#
|
||||
# assert payload['reason'] == 'watchpoint-trigger'
|
||||
# assert int(payload['value']['new']) == int(payload['value']['old']) + 1
|
||||
# assert payload['frame']['line'] == '14'
|
||||
|
||||
cmd = '-break-delete 2'
|
||||
responses = dut.gdb_write(cmd)
|
||||
|
||||
Reference in New Issue
Block a user