mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
This commit add to GDBstup:
1. Multicore suupor 2. Stepping 3. Console output 4. Update example + readme 5. Jumps
This commit is contained in:
@ -6,13 +6,14 @@ idf_component_register(SRCS "src/gdbstub.c" "src/packet.c"
|
|||||||
PRIV_INCLUDE_DIRS "private_include"
|
PRIV_INCLUDE_DIRS "private_include"
|
||||||
LDFRAGMENTS "linker.lf"
|
LDFRAGMENTS "linker.lf"
|
||||||
REQUIRES "freertos"
|
REQUIRES "freertos"
|
||||||
PRIV_REQUIRES "soc" "esp_rom")
|
PRIV_REQUIRES "soc" "esp_rom" "esp_system")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||||
target_include_directories(${COMPONENT_LIB} PUBLIC "xtensa" "${target}")
|
target_include_directories(${COMPONENT_LIB} PUBLIC "xtensa" "${target}")
|
||||||
target_sources(${COMPONENT_LIB} PRIVATE "xtensa/gdbstub_xtensa.c"
|
target_sources(${COMPONENT_LIB} PRIVATE "xtensa/gdbstub_xtensa.c"
|
||||||
"xtensa/gdbstub-entry.S"
|
"xtensa/gdbstub-entry.S"
|
||||||
|
"xtensa/xt_debugexception.S"
|
||||||
"esp_common/gdbstub_common.c")
|
"esp_common/gdbstub_common.c")
|
||||||
|
|
||||||
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "soc/uart_periph.h"
|
#include "soc/uart_periph.h"
|
||||||
#include "soc/gpio_periph.h"
|
#include "soc/gpio_periph.h"
|
||||||
#include "esp_gdbstub_common.h"
|
#include "esp_gdbstub_common.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "hal/uart_ll.h"
|
#include "hal/uart_ll.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "xtensa/config/specreg.h"
|
||||||
|
|
||||||
#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
|
#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
|
||||||
|
|
||||||
@ -70,7 +64,10 @@ void esp_gdbstub_putchar(int c)
|
|||||||
|
|
||||||
void esp_gdbstub_flush()
|
void esp_gdbstub_flush()
|
||||||
{
|
{
|
||||||
//not needed for uart
|
// wait until some data in transmition
|
||||||
|
while (false == uart_ll_is_tx_idle(gdb_uart))
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int esp_gdbstub_getfifo()
|
int esp_gdbstub_getfifo()
|
||||||
@ -87,9 +84,6 @@ int esp_gdbstub_getfifo()
|
|||||||
if (data == 0x3) {
|
if (data == 0x3) {
|
||||||
doDebug = 1; //Check if any of the chars is Ctrl+C. Throw away rest.
|
doDebug = 1; //Check if any of the chars is Ctrl+C. Throw away rest.
|
||||||
}
|
}
|
||||||
if (data == '+') {
|
|
||||||
doDebug = 1; //Check if any of the chars is '+'. Throw away rest.
|
|
||||||
}
|
|
||||||
fifolen--;
|
fifolen--;
|
||||||
}
|
}
|
||||||
uart_ll_clr_intsts_mask(gdb_uart, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
|
uart_ll_clr_intsts_mask(gdb_uart, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -20,6 +12,7 @@ extern "C" {
|
|||||||
|
|
||||||
void esp_gdbstub_init(void);
|
void esp_gdbstub_init(void);
|
||||||
void esp_gdbstub_panic_handler(void *frame);
|
void esp_gdbstub_panic_handler(void *frame);
|
||||||
|
void update_breakpoints(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -68,7 +60,7 @@ typedef struct {
|
|||||||
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
} esp_gdbstub_scratch_t;
|
} esp_gdbstub_scratch_t;
|
||||||
|
|
||||||
|
extern esp_gdbstub_scratch_t s_scratch;
|
||||||
/**** Functions provided by the architecture specific part ****/
|
/**** Functions provided by the architecture specific part ****/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,3 +162,19 @@ int esp_gdbstub_read_command(unsigned char **out_cmd, size_t *out_size);
|
|||||||
|
|
||||||
/** Handle a command received from gdb */
|
/** Handle a command received from gdb */
|
||||||
int esp_gdbstub_handle_command(unsigned char *cmd, int len);
|
int esp_gdbstub_handle_command(unsigned char *cmd, int len);
|
||||||
|
|
||||||
|
void esp_gdbstub_init_dports(void);
|
||||||
|
void esp_gdbstub_stall_other_cpus_start(void);
|
||||||
|
void esp_gdbstub_stall_other_cpus_end(void);
|
||||||
|
|
||||||
|
void esp_gdbstub_clear_step(void);
|
||||||
|
void esp_gdbstub_do_step(void);
|
||||||
|
void esp_gdbstub_trigger_cpu(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a value to register in frame
|
||||||
|
* @param frame gdbstub frame
|
||||||
|
* @param reg_index register index, depends on architecture
|
||||||
|
* @param value 32 bit data value
|
||||||
|
*/
|
||||||
|
void esp_gdbstub_set_register(esp_gdbstub_frame_t *frame, uint32_t reg_index, uint32_t value);
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -29,6 +21,17 @@ typedef struct {
|
|||||||
uint32_t pc;
|
uint32_t pc;
|
||||||
} esp_gdbstub_gdb_regfile_t;
|
} esp_gdbstub_gdb_regfile_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Amount of HW breakpoints used in GDB
|
||||||
|
#ifndef GDB_BP_SIZE
|
||||||
|
#define GDB_BP_SIZE 2
|
||||||
|
#endif // GDB_BP_SIZE
|
||||||
|
|
||||||
|
// Amount of HW watchpoints used in GDB
|
||||||
|
#ifndef GDB_WP_SIZE
|
||||||
|
#define GDB_WP_SIZE 2
|
||||||
|
#endif // GDB_WP_SIZE
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -47,10 +47,37 @@ void esp_gdbstub_tcb_to_regfile(TaskHandle_t tcb, esp_gdbstub_gdb_regfile_t *dst
|
|||||||
|
|
||||||
int esp_gdbstub_get_signal(const esp_gdbstub_frame_t *frame)
|
int esp_gdbstub_get_signal(const esp_gdbstub_frame_t *frame)
|
||||||
{
|
{
|
||||||
return 5; // SIGTRAP, see IDF-2490
|
return 5; // SIGTRAP, see IDF-2490
|
||||||
}
|
}
|
||||||
|
|
||||||
void _xt_gdbstub_int(void * frame)
|
void _xt_gdbstub_int(void *frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_init_dports()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_stall_other_cpus_start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_stall_other_cpus_end()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_clear_step()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_do_step()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_trigger_cpu(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_set_register(esp_gdbstub_frame_t *frame, uint32_t reg_index, uint32_t value)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,17 @@
|
|||||||
#include "esp_gdbstub.h"
|
#include "esp_gdbstub.h"
|
||||||
#include "esp_gdbstub_common.h"
|
#include "esp_gdbstub_common.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include "soc/uart_reg.h"
|
#include "soc/uart_reg.h"
|
||||||
#include "soc/periph_defs.h"
|
#include "soc/periph_defs.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "hal/wdt_hal.h"
|
#include "hal/wdt_hal.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
static inline int gdb_tid_to_task_index(int tid);
|
static inline int gdb_tid_to_task_index(int tid);
|
||||||
static inline int task_index_to_gdb_tid(int tid);
|
static inline int task_index_to_gdb_tid(int tid);
|
||||||
@ -28,10 +29,19 @@ static int handle_task_commands(unsigned char *cmd, int len);
|
|||||||
static void esp_gdbstub_send_str_as_hex(const char *str);
|
static void esp_gdbstub_send_str_as_hex(const char *str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void send_reason(void);
|
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
static void handle_qSupported_command(const unsigned char *cmd, int len);
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
|
||||||
static esp_gdbstub_scratch_t s_scratch;
|
#if (CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS)
|
||||||
static esp_gdbstub_gdb_regfile_t *gdb_local_regfile = &s_scratch.regfile;
|
static bool command_name_matches(const char *pattern, const unsigned char *ucmd, int len);
|
||||||
|
#endif // (CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS)
|
||||||
|
|
||||||
|
static void send_reason(void);
|
||||||
|
static char gdb_packet(char *dest_buff, char *src_buff, int len);
|
||||||
|
|
||||||
|
esp_gdbstub_scratch_t s_scratch;
|
||||||
|
esp_gdbstub_gdb_regfile_t *gdb_local_regfile = &s_scratch.regfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief panic handler
|
* @brief panic handler
|
||||||
@ -60,7 +70,7 @@ void esp_gdbstub_panic_handler(void *in_frame)
|
|||||||
set_active_task(s_scratch.paniced_task_index);
|
set_active_task(s_scratch.paniced_task_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#endif /* CONFIG_ESP_GDBSTUB_SUPPORT_TASKS */
|
||||||
|
|
||||||
esp_gdbstub_target_init();
|
esp_gdbstub_target_init();
|
||||||
s_scratch.signal = esp_gdbstub_get_signal(frame);
|
s_scratch.signal = esp_gdbstub_get_signal(frame);
|
||||||
@ -119,7 +129,7 @@ static inline void disable_all_wdts(void)
|
|||||||
wdt1_context_enabled = wdt_hal_is_enabled(&wdt1_context);
|
wdt1_context_enabled = wdt_hal_is_enabled(&wdt1_context);
|
||||||
rtc_wdt_ctx_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx);
|
rtc_wdt_ctx_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx);
|
||||||
|
|
||||||
//Task WDT is the Main Watchdog Timer of Timer Group 0
|
/*Task WDT is the Main Watchdog Timer of Timer Group 0 */
|
||||||
if (true == wdt0_context_enabled) {
|
if (true == wdt0_context_enabled) {
|
||||||
wdt_hal_write_protect_disable(&wdt0_context);
|
wdt_hal_write_protect_disable(&wdt0_context);
|
||||||
wdt_hal_disable(&wdt0_context);
|
wdt_hal_disable(&wdt0_context);
|
||||||
@ -127,7 +137,7 @@ static inline void disable_all_wdts(void)
|
|||||||
wdt_hal_write_protect_enable(&wdt0_context);
|
wdt_hal_write_protect_enable(&wdt0_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Interupt WDT is the Main Watchdog Timer of Timer Group 1
|
/* Interupt WDT is the Main Watchdog Timer of Timer Group 1 */
|
||||||
if (true == wdt1_context_enabled) {
|
if (true == wdt1_context_enabled) {
|
||||||
wdt_hal_write_protect_disable(&wdt1_context);
|
wdt_hal_write_protect_disable(&wdt1_context);
|
||||||
wdt_hal_disable(&wdt1_context);
|
wdt_hal_disable(&wdt1_context);
|
||||||
@ -147,13 +157,13 @@ static inline void disable_all_wdts(void)
|
|||||||
*/
|
*/
|
||||||
static inline void enable_all_wdts(void)
|
static inline void enable_all_wdts(void)
|
||||||
{
|
{
|
||||||
//Task WDT is the Main Watchdog Timer of Timer Group 0
|
/* Task WDT is the Main Watchdog Timer of Timer Group 0 */
|
||||||
if (false == wdt0_context_enabled) {
|
if (false == wdt0_context_enabled) {
|
||||||
wdt_hal_write_protect_disable(&wdt0_context);
|
wdt_hal_write_protect_disable(&wdt0_context);
|
||||||
wdt_hal_enable(&wdt0_context);
|
wdt_hal_enable(&wdt0_context);
|
||||||
wdt_hal_write_protect_enable(&wdt0_context);
|
wdt_hal_write_protect_enable(&wdt0_context);
|
||||||
}
|
}
|
||||||
// Interupt WDT is the Main Watchdog Timer of Timer Group 1
|
/* Interupt WDT is the Main Watchdog Timer of Timer Group 1 */
|
||||||
if (false == wdt1_context_enabled) {
|
if (false == wdt1_context_enabled) {
|
||||||
wdt_hal_write_protect_disable(&wdt1_context);
|
wdt_hal_write_protect_disable(&wdt1_context);
|
||||||
wdt_hal_enable(&wdt1_context);
|
wdt_hal_enable(&wdt1_context);
|
||||||
@ -177,18 +187,50 @@ static inline void enable_all_wdts(void)
|
|||||||
* @param curr_regs - actual registers frame
|
* @param curr_regs - actual registers frame
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
static int bp_count = 0;
|
||||||
|
static int wp_count = 0;
|
||||||
|
static uint32_t bp_list[GDB_BP_SIZE] = {0};
|
||||||
|
static uint32_t wp_list[GDB_WP_SIZE] = {0};
|
||||||
|
static uint32_t wp_size[GDB_WP_SIZE] = {0};
|
||||||
|
static watchpoint_trigger_t wp_access[GDB_WP_SIZE] = {0};
|
||||||
|
|
||||||
|
static volatile bool step_in_progress = false;
|
||||||
|
static bool not_send_reason = false;
|
||||||
|
static bool process_gdb_kill = false;
|
||||||
|
static bool gdb_debug_int = false;
|
||||||
|
int getActiveTaskNum(void);
|
||||||
|
int __swrite(struct _reent *, void *, const char *, int);
|
||||||
|
int gdbstub__swrite(struct _reent *data1, void *data2, const char *buff, int len);
|
||||||
|
|
||||||
|
volatile esp_gdbstub_frame_t *temp_regs_frame;
|
||||||
|
|
||||||
void gdbstub_handle_uart_int(esp_gdbstub_frame_t *regs_frame)
|
void gdbstub_handle_uart_int(esp_gdbstub_frame_t *regs_frame)
|
||||||
{
|
{
|
||||||
// Disable all enabled WDT on enter
|
temp_regs_frame = regs_frame;
|
||||||
|
not_send_reason = step_in_progress;
|
||||||
|
if (step_in_progress == true) {
|
||||||
|
esp_gdbstub_send_str_packet("S05");
|
||||||
|
step_in_progress = false;
|
||||||
|
}
|
||||||
|
// process_gdb_kill = false;
|
||||||
|
bp_count = 0;
|
||||||
|
wp_count = 0;
|
||||||
|
/* Disable all enabled WDT on enter */
|
||||||
disable_all_wdts();
|
disable_all_wdts();
|
||||||
|
|
||||||
int doDebug = esp_gdbstub_getfifo();
|
int doDebug = esp_gdbstub_getfifo();
|
||||||
s_scratch.signal = esp_gdbstub_get_signal(regs_frame);
|
s_scratch.signal = esp_gdbstub_get_signal(regs_frame);
|
||||||
|
|
||||||
if (doDebug) {
|
if (doDebug) {
|
||||||
|
process_gdb_kill = false;
|
||||||
|
/* To enable console output in GDB, we replace the default stdout->_write function */
|
||||||
|
stdout->_write = gdbstub__swrite;
|
||||||
|
stderr->_write = gdbstub__swrite;
|
||||||
|
/* Stall other core until GDB exit */
|
||||||
|
esp_gdbstub_stall_other_cpus_start();
|
||||||
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
init_task_info();
|
init_task_info();
|
||||||
#endif// CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#endif/* CONFIG_ESP_GDBSTUB_SUPPORT_TASKS */
|
||||||
esp_gdbstub_frame_to_regfile(regs_frame, gdb_local_regfile);
|
esp_gdbstub_frame_to_regfile(regs_frame, gdb_local_regfile);
|
||||||
send_reason();
|
send_reason();
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -216,9 +258,92 @@ void gdbstub_handle_uart_int(esp_gdbstub_frame_t *regs_frame)
|
|||||||
if (res == GDBSTUB_ST_CONT) {
|
if (res == GDBSTUB_ST_CONT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
#endif /* CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME */
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Resume other core */
|
||||||
|
if (step_in_progress == false) {
|
||||||
|
esp_gdbstub_stall_other_cpus_end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
esp_gdbstub_getfifo();
|
||||||
|
/* This is workaround for problem with 'next' command. */
|
||||||
|
if (process_gdb_kill == false) {
|
||||||
|
esp_gdbstub_send_str("OK");
|
||||||
|
} else {
|
||||||
|
/* We flush all data before exit from GDB.*/
|
||||||
|
esp_gdbstub_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdbstub_handle_debug_int(esp_gdbstub_frame_t *regs_frame)
|
||||||
|
{
|
||||||
|
bp_count = 0;
|
||||||
|
wp_count = 0;
|
||||||
|
temp_regs_frame = regs_frame;
|
||||||
|
gdb_debug_int = true;
|
||||||
|
not_send_reason = step_in_progress;
|
||||||
|
if (step_in_progress == true) {
|
||||||
|
esp_gdbstub_clear_step();
|
||||||
|
esp_gdbstub_send_str_packet("S05");
|
||||||
|
step_in_progress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int doDebug = esp_gdbstub_getfifo();
|
||||||
|
s_scratch.signal = 5; /* esp_gdbstub_get_db_signal(regs_frame); */
|
||||||
|
|
||||||
|
doDebug = 1;
|
||||||
|
if (doDebug) {
|
||||||
|
#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
|
s_scratch.current_task_index = getActiveTaskNum();
|
||||||
|
#endif
|
||||||
|
process_gdb_kill = false;
|
||||||
|
/* Stall other core until GDB exit */
|
||||||
|
esp_gdbstub_stall_other_cpus_start();
|
||||||
|
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
|
init_task_info();
|
||||||
|
#endif/* CONFIG_ESP_GDBSTUB_SUPPORT_TASKS */
|
||||||
|
esp_gdbstub_frame_to_regfile(regs_frame, gdb_local_regfile);
|
||||||
|
send_reason();
|
||||||
|
while (true) {
|
||||||
|
unsigned char *cmd;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
int res = esp_gdbstub_read_command(&cmd, &size);
|
||||||
|
if (res == '-') {
|
||||||
|
send_reason();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (res > 0) {
|
||||||
|
/* character received instead of a command */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (res == -2) {
|
||||||
|
esp_gdbstub_send_str_packet("E01");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = esp_gdbstub_handle_command(cmd, size);
|
||||||
|
if (res == -2) {
|
||||||
|
esp_gdbstub_send_str_packet(NULL);
|
||||||
|
}
|
||||||
|
if (res == GDBSTUB_ST_CONT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* Resume other core */
|
||||||
|
if (step_in_progress == false) {
|
||||||
|
esp_gdbstub_stall_other_cpus_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esp_gdbstub_getfifo();
|
||||||
|
if (process_gdb_kill == true) {
|
||||||
|
/* We flush all data before exit from GDB.*/
|
||||||
|
esp_gdbstub_flush();
|
||||||
|
}
|
||||||
|
gdb_debug_int = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
intr_handle_t intr_handle_;
|
intr_handle_t intr_handle_;
|
||||||
@ -231,8 +356,9 @@ extern void _xt_gdbstub_int(void * );
|
|||||||
void esp_gdbstub_init(void)
|
void esp_gdbstub_init(void)
|
||||||
{
|
{
|
||||||
esp_intr_alloc(ETS_UART0_INTR_SOURCE, 0, _xt_gdbstub_int, NULL, &intr_handle_);
|
esp_intr_alloc(ETS_UART0_INTR_SOURCE, 0, _xt_gdbstub_int, NULL, &intr_handle_);
|
||||||
|
esp_gdbstub_init_dports();
|
||||||
}
|
}
|
||||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
#endif /* CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME */
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
|
|
||||||
@ -291,9 +417,9 @@ static void handle_m_command(const unsigned char *cmd, int len)
|
|||||||
static void handle_M_command(const unsigned char *cmd, int len)
|
static void handle_M_command(const unsigned char *cmd, int len)
|
||||||
{
|
{
|
||||||
intptr_t addr = (intptr_t) esp_gdbstub_gethex(&cmd, -1);
|
intptr_t addr = (intptr_t) esp_gdbstub_gethex(&cmd, -1);
|
||||||
cmd++; // skip '.'
|
cmd++; /* skip '.' */
|
||||||
uint32_t size = esp_gdbstub_gethex(&cmd, -1);
|
uint32_t size = esp_gdbstub_gethex(&cmd, -1);
|
||||||
cmd++; // skip ':'
|
cmd++; /* skip ':' */
|
||||||
|
|
||||||
if (esp_gdbstub_readmem(addr) < 0 || esp_gdbstub_readmem(addr + size - 1) < 0) {
|
if (esp_gdbstub_readmem(addr) < 0 || esp_gdbstub_readmem(addr + size - 1) < 0) {
|
||||||
esp_gdbstub_send_str_packet("E01");
|
esp_gdbstub_send_str_packet("E01");
|
||||||
@ -308,6 +434,210 @@ static void handle_M_command(const unsigned char *cmd, int len)
|
|||||||
esp_gdbstub_send_end();
|
esp_gdbstub_send_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_breakpoints(void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < GDB_BP_SIZE; i++) {
|
||||||
|
if (bp_list[i] != 0) {
|
||||||
|
cpu_ll_set_breakpoint(i, (uint32_t)bp_list[i]);
|
||||||
|
} else {
|
||||||
|
cpu_hal_clear_breakpoint(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < GDB_WP_SIZE; i++) {
|
||||||
|
if (wp_list[i] != 0) {
|
||||||
|
cpu_hal_set_watchpoint(i, (void *)wp_list[i], wp_size[i], wp_access[i]);
|
||||||
|
} else {
|
||||||
|
cpu_hal_clear_watchpoint(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
/** Write breakpoint */
|
||||||
|
static void handle_Z0_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'Z' */
|
||||||
|
cmd++; /* skip '0' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
if (bp_count >= GDB_BP_SIZE) {
|
||||||
|
esp_gdbstub_send_str_packet("E02");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool add_bp = true;
|
||||||
|
/* Check if bp already exist */
|
||||||
|
for (size_t i = 0; i < GDB_BP_SIZE; i++) {
|
||||||
|
if (bp_list[i] == addr) {
|
||||||
|
add_bp = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (true == add_bp) {
|
||||||
|
for (size_t i = 0; i < GDB_BP_SIZE; i++) {
|
||||||
|
if (bp_list[i] == 0) {
|
||||||
|
bp_list[i] = (uint32_t)addr;
|
||||||
|
bp_count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clear breakpoint */
|
||||||
|
static void handle_z0_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'z' */
|
||||||
|
cmd++; /* skip '0' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
for (size_t i = 0; i < GDB_BP_SIZE; i++) {
|
||||||
|
if (bp_list[i] == addr) {
|
||||||
|
bp_list[i] = 0;
|
||||||
|
bp_count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
/** Write watchpoints write*/
|
||||||
|
static void handle_Z2_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'Z' */
|
||||||
|
cmd++; /* skip '2' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
cmd++;
|
||||||
|
uint32_t size = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
|
||||||
|
if (wp_count >= GDB_WP_SIZE) {
|
||||||
|
esp_gdbstub_send_str_packet("E02");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wp_access[wp_count] = WATCHPOINT_TRIGGER_ON_WO;
|
||||||
|
wp_size[wp_count] = size;
|
||||||
|
wp_list[wp_count++] = (uint32_t)addr;
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
/** Write watchpoints read*/
|
||||||
|
static void handle_Z3_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'Z' */
|
||||||
|
cmd++; /* skip '3' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
cmd++;
|
||||||
|
uint32_t size = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
if (wp_count >= GDB_WP_SIZE) {
|
||||||
|
esp_gdbstub_send_str_packet("E02");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wp_access[wp_count] = WATCHPOINT_TRIGGER_ON_RO;
|
||||||
|
wp_size[wp_count] = size;
|
||||||
|
wp_list[wp_count++] = (uint32_t)addr;
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
/** Write watchpoints access*/
|
||||||
|
static void handle_Z4_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'Z' */
|
||||||
|
cmd++; /* skip '4' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
cmd++;
|
||||||
|
uint32_t size = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
if (wp_count >= GDB_WP_SIZE) {
|
||||||
|
esp_gdbstub_send_str_packet("E02");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wp_access[wp_count] = WATCHPOINT_TRIGGER_ON_RW;
|
||||||
|
wp_size[wp_count] = size;
|
||||||
|
wp_list[wp_count++] = (uint32_t)addr;
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
/** Clear watchpoint */
|
||||||
|
static void handle_zx_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
cmd++; /* skip 'z' */
|
||||||
|
cmd++; /* skip 'x' */
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
for (size_t i = 0; i < GDB_WP_SIZE; i++) {
|
||||||
|
if (wp_list[i] == addr) {
|
||||||
|
wp_access[i] = 0;
|
||||||
|
wp_list[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_breakpoints();
|
||||||
|
esp_gdbstub_trigger_cpu();
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Step ... */
|
||||||
|
static void handle_S_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
esp_gdbstub_send_str_packet("S05");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Step ... */
|
||||||
|
static void handle_s_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
step_in_progress = true;
|
||||||
|
esp_gdbstub_do_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Step ... */
|
||||||
|
static void handle_C_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set Register ... */
|
||||||
|
static void handle_P_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
uint32_t reg_index = 0;
|
||||||
|
if (cmd[1] == '=') {
|
||||||
|
reg_index = esp_gdbstub_gethex(&cmd, 4);
|
||||||
|
cmd++;
|
||||||
|
} else if (cmd[2] == '=') {
|
||||||
|
reg_index = esp_gdbstub_gethex(&cmd, 8);
|
||||||
|
cmd++;
|
||||||
|
cmd++;
|
||||||
|
} else {
|
||||||
|
esp_gdbstub_send_str_packet("E02");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t addr = esp_gdbstub_gethex(&cmd, -1);
|
||||||
|
/* The address comes with inverted byte order.*/
|
||||||
|
uint8_t *addr_ptr = (uint8_t *)&addr;
|
||||||
|
uint32_t p_address = 0;
|
||||||
|
uint8_t *p_addr_ptr = (uint8_t *)&p_address;
|
||||||
|
p_addr_ptr[3] = addr_ptr[0];
|
||||||
|
p_addr_ptr[2] = addr_ptr[1];
|
||||||
|
p_addr_ptr[1] = addr_ptr[2];
|
||||||
|
p_addr_ptr[0] = addr_ptr[3];
|
||||||
|
|
||||||
|
esp_gdbstub_set_register((esp_gdbstub_frame_t *)temp_regs_frame, reg_index, p_address);
|
||||||
|
/* Convert current regioster file to GDB*/
|
||||||
|
esp_gdbstub_frame_to_regfile((esp_gdbstub_frame_t *)temp_regs_frame, gdb_local_regfile);
|
||||||
|
/* Sen OK response*/
|
||||||
|
esp_gdbstub_send_str_packet("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** qSupported requests the communication with GUI
|
||||||
|
*/
|
||||||
|
static void handle_qSupported_command(const unsigned char *cmd, int len)
|
||||||
|
{
|
||||||
|
esp_gdbstub_send_start();
|
||||||
|
esp_gdbstub_send_str("qSupported:multiprocess+;swbreak-;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+");
|
||||||
|
esp_gdbstub_send_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
|
||||||
/** Handle a command received from gdb */
|
/** Handle a command received from gdb */
|
||||||
int esp_gdbstub_handle_command(unsigned char *cmd, int len)
|
int esp_gdbstub_handle_command(unsigned char *cmd, int len)
|
||||||
{
|
{
|
||||||
@ -326,21 +656,148 @@ int esp_gdbstub_handle_command(unsigned char *cmd, int len)
|
|||||||
} else if (cmd[0] == '?') {
|
} else if (cmd[0] == '?') {
|
||||||
/* Reply with stop reason */
|
/* Reply with stop reason */
|
||||||
send_reason();
|
send_reason();
|
||||||
|
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
} else if (cmd[0] == 'Z') {
|
||||||
|
if (cmd[1] == '0') {
|
||||||
|
/* Write breakpoint */
|
||||||
|
handle_Z0_command(data, len - 1);
|
||||||
|
}
|
||||||
|
if (cmd[1] == '2') {
|
||||||
|
/* Write breakpoint */
|
||||||
|
handle_Z2_command(data, len - 1);
|
||||||
|
}
|
||||||
|
if (cmd[1] == '3') {
|
||||||
|
/* Write breakpoint */
|
||||||
|
handle_Z3_command(data, len - 1);
|
||||||
|
}
|
||||||
|
if (cmd[1] == '4') {
|
||||||
|
/* Write breakpoint */
|
||||||
|
handle_Z4_command(data, len - 1);
|
||||||
|
}
|
||||||
|
} else if (cmd[0] == 'z') {
|
||||||
|
/* Clear breakpoint*/
|
||||||
|
if (cmd[1] == '0') {
|
||||||
|
handle_z0_command(data, len - 1);
|
||||||
|
}
|
||||||
|
/* Clear breakpoint*/
|
||||||
|
if ((cmd[1] == '2') || (cmd[1] == '3') || (cmd[1] == '4')) {
|
||||||
|
handle_zx_command(data, len - 1);
|
||||||
|
}
|
||||||
|
} else if (cmd[0] == 'S') {
|
||||||
|
/* Step */
|
||||||
|
handle_S_command(data, len - 1);
|
||||||
|
} else if (cmd[0] == 'k') {
|
||||||
|
/* Kill GDB and continue without */
|
||||||
|
/* By exit from GDB we have to replcae stdout->_write back */
|
||||||
|
stdout->_write = __swrite;
|
||||||
|
stderr->_write = __swrite;
|
||||||
|
process_gdb_kill = true;
|
||||||
|
return GDBSTUB_ST_CONT;
|
||||||
|
} else if (cmd[0] == 's') {
|
||||||
|
/* Step and continue*/
|
||||||
|
handle_s_command(data, len - 1);
|
||||||
|
return GDBSTUB_ST_CONT;
|
||||||
|
} else if (cmd[0] == 'C') {
|
||||||
|
/* Just continue*/
|
||||||
|
handle_C_command(data, len - 1);
|
||||||
|
size_t size;
|
||||||
|
esp_gdbstub_read_command(&cmd, &size);
|
||||||
|
return GDBSTUB_ST_CONT;
|
||||||
|
} else if (cmd[0] == 'P') {
|
||||||
|
handle_P_command(data, len - 1);
|
||||||
|
} else if (cmd[0] == 'c') { //continue execution
|
||||||
|
return GDBSTUB_ST_CONT;
|
||||||
|
} else if (command_name_matches("qSupported", cmd, 10)) {
|
||||||
|
handle_qSupported_command(cmd, len);
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#if CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
} else if (s_scratch.state != GDBSTUB_TASK_SUPPORT_DISABLED) {
|
} else if (s_scratch.state != GDBSTUB_TASK_SUPPORT_DISABLED) {
|
||||||
return handle_task_commands(cmd, len);
|
return handle_task_commands(cmd, len);
|
||||||
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
} else if (strncmp((char *)cmd, "vCont;c", 7) == 0 || cmd[0] == 'c') { //continue execution
|
|
||||||
return GDBSTUB_ST_CONT;
|
|
||||||
} else {
|
} else {
|
||||||
/* Unrecognized command */
|
/* Unrecognized command */
|
||||||
return GDBSTUB_ST_ERR;
|
return GDBSTUB_ST_ERR;
|
||||||
}
|
}
|
||||||
return GDBSTUB_ST_OK;
|
return GDBSTUB_ST_OK;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Replace standard __swrite function for GDB
|
||||||
|
*/
|
||||||
|
/* const int buff_len = 16; */
|
||||||
|
/* static char log_buffer[16*2 + 7]; */
|
||||||
|
int gdbstub__swrite(struct _reent *data1, void *data2, const char *buff, int len)
|
||||||
|
{
|
||||||
|
const int buff_len = 16;
|
||||||
|
char log_buffer[buff_len * 2 + 7];
|
||||||
|
char s_chsum = 'O';
|
||||||
|
char *sent_data = (char *)buff;
|
||||||
|
size_t remaining = len;
|
||||||
|
size_t send_pos = 0;
|
||||||
|
while (remaining > 0) {
|
||||||
|
size_t will_send = MIN(remaining, buff_len);
|
||||||
|
remaining -= will_send;
|
||||||
|
/* prepare and set 'will_send' number of bytes */
|
||||||
|
if (will_send > 0) {
|
||||||
|
log_buffer[0] = '$';
|
||||||
|
log_buffer[1] = 'O';
|
||||||
|
s_chsum = 'O';
|
||||||
|
s_chsum += gdb_packet(&log_buffer[2], &sent_data[send_pos], will_send);
|
||||||
|
sprintf(&log_buffer[will_send * 2 + 2], "#%2.2x\n", s_chsum);
|
||||||
|
__swrite(data1, data2, log_buffer, will_send * 2 + 6);
|
||||||
|
send_pos += buff_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Convert to ASCI
|
||||||
|
* Function convert byte value to two ASCI carecters
|
||||||
|
*/
|
||||||
|
void gdb_get_asci_char(unsigned char data, char *buff)
|
||||||
|
{
|
||||||
|
const char *hex_chars = "0123456789abcdef";
|
||||||
|
buff[0] = hex_chars[(data >> 4) & 0x0f];
|
||||||
|
buff[1] = hex_chars[(data) & 0x0f];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Everything below is related to the support for listing FreeRTOS tasks as threads in GDB */
|
/* Everything below is related to the support for listing FreeRTOS tasks as threads in GDB */
|
||||||
|
|
||||||
|
/** @brief Prepare GDB packet
|
||||||
|
* Function build GDB asci packet and return checksum
|
||||||
|
*
|
||||||
|
* Return checksum
|
||||||
|
*/
|
||||||
|
char gdb_packet(char *dest_buff, char *src_buff, int len)
|
||||||
|
{
|
||||||
|
char s_chsum = 0;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
gdb_get_asci_char(src_buff[i], &dest_buff[i * 2 + 0]);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < len * 2; i++) {
|
||||||
|
s_chsum += dest_buff[i];
|
||||||
|
}
|
||||||
|
return s_chsum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS)
|
||||||
|
static bool command_name_matches(const char *pattern, const unsigned char *ucmd, int len)
|
||||||
|
{
|
||||||
|
const char *cmd = (const char *) ucmd;
|
||||||
|
const char *end = cmd + len;
|
||||||
|
for (; *pattern && cmd < end; ++cmd, ++pattern) {
|
||||||
|
if (*pattern == '?') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*pattern != *cmd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *pattern == 0 && (cmd == end || *cmd == ',');
|
||||||
|
}
|
||||||
|
#endif // (CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS)
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
||||||
|
|
||||||
/* Some terminology related to task/thread indices:
|
/* Some terminology related to task/thread indices:
|
||||||
@ -386,6 +843,25 @@ static bool get_task_handle(size_t index, TaskHandle_t *handle)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static eTaskState get_task_state(size_t index)
|
||||||
|
{
|
||||||
|
eTaskState result = eReady;
|
||||||
|
TaskHandle_t handle;
|
||||||
|
get_task_handle(index, &handle);
|
||||||
|
if (gdb_debug_int == false) {
|
||||||
|
result = eTaskGetState(handle);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_task_cpu_id(size_t index)
|
||||||
|
{
|
||||||
|
TaskHandle_t handle;
|
||||||
|
get_task_handle(index, &handle);
|
||||||
|
BaseType_t core_id = xTaskGetAffinity(handle);
|
||||||
|
return (int)core_id;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the index of the task running on the current CPU, and save the result */
|
/** Get the index of the task running on the current CPU, and save the result */
|
||||||
static void find_paniced_task_index(void)
|
static void find_paniced_task_index(void)
|
||||||
{
|
{
|
||||||
@ -455,6 +931,19 @@ static void handle_qC_command(const unsigned char *cmd, int len)
|
|||||||
esp_gdbstub_send_end();
|
esp_gdbstub_send_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getActiveTaskNum(void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s_scratch.task_count; i++) {
|
||||||
|
{
|
||||||
|
eTaskState state = get_task_state(task_index_to_gdb_tid(i));
|
||||||
|
if (state == eRunning) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s_scratch.task_count;
|
||||||
|
}
|
||||||
|
|
||||||
/** T command checks if the task is alive.
|
/** T command checks if the task is alive.
|
||||||
* Since GDB isn't going to ask about the tasks which haven't been listed by q*ThreadInfo,
|
* Since GDB isn't going to ask about the tasks which haven't been listed by q*ThreadInfo,
|
||||||
* and the state of tasks can not change (no stepping allowed), simply return "OK" here.
|
* and the state of tasks can not change (no stepping allowed), simply return "OK" here.
|
||||||
@ -510,27 +999,34 @@ static void handle_qThreadExtraInfo_command(const unsigned char *cmd, int len)
|
|||||||
esp_gdbstub_send_str_as_hex((const char *)pcTaskGetName(handle));
|
esp_gdbstub_send_str_as_hex((const char *)pcTaskGetName(handle));
|
||||||
esp_gdbstub_send_hex(' ', 8);
|
esp_gdbstub_send_hex(' ', 8);
|
||||||
|
|
||||||
// Current version report only Suspended state
|
eTaskState state = get_task_state(task_index);
|
||||||
esp_gdbstub_send_str_as_hex("State: Suspended");
|
/* esp_gdbstub_send_str_as_hex("State: Suspended"); */
|
||||||
|
switch (state) {
|
||||||
|
case eRunning:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Running ");
|
||||||
|
esp_gdbstub_send_str_as_hex("@CPU - ");
|
||||||
|
esp_gdbstub_send_hex(get_task_cpu_id(task_index) + '0', 8);
|
||||||
|
break;
|
||||||
|
case eReady:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Ready");
|
||||||
|
break;
|
||||||
|
case eBlocked:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Blocked");
|
||||||
|
break;
|
||||||
|
case eSuspended:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Suspended");
|
||||||
|
break;
|
||||||
|
case eDeleted:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Deleted");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
esp_gdbstub_send_str_as_hex("State: Invalid");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
esp_gdbstub_send_end();
|
esp_gdbstub_send_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool command_name_matches(const char *pattern, const unsigned char *ucmd, int len)
|
|
||||||
{
|
|
||||||
const char *cmd = (const char *) ucmd;
|
|
||||||
const char *end = cmd + len;
|
|
||||||
for (; *pattern && cmd < end; ++cmd, ++pattern) {
|
|
||||||
if (*pattern == '?') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*pattern != *cmd) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *pattern == 0 && (cmd == end || *cmd == ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Handle all the thread-related commands */
|
/** Handle all the thread-related commands */
|
||||||
static int handle_task_commands(unsigned char *cmd, int len)
|
static int handle_task_commands(unsigned char *cmd, int len)
|
||||||
{
|
{
|
||||||
@ -553,7 +1049,7 @@ static int handle_task_commands(unsigned char *cmd, int len)
|
|||||||
/* Unrecognized command */
|
/* Unrecognized command */
|
||||||
return GDBSTUB_ST_ERR;
|
return GDBSTUB_ST_ERR;
|
||||||
}
|
}
|
||||||
} else if (strncmp((char *)cmd, "vCont;c", 7) == 0 || cmd[0] == 'c') { //continue execution
|
} else if (strncmp((char *)cmd, "vCont;c", 7) == 0 || cmd[0] == 'c') { /*continue execution */
|
||||||
return GDBSTUB_ST_CONT;
|
return GDBSTUB_ST_CONT;
|
||||||
} else {
|
} else {
|
||||||
/* Unrecognized command */
|
/* Unrecognized command */
|
||||||
@ -562,4 +1058,4 @@ static int handle_task_commands(unsigned char *cmd, int len)
|
|||||||
return GDBSTUB_ST_OK;
|
return GDBSTUB_ST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
|
#endif /* CONFIG_ESP_GDBSTUB_SUPPORT_TASKS */
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -86,6 +78,16 @@ typedef struct {
|
|||||||
} esp_gdbstub_gdb_regfile_t;
|
} esp_gdbstub_gdb_regfile_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Amount of HW breakpoints used in GDB
|
||||||
|
#ifndef GDB_BP_SIZE
|
||||||
|
#define GDB_BP_SIZE 2
|
||||||
|
#endif // GDB_BP_SIZE
|
||||||
|
|
||||||
|
// Amount of HW watchpoints used in GDB
|
||||||
|
#ifndef GDB_WP_SIZE
|
||||||
|
#define GDB_WP_SIZE 2
|
||||||
|
#endif // GDB_WP_SIZE
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
#include "freertos/xtensa_rtos.h"
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
// ------------------------------------------------
|
#include "freertos/xtensa_rtos.h"
|
||||||
.section .iram1,"ax"
|
|
||||||
|
|
||||||
.global gdbstub_handle_uart_int
|
.section .iram1, "ax"
|
||||||
.global _xt_gdbstub_int
|
|
||||||
.align 4
|
.global gdbstub_handle_uart_int
|
||||||
|
.global _xt_gdbstub_int
|
||||||
|
.align 4
|
||||||
|
|
||||||
_xt_gdbstub_int:
|
_xt_gdbstub_int:
|
||||||
|
|
||||||
/* Allocate exception frame and save minimal context. */
|
/* Allocate exception frame and save minimal context. */
|
||||||
mov a0, sp
|
mov a0, sp
|
||||||
addi sp, sp, -XT_STK_FRMSZ
|
addi sp, sp, -XT_STK_FRMSZ
|
||||||
s32i a0, sp, XT_STK_A1
|
s32i a0, sp, XT_STK_EXIT
|
||||||
|
s32i a0, sp, XT_STK_A0
|
||||||
|
|
||||||
#if XCHAL_HAVE_WINDOWED
|
#if XCHAL_HAVE_WINDOWED
|
||||||
s32e a0, sp, -12 /* for debug backtrace */
|
s32e a0, sp, -12 /* for debug backtrace */
|
||||||
#endif
|
#endif
|
||||||
@ -20,8 +27,6 @@ _xt_gdbstub_int:
|
|||||||
s32i a0, sp, XT_STK_PS
|
s32i a0, sp, XT_STK_PS
|
||||||
rsr a0, EPC_1 /* save interruptee's PC */
|
rsr a0, EPC_1 /* save interruptee's PC */
|
||||||
s32i a0, sp, XT_STK_PC
|
s32i a0, sp, XT_STK_PC
|
||||||
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
|
|
||||||
s32i a0, sp, XT_STK_A0
|
|
||||||
#if XCHAL_HAVE_WINDOWED
|
#if XCHAL_HAVE_WINDOWED
|
||||||
s32e a0, sp, -16 /* for debug backtrace */
|
s32e a0, sp, -16 /* for debug backtrace */
|
||||||
#endif
|
#endif
|
||||||
@ -34,7 +39,20 @@ _xt_gdbstub_int:
|
|||||||
rsr a0, EXCVADDR
|
rsr a0, EXCVADDR
|
||||||
s32i a0, sp, XT_STK_EXCVADDR
|
s32i a0, sp, XT_STK_EXCVADDR
|
||||||
|
|
||||||
mov a6,sp
|
|
||||||
|
/* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
|
||||||
|
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
|
||||||
|
|
||||||
|
s32i a0, sp, XT_STK_A0
|
||||||
|
|
||||||
|
/* Save context pointer as input parameter */
|
||||||
|
rsr a6, excsave1
|
||||||
|
|
||||||
|
rsr a3, EPS
|
||||||
|
s32i a3, sp, XT_STK_PS // store PS to the ps place
|
||||||
movi a3, gdbstub_handle_uart_int
|
movi a3, gdbstub_handle_uart_int
|
||||||
callx0 a3
|
callx0 a3
|
||||||
|
|
||||||
|
l32i a0, sp, XT_STK_EXIT
|
||||||
|
addi sp, sp, XT_STK_FRMSZ
|
||||||
ret
|
ret
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -10,6 +10,8 @@
|
|||||||
#include "soc/soc_memory_layout.h"
|
#include "soc/soc_memory_layout.h"
|
||||||
#include "xtensa/config/specreg.h"
|
#include "xtensa/config/specreg.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_ipc_isr.h"
|
||||||
|
#include "esp_private/crosscore_int.h"
|
||||||
|
|
||||||
#if !XCHAL_HAVE_WINDOWED
|
#if !XCHAL_HAVE_WINDOWED
|
||||||
#warning "gdbstub_xtensa: revisit the implementation for Call0 ABI"
|
#warning "gdbstub_xtensa: revisit the implementation for Call0 ABI"
|
||||||
@ -122,3 +124,96 @@ int esp_gdbstub_get_signal(const esp_gdbstub_frame_t *frame)
|
|||||||
}
|
}
|
||||||
return (int) exccause_to_signal[frame->exccause];
|
return (int) exccause_to_signal[frame->exccause];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Init dport for GDB
|
||||||
|
* Init dport for iterprocessor communications
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_init_dports(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ARCH_XTENSA && (!CONFIG_FREERTOS_UNICORE) && CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
static bool stall_started = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @brief GDB stall other CPU
|
||||||
|
* GDB stall other CPU
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_stall_other_cpus_start()
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ARCH_XTENSA && (!CONFIG_FREERTOS_UNICORE) && CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
if (stall_started == false) {
|
||||||
|
esp_ipc_isr_stall_other_cpu();
|
||||||
|
stall_started = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief GDB end stall other CPU
|
||||||
|
* GDB end stall other CPU
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_stall_other_cpus_end()
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ARCH_XTENSA && (!CONFIG_FREERTOS_UNICORE) && CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
if (stall_started == true) {
|
||||||
|
esp_ipc_isr_release_other_cpu();
|
||||||
|
stall_started = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief GDB clear step
|
||||||
|
* GDB clear step registers
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_clear_step(void)
|
||||||
|
{
|
||||||
|
WSR(ICOUNT, 0);
|
||||||
|
WSR(ICOUNTLEVEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief GDB do step
|
||||||
|
* GDB do one step
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_do_step(void)
|
||||||
|
{
|
||||||
|
// We have gdbstub uart interrupt, and if we will call step, with ICOUNTLEVEL=2 or higher, from uart interrupt, the
|
||||||
|
// application will hang because it will try to step uart interrupt. That's why we have to set ICOUNTLEVEL=1
|
||||||
|
// If we will stop by the breakpoint inside interrupt, we will handle this interrupt with ICOUNTLEVEL=ps.intlevel+1
|
||||||
|
|
||||||
|
uint32_t level = s_scratch.regfile.ps;
|
||||||
|
level &= 0x7;
|
||||||
|
level += 1;
|
||||||
|
|
||||||
|
WSR(ICOUNTLEVEL, level);
|
||||||
|
WSR(ICOUNT, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief GDB trigger other CPU
|
||||||
|
* GDB trigger other CPU
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_trigger_cpu(void)
|
||||||
|
{
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
if (0 == cpu_hal_get_core_id()) {
|
||||||
|
esp_crosscore_int_send_gdb_call(1);
|
||||||
|
} else {
|
||||||
|
esp_crosscore_int_send_gdb_call(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief GDB set register in frame
|
||||||
|
* Set register in frame with address to value
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
void esp_gdbstub_set_register(esp_gdbstub_frame_t *frame, uint32_t reg_index, uint32_t value)
|
||||||
|
{
|
||||||
|
switch (reg_index) {
|
||||||
|
case 0:
|
||||||
|
frame->pc = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
(&frame->a0)[reg_index - 1] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
64
components/esp_gdbstub/xtensa/xt_debugexception.S
Normal file
64
components/esp_gdbstub/xtensa/xt_debugexception.S
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtensa/coreasm.h>
|
||||||
|
#include <xtensa/corebits.h>
|
||||||
|
#include <xtensa/config/system.h>
|
||||||
|
#include "freertos/xtensa_context.h"
|
||||||
|
|
||||||
|
.section .iram1,"ax"
|
||||||
|
.global _xt_panic_gdbstub
|
||||||
|
.type _xt_panic_gdbstub,@function
|
||||||
|
.align 4
|
||||||
|
.literal_position
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
_xt_panic_gdbstub:
|
||||||
|
/* Allocate exception frame and save minimal context. */
|
||||||
|
addi sp, sp, -XT_STK_FRMSZ
|
||||||
|
s32i a0, sp, XT_STK_EXIT
|
||||||
|
s32i a0, sp, XT_STK_A0
|
||||||
|
|
||||||
|
rsr a0, PS /* save interruptee's PS */
|
||||||
|
s32i a0, sp, XT_STK_PS
|
||||||
|
rsr a0, EPC_1 /* save interruptee's PC */
|
||||||
|
s32i a0, sp, XT_STK_PC
|
||||||
|
call0 _xt_context_save /* Save full context*/
|
||||||
|
addi a7, sp, XT_STK_FRMSZ
|
||||||
|
s32i a7, sp, XT_STK_A1
|
||||||
|
s32i a12, sp, XT_STK_A12
|
||||||
|
s32i a13, sp, XT_STK_A13
|
||||||
|
|
||||||
|
/* Save exc cause and vaddr into exception frame */
|
||||||
|
rsr a0, EXCCAUSE
|
||||||
|
s32i a0, sp, XT_STK_EXCCAUSE
|
||||||
|
rsr a0, EXCVADDR
|
||||||
|
s32i a0, sp, XT_STK_EXCVADDR
|
||||||
|
|
||||||
|
/* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
|
||||||
|
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
|
||||||
|
|
||||||
|
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||||
|
movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
|
||||||
|
wsr a0, PS
|
||||||
|
|
||||||
|
//Call gdbstub handler
|
||||||
|
|
||||||
|
rsr a0,(EPC + XCHAL_DEBUGLEVEL)
|
||||||
|
s32i a0, sp, XT_STK_PC
|
||||||
|
mov a6, sp
|
||||||
|
rsr a9, EPS_6
|
||||||
|
s32i a9, sp, XT_STK_PS // store PS to the ps place
|
||||||
|
movi a11, gdbstub_handle_debug_int
|
||||||
|
callx4 a11 /* Call interrupt handler */
|
||||||
|
l32i a0, sp, XT_STK_PC
|
||||||
|
wsr a0,(EPC + XCHAL_DEBUGLEVEL)
|
||||||
|
call0 _xt_context_restore /* Restore full context*/
|
||||||
|
l32i a12, sp, XT_STK_A12
|
||||||
|
l32i a13, sp, XT_STK_A13
|
||||||
|
l32i a0, sp, XT_STK_EXIT /* Restore return point*/
|
||||||
|
addi sp, sp, XT_STK_FRMSZ /* Restore SP*/
|
||||||
|
rfi 6 // Return from high-level interrupt
|
@ -86,6 +86,4 @@ endif()
|
|||||||
|
|
||||||
# [refactor-todo] requirement from the panic handler,
|
# [refactor-todo] requirement from the panic handler,
|
||||||
# need to introduce panic "event" concept to remove this dependency (IDF-2194)
|
# need to introduce panic "event" concept to remove this dependency (IDF-2194)
|
||||||
if(CONFIG_ESP_SYSTEM_PANIC_GDBSTUB)
|
idf_component_optional_requires(PRIVATE esp_gdbstub)
|
||||||
idf_component_optional_requires(PRIVATE esp_gdbstub)
|
|
||||||
endif()
|
|
||||||
|
@ -34,11 +34,10 @@ menu "ESP System Settings"
|
|||||||
|
|
||||||
config ESP_SYSTEM_GDBSTUB_RUNTIME
|
config ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
bool "GDBStub at runtime"
|
bool "GDBStub at runtime"
|
||||||
select FREERTOS_UNICORE
|
|
||||||
select ESP_GDBSTUB_ENABLED
|
select ESP_GDBSTUB_ENABLED
|
||||||
|
depends on !IDF_TARGET_ESP32C2
|
||||||
help
|
help
|
||||||
Invoke gdbstub on the serial port, allowing for gdb to attach to it and to do a debug on runtime.
|
Invoke gdbstub on the serial port, allowing for gdb to attach to it and to do a debug on runtime.
|
||||||
This feature will switch system to single core mode.
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config ESP_SYSTEM_SINGLE_CORE_MODE
|
config ESP_SYSTEM_SINGLE_CORE_MODE
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/portmacro.h"
|
#include "freertos/portmacro.h"
|
||||||
|
|
||||||
|
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
#include "esp_gdbstub.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
|
||||||
@ -22,6 +26,7 @@
|
|||||||
|
|
||||||
#define REASON_YIELD BIT(0)
|
#define REASON_YIELD BIT(0)
|
||||||
#define REASON_FREQ_SWITCH BIT(1)
|
#define REASON_FREQ_SWITCH BIT(1)
|
||||||
|
#define REASON_GDB_CALL BIT(3)
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
|
||||||
#define REASON_PRINT_BACKTRACE BIT(2)
|
#define REASON_PRINT_BACKTRACE BIT(2)
|
||||||
@ -79,6 +84,11 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) {
|
|||||||
* to allow DFS features without the extra latency of the ISR hook.
|
* to allow DFS features without the extra latency of the ISR hook.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
if (my_reason_val & REASON_GDB_CALL) {
|
||||||
|
update_breakpoints();
|
||||||
|
}
|
||||||
|
#endif // !CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2 // IDF-2986
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2 // IDF-2986
|
||||||
if (my_reason_val & REASON_PRINT_BACKTRACE) {
|
if (my_reason_val & REASON_PRINT_BACKTRACE) {
|
||||||
esp_backtrace_print(100);
|
esp_backtrace_print(100);
|
||||||
@ -141,6 +151,11 @@ void IRAM_ATTR esp_crosscore_int_send_freq_switch(int core_id)
|
|||||||
esp_crosscore_int_send(core_id, REASON_FREQ_SWITCH);
|
esp_crosscore_int_send(core_id, REASON_FREQ_SWITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR esp_crosscore_int_send_gdb_call(int core_id)
|
||||||
|
{
|
||||||
|
esp_crosscore_int_send(core_id, REASON_GDB_CALL);
|
||||||
|
}
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
|
||||||
void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id)
|
void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@ void esp_crosscore_int_send_yield(int core_id);
|
|||||||
*/
|
*/
|
||||||
void esp_crosscore_int_send_freq_switch(int core_id);
|
void esp_crosscore_int_send_freq_switch(int core_id);
|
||||||
|
|
||||||
|
void esp_crosscore_int_send_gdb_call(int core_id);
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -68,7 +68,7 @@ void esp_startup_start_app_common(void)
|
|||||||
|
|
||||||
esp_crosscore_int_init();
|
esp_crosscore_int_init();
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME && !CONFIG_IDF_TARGET_ESP8684
|
||||||
esp_gdbstub_init();
|
esp_gdbstub_init();
|
||||||
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ The default behaviour is to just exit the interrupt or call the panic handler on
|
|||||||
|
|
||||||
_xt_debugexception:
|
_xt_debugexception:
|
||||||
#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI)
|
#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI)
|
||||||
|
s32i a0, sp, XT_STK_EXIT
|
||||||
|
|
||||||
#define XT_DEBUGCAUSE_DI (5)
|
#define XT_DEBUGCAUSE_DI (5)
|
||||||
getcoreid a0
|
getcoreid a0
|
||||||
#if (CONFIG_BTDM_CTRL_PINNED_TO_CORE == PRO_CPU_NUM)
|
#if (CONFIG_BTDM_CTRL_PINNED_TO_CORE == PRO_CPU_NUM)
|
||||||
@ -48,7 +50,11 @@ _xt_debugexception:
|
|||||||
wsr a0,EPC_1
|
wsr a0,EPC_1
|
||||||
rsr a0,(EXCSAVE + XCHAL_DEBUGLEVEL)
|
rsr a0,(EXCSAVE + XCHAL_DEBUGLEVEL)
|
||||||
wsr a0,EXCSAVE_1
|
wsr a0,EXCSAVE_1
|
||||||
|
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
|
J _xt_panic_gdbstub /* For gdbstub we make jump */
|
||||||
|
#else
|
||||||
call0 _xt_panic /* does not return */
|
call0 _xt_panic /* does not return */
|
||||||
|
#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
|
||||||
rfi XCHAL_DEBUGLEVEL
|
rfi XCHAL_DEBUGLEVEL
|
||||||
|
|
||||||
#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI)
|
#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI)
|
||||||
|
@ -443,7 +443,7 @@ Debug Exception.
|
|||||||
.global xt_debugexception
|
.global xt_debugexception
|
||||||
_DebugExceptionVector:
|
_DebugExceptionVector:
|
||||||
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* preserve a0 */
|
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* preserve a0 */
|
||||||
call0 xt_debugexception /* load exception handler */
|
J xt_debugexception /* load exception handler */
|
||||||
|
|
||||||
.end literal_prefix
|
.end literal_prefix
|
||||||
|
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
This example shows how to use gdbstub and it's functionality at runtime to debug an application with GDB.
|
This example shows how to use gdbstub and it's functionality at runtime to debug an application with GDB.
|
||||||
With the gdbstub component it is possible to run GDB from IDF Monitor by pressing Ctrl+C and debug
|
With the gdbstub component it is possible to run GDB from IDF Monitor by pressing Ctrl+C and debug
|
||||||
the application using GDB. It is also possible to read/modify memory values, interrupt and continue the application.
|
the application using GDB. It is also possible to read/modify memory values, interrupt and continue
|
||||||
|
the application, set breakpoints, make steps and so on.
|
||||||
Upon exit from GDB, the application will continue to work in IDF Monitor as before.
|
Upon exit from GDB, the application will continue to work in IDF Monitor as before.
|
||||||
|
|
||||||
## How to use example
|
## How to use example
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
he example can run on any commonly available ESP32 development board.
|
The example can run on any commonly available ESP32 development board.
|
||||||
There are two possible ways to execute gdbstub with GDB: from IDF Monitor and as standalone application.
|
There are two possible ways to execute gdbstub with GDB: from IDF Monitor and as standalone application.
|
||||||
gdbstub support ESP32, ESP32-S2 and ESP32-S3 chips.
|
gdbstub support ESP32, ESP32-S2 and ESP32-S3 chips.
|
||||||
|
|
||||||
@ -25,9 +26,6 @@ This selection switches gdbstub to runtime mode.
|
|||||||
Depending on the project, following settings could be used:
|
Depending on the project, following settings could be used:
|
||||||
-> Component Config -> GDB Stub -> ...
|
-> Component Config -> GDB Stub -> ...
|
||||||
The user can enable or disable task list handling and define a maximum amount of tasks.
|
The user can enable or disable task list handling and define a maximum amount of tasks.
|
||||||
Note that gdbstub can now only be used when FreeRTOS is run on the first core only.
|
|
||||||
This setting is located here:
|
|
||||||
-> Component Config -> FreeRTOS -> Run FreeRTOS only on first core.
|
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
@ -56,15 +54,27 @@ The user can continue running the application in GDB by entering "continue" and
|
|||||||
The user can check again that the application has worked by checking variable "print call_count".
|
The user can check again that the application has worked by checking variable "print call_count".
|
||||||
The user can exit from GDB to continue seeing the trace from IDF Monitor by pressing "quit" and then "y".
|
The user can exit from GDB to continue seeing the trace from IDF Monitor by pressing "quit" and then "y".
|
||||||
The user will see in IDF Monitor that call_count and logging level have changed.
|
The user will see in IDF Monitor that call_count and logging level have changed.
|
||||||
|
The user can add breakpoint to the label test_point2 by entering "break test_point2" and then enter "continue" or "c". The application will break at this line.
|
||||||
|
If user will continue again, the application will break at this line again.
|
||||||
|
Also, user can try to step application by entering "si".
|
||||||
A typical console output for such a scenario is shown below:
|
A typical console output for such a scenario is shown below:
|
||||||
```
|
```
|
||||||
I (300) cpu_start: Starting scheduler on PRO CPU.
|
I (312) cpu_start: Starting scheduler on PRO CPU.
|
||||||
|
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||||
Hello GDB example!
|
Hello GDB example!
|
||||||
I (307) gdbstub_example: INFO mode enabled. Call - 0. To enter GDB please press "Ctrl+C"
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
W (317) gdbstub_example: WARN mode enabled. Call - 0. To enter GDB please press "Ctrl+C"
|
I (4317) gdbstub_example: INFO mode enabled. Task 0, Core ID 0, Call - 0.
|
||||||
I (1317) gdbstub_example: INFO mode enabled. Call - 1. To enter GDB please press "Ctrl+C"
|
W (4317) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 0.
|
||||||
W (1317) gdbstub_example: WARN mode enabled. Call - 1. To enter GDB please press "Ctrl+C"
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
To exit from the idf.py please use "Ctrl+]"
|
I (4327) gdbstub_example: INFO mode enabled. Task 1, Core ID 1, Call - 0.
|
||||||
|
W (4337) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 0.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
I (5137) gdbstub_example: INFO mode enabled. Task 0, Core ID 0, Call - 1.
|
||||||
|
W (5137) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 1.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
I (5157) gdbstub_example: INFO mode enabled. Task 1, Core ID 1, Call - 1.
|
||||||
|
W (5157) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 1.
|
||||||
|
To exit from IDF monitor please use "Ctrl+]"
|
||||||
$T02#b6GNU gdb (crosstool-NG esp-2020r3) 8.1.0.20180627-git
|
$T02#b6GNU gdb (crosstool-NG esp-2020r3) 8.1.0.20180627-git
|
||||||
Copyright (C) 2018 Free Software Foundation, Inc.
|
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||||
@ -80,37 +90,71 @@ Find the GDB manual and other documentation resources online at:
|
|||||||
For help, type "help".
|
For help, type "help".
|
||||||
Type "apropos word" to search for commands related to "word"...
|
Type "apropos word" to search for commands related to "word"...
|
||||||
Reading symbols from c:\esp-idf\examples\system\gdbstub\build\gdbstub.elf...done.
|
Reading symbols from c:\esp-idf\examples\system\gdbstub\build\gdbstub.elf...done.
|
||||||
Remote debugging using \\.\COM15
|
Remote debugging using \\.\COM16
|
||||||
0x400dff0a in esp_pm_impl_waiti () at C:/esp-idf/components/esp_pm/pm_impl.c:533
|
task4test (param=0x0) at ../main/gdbstub_main.c:41
|
||||||
533 asm("waiti 0");
|
41 asm(" nop;");
|
||||||
(gdb) print call_count
|
(gdb) print call_counts[0]
|
||||||
$1 = 2
|
$1 = 2
|
||||||
(gdb) set call_count = 100
|
(gdb) print call_counts[1]
|
||||||
(gdb) print call_count
|
$2 = 2
|
||||||
$2 = 100
|
(gdb) set call_counts[0] = 100
|
||||||
|
(gdb) set call_counts[0] = 100(gdb) print call_counts[0]
|
||||||
|
$3 = 100
|
||||||
(gdb) print update_log_level
|
(gdb) print update_log_level
|
||||||
$3 = ESP_LOG_DEBUG
|
$4 = ESP_LOG_DEBUG
|
||||||
(gdb) set update_log_level = ESP_LOG_WARN
|
(gdb) set update_log_level = ESP_LOG_WARN
|
||||||
(gdb) print update_log_level
|
(gdb) print update_log_level
|
||||||
$4 = ESP_LOG_WARN
|
$5 = ESP_LOG_WARN
|
||||||
|
(gdb) c
|
||||||
|
Continuing.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 100.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 2.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 101.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 3.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 102.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
W (5927) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 4.
|
||||||
|
|
||||||
|
Thread 1 received signal SIGINT, Interrupt.
|
||||||
|
task4test (param=0x0) at ../main/gdbstub_main.c:38
|
||||||
|
38 for (int i=0 ; i< 10000000; i++)
|
||||||
|
(gdb) break test_point2
|
||||||
|
Breakpoint 1 at 0x400d511d: file ../main/gdbstub_main.c, line 40.
|
||||||
(gdb) c
|
(gdb) c
|
||||||
Continuing.
|
Continuing.
|
||||||
|
|
||||||
|
Thread 1 hit Breakpoint 1, task4test (param=0x1) at ../main/gdbstub_main.c:40
|
||||||
|
40 asm("test_point2: nop;");
|
||||||
|
(gdb) si
|
||||||
|
41 asm(" nop;");
|
||||||
|
(gdb) si
|
||||||
|
42 asm(" nop;");
|
||||||
|
(gdb) c
|
||||||
|
Continuing.
|
||||||
|
|
||||||
|
Thread 1 hit Breakpoint 1, task4test (param=0x1) at ../main/gdbstub_main.c:40
|
||||||
|
40 asm("test_point2: nop;");
|
||||||
|
(gdb) delete 1
|
||||||
|
(gdb) c
|
||||||
|
Continuing.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
W (36077) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 103.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
W (36107) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 5.
|
||||||
|
CPU 0: To enter GDB please press "Ctrl+C"
|
||||||
|
W (36917) gdbstub_example: WARN mode enabled. Task 0, Core ID 0, Call - 104.
|
||||||
|
CPU 1: To enter GDB please press "Ctrl+C"
|
||||||
|
W (36947) gdbstub_example: WARN mode enabled. Task 1, Core ID 1, Call - 6.
|
||||||
|
|
||||||
Thread 1 received signal SIGINT, Interrupt.
|
Thread 1 received signal SIGINT, Interrupt.
|
||||||
0x400dff0a in esp_pm_impl_waiti () at C:/esp-idf/components/esp_pm/pm_impl.c:533
|
task4test (param=0x0) at ../main/gdbstub_main.c:38
|
||||||
533 asm("waiti 0");
|
38 for (int i=0 ; i< 10000000; i++)
|
||||||
(gdb) print call_count
|
(gdb)
|
||||||
$6 = 108
|
|
||||||
(gdb) quit
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be killed.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) y
|
|
||||||
W (13977) gdbstub_example: WARN mode enabled. Call - 108. To enter GDB please press "Ctrl+C"
|
|
||||||
W (14977) gdbstub_example: WARN mode enabled. Call - 109. To enter GDB please press "Ctrl+C"
|
|
||||||
W (15977) gdbstub_example: WARN mode enabled. Call - 110. To enter GDB please press "Ctrl+C"
|
|
||||||
W (16977) gdbstub_example: WARN mode enabled. Call - 111. To enter GDB please press "Ctrl+C"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To reproduce this scenario run the application by: idf.py -P PORT flash monitor
|
To reproduce this scenario run the application by: idf.py -P PORT flash monitor
|
||||||
@ -121,7 +165,13 @@ Then:
|
|||||||
4. Continue the application by typing in GDB command line "continue"
|
4. Continue the application by typing in GDB command line "continue"
|
||||||
5. Interrupt application by pressing Ctrl+C
|
5. Interrupt application by pressing Ctrl+C
|
||||||
6. Check the value by typing in GDB command line "print call_count" or "print update_log_level"
|
6. Check the value by typing in GDB command line "print call_count" or "print update_log_level"
|
||||||
7. Exit GDB by typing "quit" and then "y"
|
7. Continue the application by typing in GDB command line "continue"
|
||||||
|
8. Interrupt the application by pressing Ctrl+C
|
||||||
|
9. Add breakpoint by typing in GDB command line "break test_point2" or break 40 (break at line 40).
|
||||||
|
10. Continue the application by typing in GDB command line "continue"
|
||||||
|
11. After application stop at label "test_point2".
|
||||||
|
12. Make stepping by typing "si"
|
||||||
|
13. To exit from GDB to monitor type "exit" and press "y"
|
||||||
|
|
||||||
To exit from monitor please use Ctrl+]
|
To exit from monitor please use Ctrl+]
|
||||||
|
|
||||||
|
@ -14,26 +14,41 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
|
||||||
int call_count = 0;
|
|
||||||
|
|
||||||
static const char *TAG = "gdbstub_example";
|
static const char *TAG = "gdbstub_example";
|
||||||
esp_log_level_t log_level = ESP_LOG_DEBUG;
|
esp_log_level_t log_level = ESP_LOG_DEBUG;
|
||||||
esp_log_level_t update_log_level = ESP_LOG_DEBUG;
|
esp_log_level_t update_log_level = ESP_LOG_DEBUG;
|
||||||
|
|
||||||
|
int call_counts[4] = {0};
|
||||||
|
void task4test(void *param)
|
||||||
|
{
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
int task_num = (int)param;
|
||||||
|
volatile int core = xPortGetCoreID();
|
||||||
|
while (1) {
|
||||||
|
core = xPortGetCoreID();
|
||||||
|
printf("CPU %i: To enter GDB please press \"Ctrl+C\"\n", core);
|
||||||
|
ESP_LOGD(TAG, "DEBUG mode enabled. Task %i, Core ID %i, Call - %i.", task_num, core, call_counts[task_num]);
|
||||||
|
ESP_LOGI(TAG, "INFO mode enabled. Task %i, Core ID %i, Call - %i.", task_num, core, call_counts[task_num]);
|
||||||
|
ESP_LOGW(TAG, "WARN mode enabled. Task %i, Core ID %i, Call - %i.", task_num, core, call_counts[task_num]++);
|
||||||
|
|
||||||
|
asm("test_point1: nop;");
|
||||||
|
for (int i = 0 ; i < 10000000; i++) {
|
||||||
|
asm("test_point2: nop;");
|
||||||
|
asm(" nop;");
|
||||||
|
asm(" nop;");
|
||||||
|
asm(" nop;");
|
||||||
|
}
|
||||||
|
log_level = update_log_level;
|
||||||
|
esp_log_level_set(TAG, log_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
printf("Hello GDB example!\n");
|
printf("Hello GDB example!\n");
|
||||||
|
|
||||||
call_count = 0;
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
for (;;) {
|
xTaskCreatePinnedToCore(task4test, "task 3", 4096, (void *)0, 10, NULL, 0);
|
||||||
ESP_LOGD(TAG, "DEBUG mode enabled. Call - %i. To enter GDB please press \"Ctrl+C\"", call_count);
|
xTaskCreatePinnedToCore(task4test, "task 4", 4096, (void *)1, 10, NULL, 1);
|
||||||
ESP_LOGI(TAG, "INFO mode enabled. Call - %i. To enter GDB please press \"Ctrl+C\"", call_count);
|
|
||||||
ESP_LOGW(TAG, "WARN mode enabled. Call - %i. To enter GDB please press \"Ctrl+C\"", call_count++);
|
|
||||||
if (update_log_level != log_level) {
|
|
||||||
log_level = update_log_level;
|
|
||||||
esp_log_level_set(TAG, log_level);
|
|
||||||
}
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,6 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y
|
|||||||
CONFIG_ESP_GDBSTUB_MAX_TASKS=32
|
CONFIG_ESP_GDBSTUB_MAX_TASKS=32
|
||||||
# end of GDB Stub
|
# end of GDB Stub
|
||||||
|
|
||||||
#
|
|
||||||
# FreeRTOS
|
|
||||||
#
|
|
||||||
CONFIG_FREERTOS_UNICORE=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# ESP System Settings
|
# ESP System Settings
|
||||||
#
|
#
|
||||||
@ -18,5 +13,6 @@ CONFIG_FREERTOS_UNICORE=y
|
|||||||
# CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT is not set
|
# CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT is not set
|
||||||
# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
|
# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
|
||||||
CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME=y
|
CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME=y
|
||||||
CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y
|
# CONFIG_ESP_INT_WDT is not set
|
||||||
|
# CONFIG_ESP_TASK_WDT is not set
|
||||||
# end of ESP System Settings
|
# end of ESP System Settings
|
||||||
|
@ -448,12 +448,7 @@ components/esp_gdbstub/esp32c3/gdbstub_target_config.h
|
|||||||
components/esp_gdbstub/esp32h2/gdbstub_target_config.h
|
components/esp_gdbstub/esp32h2/gdbstub_target_config.h
|
||||||
components/esp_gdbstub/esp32s2/gdbstub_target_config.h
|
components/esp_gdbstub/esp32s2/gdbstub_target_config.h
|
||||||
components/esp_gdbstub/esp32s3/gdbstub_target_config.h
|
components/esp_gdbstub/esp32s3/gdbstub_target_config.h
|
||||||
components/esp_gdbstub/esp_common/gdbstub_common.c
|
|
||||||
components/esp_gdbstub/include/esp_gdbstub.h
|
|
||||||
components/esp_gdbstub/private_include/esp_gdbstub_common.h
|
|
||||||
components/esp_gdbstub/riscv/esp_gdbstub_arch.h
|
|
||||||
components/esp_gdbstub/src/packet.c
|
components/esp_gdbstub/src/packet.c
|
||||||
components/esp_gdbstub/xtensa/esp_gdbstub_arch.h
|
|
||||||
components/esp_hid/include/esp_hid_common.h
|
components/esp_hid/include/esp_hid_common.h
|
||||||
components/esp_hid/include/esp_hidd.h
|
components/esp_hid/include/esp_hidd.h
|
||||||
components/esp_hid/include/esp_hidd_gatts.h
|
components/esp_hid/include/esp_hidd_gatts.h
|
||||||
|
Reference in New Issue
Block a user