This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 673b4245f77 xtensa/esp32s3: Fix CONSOLE_DEV clobbered by USBSERIAL
macro.
673b4245f77 is described below
commit 673b4245f77ba995f25e1b958720e6d12f59b1bd
Author: Felipe Moura <[email protected]>
AuthorDate: Thu Sep 3 12:15:17 2026 -0300
xtensa/esp32s3: Fix CONSOLE_DEV clobbered by USBSERIAL macro.
When a real UART (CONFIG_UARTx_SERIAL_CONSOLE) is selected as the
system console while CONFIG_ESP32S3_USBSERIAL is also enabled (e.g. to
keep /dev/ttyACM0 available as a secondary device alongside an
external console UART), the unconditional
#ifdef CONFIG_ESP32S3_USBSERIAL
# define CONSOLE_DEV g_uart_usbserial
#endif
block silently redefines CONSOLE_DEV, clobbering the correct earlier
definition that pointed it at the chosen UART device.
Confirmed on real hardware (Seeed XIAO ESP32-S3): with UART0 selected
as console and USBSERIAL also enabled, the board boot-looped on
RTCWDT_RTC_RST every ~8s, never reaching NSH. With this fix, NSH comes
up normally over UART0 and /dev/ttyACM0 remains available.
Signed-off-by: Felipe Moura <[email protected]>
Assisted-by: Claude:claude-sonnet-5
---
arch/xtensa/src/esp32s3/esp32s3_serial.c | 284 ++++++++++++++++---------------
1 file changed, 145 insertions(+), 139 deletions(-)
diff --git a/arch/xtensa/src/esp32s3/esp32s3_serial.c
b/arch/xtensa/src/esp32s3/esp32s3_serial.c
index 11d4b3f71c1..33d23f2251e 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_serial.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_serial.c
@@ -101,8 +101,11 @@
# endif
#endif /* CONSOLE_UART */
-#ifdef CONFIG_ESP32S3_USBSERIAL
+#if defined(CONFIG_ESP32S3_USBSERIAL) && !defined(CONSOLE_DEV)
# define CONSOLE_DEV g_uart_usbserial
+#endif
+
+#ifdef CONFIG_ESP32S3_USBSERIAL
# define TTYACM0_DEV g_uart_usbserial
#endif
@@ -855,194 +858,196 @@ static int esp32s3_ioctl(struct file *filep, int cmd,
unsigned long arg)
{
#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
- /* Get the internal driver data structure for debug purposes. */
-
- case TIOCSERGSTRUCT:
- {
- struct esp32s3_uart_s *user = (struct esp32s3_uart_s *)arg;
- if (user == NULL)
- {
- ret = -EINVAL;
- }
- else
- {
- memcpy(user, dev->priv, sizeof(struct esp32s3_uart_s));
- }
- }
- break;
+ /* Get the internal driver data structure for debug purposes. */
+
+ case TIOCSERGSTRUCT:
+ {
+ struct esp32s3_uart_s *user = (struct esp32s3_uart_s *)arg;
+
+ if (user == NULL)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ memcpy(user, dev->priv, sizeof(struct esp32s3_uart_s));
+ }
+ }
+ break;
#endif
#ifdef CONFIG_SERIAL_TERMIOS
- /* Fill a termios structure with the required information. */
+ /* Fill a termios structure with the required information. */
+
+ case TCGETS:
+ {
+ struct termios *termiosp = (struct termios *)arg;
+ struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
- case TCGETS:
- {
- struct termios *termiosp = (struct termios *)arg;
- struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
- if (termiosp == NULL)
- {
- ret = -EINVAL;
- break;
- }
+ if (termiosp == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
- /* Return parity (0 = no parity, 1 = odd parity, 2 = even parity). */
+ /* Return parity (0 = no, 1 = odd, 2 = even). */
- termiosp->c_cflag = (priv->parity != 0 ? PARENB : 0) |
- (priv->parity == 1 ? PARODD : 0);
+ termiosp->c_cflag = (priv->parity != 0 ? PARENB : 0) |
+ (priv->parity == 1 ? PARODD : 0);
- /* Return stop bits */
+ /* Return stop bits */
- termiosp->c_cflag |= priv->stop_b2 != 0 ? CSTOPB : 0;
+ termiosp->c_cflag |= priv->stop_b2 != 0 ? CSTOPB : 0;
#ifdef CONFIG_SERIAL_OFLOWCONTROL
- termiosp->c_cflag |= priv->oflow != 0 ? CCTS_OFLOW : 0;
+ termiosp->c_cflag |= priv->oflow != 0 ? CCTS_OFLOW : 0;
#endif
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- termiosp->c_cflag |= priv->iflow != 0 ? CRTS_IFLOW : 0;
+ termiosp->c_cflag |= priv->iflow != 0 ? CRTS_IFLOW : 0;
#endif
- /* Set the baud rate in the termiosp using the
- * cfsetispeed interface.
- */
-
- cfsetispeed(termiosp, priv->baud);
-
- /* Return number of bits. */
-
- switch (priv->bits)
- {
- case 5:
- termiosp->c_cflag |= CS5;
- break;
-
- case 6:
- termiosp->c_cflag |= CS6;
- break;
-
- case 7:
- termiosp->c_cflag |= CS7;
- break;
-
- default:
- case 8:
- termiosp->c_cflag |= CS8;
- break;
- }
- }
- break;
-
- case TCSETS:
- {
- struct termios *termiosp = (struct termios *)arg;
- struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
- uint32_t baud;
- uint32_t current_int_sts;
- uint8_t parity;
- uint8_t bits;
- uint8_t stop2;
+ /* Set the baud rate in the termiosp using the
+ * cfsetispeed interface.
+ */
+
+ cfsetispeed(termiosp, priv->baud);
+
+ /* Return number of bits. */
+
+ switch (priv->bits)
+ {
+ case 5:
+ termiosp->c_cflag |= CS5;
+ break;
+
+ case 6:
+ termiosp->c_cflag |= CS6;
+ break;
+
+ case 7:
+ termiosp->c_cflag |= CS7;
+ break;
+
+ default:
+ case 8:
+ termiosp->c_cflag |= CS8;
+ break;
+ }
+ }
+ break;
+
+ case TCSETS:
+ {
+ struct termios *termiosp = (struct termios *)arg;
+ struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
+ uint32_t baud;
+ uint32_t current_int_sts;
+ uint8_t parity;
+ uint8_t bits;
+ uint8_t stop2;
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- bool iflow;
+ bool iflow;
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
- bool oflow;
+ bool oflow;
#endif
- if (termiosp == NULL)
- {
- ret = -EINVAL;
- break;
- }
+ if (termiosp == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
- /* Get the target baud rate to change. */
+ /* Get the target baud rate to change. */
- baud = cfgetispeed(termiosp);
+ baud = cfgetispeed(termiosp);
- /* Decode number of bits. */
+ /* Decode number of bits. */
- switch (termiosp->c_cflag & CSIZE)
- {
- case CS5:
- bits = 5;
- break;
+ switch (termiosp->c_cflag & CSIZE)
+ {
+ case CS5:
+ bits = 5;
+ break;
- case CS6:
- bits = 6;
- break;
+ case CS6:
+ bits = 6;
+ break;
- case CS7:
- bits = 7;
- break;
+ case CS7:
+ bits = 7;
+ break;
- case CS8:
- bits = 8;
- break;
+ case CS8:
+ bits = 8;
+ break;
- default:
- ret = -EINVAL;
- break;
- }
+ default:
+ ret = -EINVAL;
+ break;
+ }
- /* Decode parity. */
+ /* Decode parity. */
- if ((termiosp->c_cflag & PARENB) != 0)
- {
- parity = (termiosp->c_cflag & PARODD) != 0 ? 1 : 2;
- }
- else
- {
- parity = 0;
- }
+ if ((termiosp->c_cflag & PARENB) != 0)
+ {
+ parity = (termiosp->c_cflag & PARODD) != 0 ? 1 : 2;
+ }
+ else
+ {
+ parity = 0;
+ }
- /* Decode stop bits. */
+ /* Decode stop bits. */
- stop2 = (termiosp->c_cflag & CSTOPB) != 0 ? 1 : 0;
+ stop2 = (termiosp->c_cflag & CSTOPB) != 0 ? 1 : 0;
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
+ iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
- oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
+ oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
#endif
- /* Verify that all settings are valid before
- * performing the changes.
- */
+ /* Verify that all settings are valid before
+ * performing the changes.
+ */
- if (ret == OK)
- {
- /* Fill the private struct fields. */
+ if (ret == OK)
+ {
+ /* Fill the private struct fields. */
- priv->baud = baud;
- priv->parity = parity;
- priv->bits = bits;
- priv->stop_b2 = stop2;
+ priv->baud = baud;
+ priv->parity = parity;
+ priv->bits = bits;
+ priv->stop_b2 = stop2;
#ifdef CONFIG_SERIAL_IFLOWCONTROL
- priv->iflow = iflow;
+ priv->iflow = iflow;
#endif
#ifdef CONFIG_SERIAL_OFLOWCONTROL
- priv->oflow = oflow;
+ priv->oflow = oflow;
#endif
- /* Effect the changes immediately - note that we do not
- * implement TCSADRAIN or TCSAFLUSH, only TCSANOW option.
- * See nuttx/libs/libc/termios/lib_tcsetattr.c
- */
+ /* Effect the changes immediately - note that we do not
+ * implement TCSADRAIN or TCSAFLUSH, only TCSANOW option.
+ * See nuttx/libs/libc/termios/lib_tcsetattr.c
+ */
- esp32s3_lowputc_disable_all_uart_int(priv, ¤t_int_sts);
- ret = esp32s3_setup(dev);
+ esp32s3_lowputc_disable_all_uart_int(priv, ¤t_int_sts);
+ ret = esp32s3_setup(dev);
- /* Restore the interrupt state */
+ /* Restore the interrupt state */
- esp32s3_lowputc_restore_all_uart_int(priv, ¤t_int_sts);
- }
- }
- break;
+ esp32s3_lowputc_restore_all_uart_int(priv, ¤t_int_sts);
+ }
+ }
+ break;
#endif /* CONFIG_SERIAL_TERMIOS */
- default:
- ret = -ENOTTY;
- break;
+ default:
+ ret = -ENOTTY;
+ break;
}
return ret;
@@ -1086,6 +1091,7 @@ static bool esp32s3_rxflowcontrol(struct uart_dev_s *dev,
{
bool ret = false;
struct esp32s3_uart_s *priv = dev->priv;
+
if (priv->iflow)
{
if (nbuffered == 0 || upper == false)