From e007ace00d1adbdc5a3450f14922f1cab5ceb671 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Wed, 17 Jul 2024 10:39:53 +0800 Subject: [PATCH] gdbstub:support only use gdbstub when panic Signed-off-by: anjiahao --- drivers/serial/Kconfig | 17 ++++ drivers/serial/serial.c | 6 +- drivers/serial/serial_gdbstub.c | 134 ++++++++++++++++++++++++++++---- include/nuttx/serial/serial.h | 2 +- 4 files changed, 139 insertions(+), 20 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 2cc09c5154..4cf3b2b4a3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -53,6 +53,23 @@ config SERIAL_GDBSTUB_PATH ---help--- The path to the serial device that will be used for GDB stub. +config SERIAL_GDBSTUB_AUTO_ATTACH + bool "GDBSTUB Serial Auto attach" + depends on SERIAL_GDBSTUB + default n + ---help--- + Attach the serial port to gdbstub by default. + Will cover the GDBSTUB_SERIAL_PATH, that port will only + be used for GDB stub. + +config SERIAL_GDBSTUB_PANIC_TIMEOUT + int "GDBSTUB Serial panic timeout" + depends on SERIAL_GDBSTUB + default 10 + ---help--- + Delay the panic timeout for gdbstub to connect. + 0 will disable the timeout. + config UART_HOSTFS bool "Use hostfs read/write on UART_HOSTFS_DEVPATH as uart console" depends on FS_HOSTFS diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 9f8fb2a3ff..6d1411d9c3 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -1928,9 +1928,11 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev) /* Register the serial driver */ #ifdef CONFIG_SERIAL_GDBSTUB - if (strcmp(path, CONFIG_SERIAL_GDBSTUB_PATH) == 0) + if (uart_gdbstub_register(dev, path) == 0) { - return uart_gdbstub_register(dev); + /* No need register the device if it is used by gdbstub */ + + return 0; } #endif diff --git a/drivers/serial/serial_gdbstub.c b/drivers/serial/serial_gdbstub.c index b2d3362e1d..37c853b638 100644 --- a/drivers/serial/serial_gdbstub.c +++ b/drivers/serial/serial_gdbstub.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -32,24 +33,54 @@ #include /**************************************************************************** - * Private Data + * Private Types ****************************************************************************/ struct uart_gdbstub_s { FAR struct uart_dev_s *dev; + FAR struct uart_dev_s *console; FAR struct gdb_state_s *state; FAR const struct uart_ops_s *org_ops; struct uart_ops_s ops; struct notifier_block nb; }; +/**************************************************************************** + * Private Data + ****************************************************************************/ + static FAR struct uart_gdbstub_s *g_uart_gdbstub; +/**************************************************************************** + * Private Functions prototypes + ****************************************************************************/ + +static int uart_gdbstub_ctrlc(FAR struct uart_dev_s *dev, + FAR unsigned int *status); + /**************************************************************************** * Private Functions ****************************************************************************/ +static void uart_gdbstub_attach(FAR struct uart_gdbstub_s *uart_gdbstub, + bool replace) +{ + FAR uart_dev_t *dev = uart_gdbstub->dev; + + if (replace && uart_gdbstub->org_ops == NULL) + { + memcpy(&uart_gdbstub->ops, dev->ops, sizeof(struct uart_ops_s)); + uart_gdbstub->org_ops = dev->ops; + uart_gdbstub->ops.receive = uart_gdbstub_ctrlc; + dev->ops = &uart_gdbstub->ops; + } + + uart_setup(dev); + uart_attach(dev); + uart_enablerxint(dev); +} + /**************************************************************************** * Name: uart_gdbstub_panic_callback * @@ -64,19 +95,74 @@ static int uart_gdbstub_panic_callback(FAR struct notifier_block *nb, { FAR struct uart_gdbstub_s *uart_gdbstub = container_of(nb, struct uart_gdbstub_s, nb); +#if CONFIG_SERIAL_GDBSTUB_PANIC_TIMEOUT != 0 + unsigned int base; + unsigned int status; + char ch; +#endif if (action != PANIC_KERNEL_FINAL) { return 0; } +#if CONFIG_SERIAL_GDBSTUB_PANIC_TIMEOUT == 0 + gdb_console_message(uart_gdbstub->state, + "Enter panic gdbstub mode!\n"); +#else + _alert("Press Y/y key in %d seconds to enter gdb debug mode\n", + CONFIG_SERIAL_GDBSTUB_PANIC_TIMEOUT); + syslog_flush(); + + if (uart_gdbstub->console == NULL) + { +#ifndef CONFIG_SERIAL_GDBSTUB_AUTO_ATTACH + uart_gdbstub_attach(uart_gdbstub, false); +#endif + uart_gdbstub->console = uart_gdbstub->dev; + } + + base = clock_systime_ticks(); + while (true) + { + if (uart_gdbstub->console == uart_gdbstub->dev && + uart_gdbstub->org_ops != NULL) + { + ch = uart_gdbstub->org_ops->receive(uart_gdbstub->console, + &status); + } + else + { + ch = uart_gdbstub->console->ops->receive(uart_gdbstub->console, + &status); + } + + if (ch == 'Y' || ch == 'y') + { + break; + } + + if ((clock_systime_ticks()) - base >= + SEC2TICK(CONFIG_SERIAL_GDBSTUB_PANIC_TIMEOUT)) + { + _alert("%d seconds passed, exit now\n", + CONFIG_SERIAL_GDBSTUB_PANIC_TIMEOUT); + return 0; + } + } +#endif + +#ifndef CONFIG_SERIAL_GDBSTUB_AUTO_ATTACH + uart_gdbstub_attach(uart_gdbstub, true); +#endif + _alert("Enter panic gdbstub mode, plase use gdb connect to debug\n"); _alert("Please use gdb of the corresponding architecture to " "connect to nuttx"); _alert("such as: arm-none-eabi-gdb nuttx -ex \"set " "target-charset ASCII\" -ex \"target remote /dev/ttyUSB0\"\n"); - gdb_console_message(uart_gdbstub->state, "Enter panic gdbstub mode!\n"); + syslog_flush(); gdb_process(uart_gdbstub->state, GDB_STOPREASON_CTRLC, NULL); return 0; } @@ -120,7 +206,7 @@ static ssize_t uart_gdbstub_receive(FAR void *priv, FAR void *buf, { if (uart_gdbstub->org_ops->rxavailable(dev)) { - ptr[i++] = g_uart_gdbstub->org_ops->receive(dev, &state); + ptr[i++] = uart_gdbstub->org_ops->receive(dev, &state); } } @@ -165,14 +251,33 @@ static ssize_t uart_gdbstub_send(FAR void *priv, FAR void *buf, size_t len) * ****************************************************************************/ -int uart_gdbstub_register(FAR uart_dev_t *dev) +int uart_gdbstub_register(FAR uart_dev_t *dev, FAR const char *path) { FAR struct uart_gdbstub_s *uart_gdbstub; - uart_gdbstub = kmm_malloc(sizeof(struct uart_gdbstub_s)); - if (uart_gdbstub == NULL) + if (g_uart_gdbstub == NULL) { - return -ENOMEM; + uart_gdbstub = kmm_zalloc(sizeof(struct uart_gdbstub_s)); + if (uart_gdbstub == NULL) + { + return -ENOMEM; + } + + g_uart_gdbstub = uart_gdbstub; + } + else + { + uart_gdbstub = g_uart_gdbstub; + } + + if (dev->isconsole && uart_gdbstub->console == NULL) + { + uart_gdbstub->console = dev; + } + + if (strcmp(path, CONFIG_SERIAL_GDBSTUB_PATH) != 0) + { + return -EINVAL; } uart_gdbstub->state = gdb_state_init(uart_gdbstub_send, @@ -184,19 +289,14 @@ int uart_gdbstub_register(FAR uart_dev_t *dev) return -ENOMEM; } - g_uart_gdbstub = uart_gdbstub; - - memcpy(&uart_gdbstub->ops, dev->ops, sizeof(struct uart_ops_s)); uart_gdbstub->dev = dev; - uart_gdbstub->org_ops = dev->ops; - uart_gdbstub->ops.receive = uart_gdbstub_ctrlc; - dev->ops = &uart_gdbstub->ops; - uart_setup(dev); - uart_attach(dev); - uart_enablerxint(dev); - uart_gdbstub->nb.notifier_call = uart_gdbstub_panic_callback; panic_notifier_chain_register(&uart_gdbstub->nb); +#ifdef CONFIG_SERIAL_GDBSTUB_AUTO_ATTACH + uart_gdbstub_attach(uart_gdbstub, true); return 0; +#else + return 1; +#endif } diff --git a/include/nuttx/serial/serial.h b/include/nuttx/serial/serial.h index c66c54f7b0..82edf04f92 100644 --- a/include/nuttx/serial/serial.h +++ b/include/nuttx/serial/serial.h @@ -561,7 +561,7 @@ int uart_check_special(FAR uart_dev_t *dev, FAR const char *buf, ****************************************************************************/ #ifdef CONFIG_SERIAL_GDBSTUB -int uart_gdbstub_register(FAR uart_dev_t *dev); +int uart_gdbstub_register(FAR uart_dev_t *dev, FAR const char *path); #endif #undef EXTERN