diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3846809b2ad..6b0ae715a09 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -174,6 +174,20 @@ config SERIAL_TERMIOS If this is not defined, then the terminal settings (baud, parity, etc). are not configurable at runtime; serial streams cannot be flushed, etc.. +config TTY_FORCE_PANIC + bool "Enable TTY force crash" + default n + ---help--- + This is for debugging system busyloop or deadlock, when the shell can't run, + then use this force crash the system to see the dumplog. + +config TTY_FORCE_PANIC_CHAR + hex "TTY force crash characters" + default 0x0 + depends on TTY_FORCE_PANIC + ---help--- + Use Ctrl-@ NULL(0x0) inputs to determine whether panic system + config TTY_SIGINT bool "Support SIGINT" default n diff --git a/drivers/serial/serial_dma.c b/drivers/serial/serial_dma.c index 6e220f1caae..6c04600102e 100644 --- a/drivers/serial/serial_dma.c +++ b/drivers/serial/serial_dma.c @@ -39,6 +39,7 @@ #include +#include #include #include #include @@ -70,22 +71,31 @@ * ****************************************************************************/ -#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) -static int uart_check_signo(const char *buf, size_t size) +#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \ + defined(CONFIG_TTY_FORCE_PANIC) +static int uart_check_signo(int pid, const char *buf, size_t size) { size_t i; for (i = 0; i < size; i++) { +#ifdef CONFIG_TTY_FORCE_PANIC + if (buf[i] == CONFIG_TTY_FORCE_PANIC_CHAR) + { + PANIC(); + return 0; + } +#endif + #ifdef CONFIG_TTY_SIGINT - if (buf[i] == CONFIG_TTY_SIGINT_CHAR) + if (pid > 0 && buf[i] == CONFIG_TTY_SIGINT_CHAR) { return SIGINT; } #endif #ifdef CONFIG_TTY_SIGTSTP - if (buf[i] == CONFIG_TTY_SIGTSTP_CHAR) + if (pid > 0 && buf[i] == CONFIG_TTY_SIGTSTP_CHAR) { return SIGTSTP; } @@ -109,7 +119,8 @@ static int uart_check_signo(const char *buf, size_t size) ****************************************************************************/ #if defined(CONFIG_SERIAL_RXDMA) && \ - (defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)) + (defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \ + defined(CONFIG_TTY_FORCE_PANIC)) static int uart_recvchars_signo(FAR uart_dev_t *dev) { FAR struct uart_dmaxfer_s *xfer = &dev->dmarx; @@ -119,19 +130,20 @@ static int uart_recvchars_signo(FAR uart_dev_t *dev) if (xfer->nbytes <= xfer->length) { - return uart_check_signo(xfer->buffer, xfer->nbytes); + return uart_check_signo(dev->pid, xfer->buffer, xfer->nbytes); } else { /* REVISIT: Additional signals could be in the second region. */ - signo = uart_check_signo(xfer->buffer, xfer->length); + signo = uart_check_signo(dev->pid, xfer->buffer, xfer->length); if (signo != 0) { return signo; } - return uart_check_signo(xfer->nbuffer, xfer->nbytes - xfer->length); + return uart_check_signo(dev->pid, xfer->nbuffer, + xfer->nbytes - xfer->length); } } #endif @@ -371,14 +383,15 @@ void uart_recvchars_done(FAR uart_dev_t *dev) FAR struct uart_dmaxfer_s *xfer = &dev->dmarx; FAR struct uart_buffer_s *rxbuf = &dev->recv; size_t nbytes = xfer->nbytes; -#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) +#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) || \ + defined(CONFIG_TTY_FORCE_PANIC) int signo = 0; /* Check if the SIGINT character is anywhere in the newly received DMA * buffer. */ - if (dev->pid >= 0 && (dev->tc_lflag & ISIG)) + if ((dev->tc_lflag & ISIG)) { signo = uart_recvchars_signo(dev); } diff --git a/drivers/serial/serial_io.c b/drivers/serial/serial_io.c index ddd4c3a99e4..a9ce9a2db8c 100644 --- a/drivers/serial/serial_io.c +++ b/drivers/serial/serial_io.c @@ -44,6 +44,7 @@ # include #endif +#include #include #include #include @@ -256,6 +257,17 @@ void uart_recvchars(FAR uart_dev_t *dev) } else #endif +#ifdef CONFIG_TTY_FORCE_PANIC + /* Is this the special character that will generate the SIGTSTP + * signal? + */ + + if ((dev->tc_lflag & ISIG) && ch == CONFIG_TTY_FORCE_PANIC_CHAR) + { + PANIC(); + } + else +#endif /* If the RX buffer becomes full, then the serial data is discarded. * This is necessary because on most serial hardware, you must read