Skip to content

Commit 8ededdb

Browse files
committed
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 <moura.fmo@gmail.com> Assisted-by: Claude:claude-sonnet-5
1 parent 3a8bd97 commit 8ededdb

1 file changed

Lines changed: 145 additions & 139 deletions

File tree

arch/xtensa/src/esp32s3/esp32s3_serial.c

Lines changed: 145 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,11 @@
101101
# endif
102102
#endif /* CONSOLE_UART */
103103

104-
#ifdef CONFIG_ESP32S3_USBSERIAL
104+
#if defined(CONFIG_ESP32S3_USBSERIAL) && !defined(CONSOLE_DEV)
105105
# define CONSOLE_DEV g_uart_usbserial
106+
#endif
107+
108+
#ifdef CONFIG_ESP32S3_USBSERIAL
106109
# define TTYACM0_DEV g_uart_usbserial
107110
#endif
108111

@@ -855,194 +858,196 @@ static int esp32s3_ioctl(struct file *filep, int cmd, unsigned long arg)
855858
{
856859
#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
857860

858-
/* Get the internal driver data structure for debug purposes. */
859-
860-
case TIOCSERGSTRUCT:
861-
{
862-
struct esp32s3_uart_s *user = (struct esp32s3_uart_s *)arg;
863-
if (user == NULL)
864-
{
865-
ret = -EINVAL;
866-
}
867-
else
868-
{
869-
memcpy(user, dev->priv, sizeof(struct esp32s3_uart_s));
870-
}
871-
}
872-
break;
861+
/* Get the internal driver data structure for debug purposes. */
862+
863+
case TIOCSERGSTRUCT:
864+
{
865+
struct esp32s3_uart_s *user = (struct esp32s3_uart_s *)arg;
866+
867+
if (user == NULL)
868+
{
869+
ret = -EINVAL;
870+
}
871+
else
872+
{
873+
memcpy(user, dev->priv, sizeof(struct esp32s3_uart_s));
874+
}
875+
}
876+
break;
873877
#endif
874878

875879
#ifdef CONFIG_SERIAL_TERMIOS
876880

877-
/* Fill a termios structure with the required information. */
881+
/* Fill a termios structure with the required information. */
882+
883+
case TCGETS:
884+
{
885+
struct termios *termiosp = (struct termios *)arg;
886+
struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
878887

879-
case TCGETS:
880-
{
881-
struct termios *termiosp = (struct termios *)arg;
882-
struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
883-
if (termiosp == NULL)
884-
{
885-
ret = -EINVAL;
886-
break;
887-
}
888+
if (termiosp == NULL)
889+
{
890+
ret = -EINVAL;
891+
break;
892+
}
888893

889-
/* Return parity (0 = no parity, 1 = odd parity, 2 = even parity). */
894+
/* Return parity (0 = no, 1 = odd, 2 = even). */
890895

891-
termiosp->c_cflag = (priv->parity != 0 ? PARENB : 0) |
892-
(priv->parity == 1 ? PARODD : 0);
896+
termiosp->c_cflag = (priv->parity != 0 ? PARENB : 0) |
897+
(priv->parity == 1 ? PARODD : 0);
893898

894-
/* Return stop bits */
899+
/* Return stop bits */
895900

896-
termiosp->c_cflag |= priv->stop_b2 != 0 ? CSTOPB : 0;
901+
termiosp->c_cflag |= priv->stop_b2 != 0 ? CSTOPB : 0;
897902

898903
#ifdef CONFIG_SERIAL_OFLOWCONTROL
899-
termiosp->c_cflag |= priv->oflow != 0 ? CCTS_OFLOW : 0;
904+
termiosp->c_cflag |= priv->oflow != 0 ? CCTS_OFLOW : 0;
900905
#endif
901906
#ifdef CONFIG_SERIAL_IFLOWCONTROL
902-
termiosp->c_cflag |= priv->iflow != 0 ? CRTS_IFLOW : 0;
907+
termiosp->c_cflag |= priv->iflow != 0 ? CRTS_IFLOW : 0;
903908
#endif
904909

905-
/* Set the baud rate in the termiosp using the
906-
* cfsetispeed interface.
907-
*/
908-
909-
cfsetispeed(termiosp, priv->baud);
910-
911-
/* Return number of bits. */
912-
913-
switch (priv->bits)
914-
{
915-
case 5:
916-
termiosp->c_cflag |= CS5;
917-
break;
918-
919-
case 6:
920-
termiosp->c_cflag |= CS6;
921-
break;
922-
923-
case 7:
924-
termiosp->c_cflag |= CS7;
925-
break;
926-
927-
default:
928-
case 8:
929-
termiosp->c_cflag |= CS8;
930-
break;
931-
}
932-
}
933-
break;
934-
935-
case TCSETS:
936-
{
937-
struct termios *termiosp = (struct termios *)arg;
938-
struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
939-
uint32_t baud;
940-
uint32_t current_int_sts;
941-
uint8_t parity;
942-
uint8_t bits;
943-
uint8_t stop2;
910+
/* Set the baud rate in the termiosp using the
911+
* cfsetispeed interface.
912+
*/
913+
914+
cfsetispeed(termiosp, priv->baud);
915+
916+
/* Return number of bits. */
917+
918+
switch (priv->bits)
919+
{
920+
case 5:
921+
termiosp->c_cflag |= CS5;
922+
break;
923+
924+
case 6:
925+
termiosp->c_cflag |= CS6;
926+
break;
927+
928+
case 7:
929+
termiosp->c_cflag |= CS7;
930+
break;
931+
932+
default:
933+
case 8:
934+
termiosp->c_cflag |= CS8;
935+
break;
936+
}
937+
}
938+
break;
939+
940+
case TCSETS:
941+
{
942+
struct termios *termiosp = (struct termios *)arg;
943+
struct esp32s3_uart_s *priv = (struct esp32s3_uart_s *)dev->priv;
944+
uint32_t baud;
945+
uint32_t current_int_sts;
946+
uint8_t parity;
947+
uint8_t bits;
948+
uint8_t stop2;
944949
#ifdef CONFIG_SERIAL_IFLOWCONTROL
945-
bool iflow;
950+
bool iflow;
946951
#endif
947952
#ifdef CONFIG_SERIAL_OFLOWCONTROL
948-
bool oflow;
953+
bool oflow;
949954
#endif
950955

951-
if (termiosp == NULL)
952-
{
953-
ret = -EINVAL;
954-
break;
955-
}
956+
if (termiosp == NULL)
957+
{
958+
ret = -EINVAL;
959+
break;
960+
}
956961

957-
/* Get the target baud rate to change. */
962+
/* Get the target baud rate to change. */
958963

959-
baud = cfgetispeed(termiosp);
964+
baud = cfgetispeed(termiosp);
960965

961-
/* Decode number of bits. */
966+
/* Decode number of bits. */
962967

963-
switch (termiosp->c_cflag & CSIZE)
964-
{
965-
case CS5:
966-
bits = 5;
967-
break;
968+
switch (termiosp->c_cflag & CSIZE)
969+
{
970+
case CS5:
971+
bits = 5;
972+
break;
968973

969-
case CS6:
970-
bits = 6;
971-
break;
974+
case CS6:
975+
bits = 6;
976+
break;
972977

973-
case CS7:
974-
bits = 7;
975-
break;
978+
case CS7:
979+
bits = 7;
980+
break;
976981

977-
case CS8:
978-
bits = 8;
979-
break;
982+
case CS8:
983+
bits = 8;
984+
break;
980985

981-
default:
982-
ret = -EINVAL;
983-
break;
984-
}
986+
default:
987+
ret = -EINVAL;
988+
break;
989+
}
985990

986-
/* Decode parity. */
991+
/* Decode parity. */
987992

988-
if ((termiosp->c_cflag & PARENB) != 0)
989-
{
990-
parity = (termiosp->c_cflag & PARODD) != 0 ? 1 : 2;
991-
}
992-
else
993-
{
994-
parity = 0;
995-
}
993+
if ((termiosp->c_cflag & PARENB) != 0)
994+
{
995+
parity = (termiosp->c_cflag & PARODD) != 0 ? 1 : 2;
996+
}
997+
else
998+
{
999+
parity = 0;
1000+
}
9961001

997-
/* Decode stop bits. */
1002+
/* Decode stop bits. */
9981003

999-
stop2 = (termiosp->c_cflag & CSTOPB) != 0 ? 1 : 0;
1004+
stop2 = (termiosp->c_cflag & CSTOPB) != 0 ? 1 : 0;
10001005

10011006
#ifdef CONFIG_SERIAL_IFLOWCONTROL
1002-
iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
1007+
iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
10031008
#endif
10041009
#ifdef CONFIG_SERIAL_OFLOWCONTROL
1005-
oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
1010+
oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
10061011
#endif
10071012

1008-
/* Verify that all settings are valid before
1009-
* performing the changes.
1010-
*/
1013+
/* Verify that all settings are valid before
1014+
* performing the changes.
1015+
*/
10111016

1012-
if (ret == OK)
1013-
{
1014-
/* Fill the private struct fields. */
1017+
if (ret == OK)
1018+
{
1019+
/* Fill the private struct fields. */
10151020

1016-
priv->baud = baud;
1017-
priv->parity = parity;
1018-
priv->bits = bits;
1019-
priv->stop_b2 = stop2;
1021+
priv->baud = baud;
1022+
priv->parity = parity;
1023+
priv->bits = bits;
1024+
priv->stop_b2 = stop2;
10201025
#ifdef CONFIG_SERIAL_IFLOWCONTROL
1021-
priv->iflow = iflow;
1026+
priv->iflow = iflow;
10221027
#endif
10231028
#ifdef CONFIG_SERIAL_OFLOWCONTROL
1024-
priv->oflow = oflow;
1029+
priv->oflow = oflow;
10251030
#endif
10261031

1027-
/* Effect the changes immediately - note that we do not
1028-
* implement TCSADRAIN or TCSAFLUSH, only TCSANOW option.
1029-
* See nuttx/libs/libc/termios/lib_tcsetattr.c
1030-
*/
1032+
/* Effect the changes immediately - note that we do not
1033+
* implement TCSADRAIN or TCSAFLUSH, only TCSANOW option.
1034+
* See nuttx/libs/libc/termios/lib_tcsetattr.c
1035+
*/
10311036

1032-
esp32s3_lowputc_disable_all_uart_int(priv, &current_int_sts);
1033-
ret = esp32s3_setup(dev);
1037+
esp32s3_lowputc_disable_all_uart_int(priv, &current_int_sts);
1038+
ret = esp32s3_setup(dev);
10341039

1035-
/* Restore the interrupt state */
1040+
/* Restore the interrupt state */
10361041

1037-
esp32s3_lowputc_restore_all_uart_int(priv, &current_int_sts);
1038-
}
1039-
}
1040-
break;
1042+
esp32s3_lowputc_restore_all_uart_int(priv, &current_int_sts);
1043+
}
1044+
}
1045+
break;
10411046
#endif /* CONFIG_SERIAL_TERMIOS */
10421047

1043-
default:
1044-
ret = -ENOTTY;
1045-
break;
1048+
default:
1049+
ret = -ENOTTY;
1050+
break;
10461051
}
10471052

10481053
return ret;
@@ -1086,6 +1091,7 @@ static bool esp32s3_rxflowcontrol(struct uart_dev_s *dev,
10861091
{
10871092
bool ret = false;
10881093
struct esp32s3_uart_s *priv = dev->priv;
1094+
10891095
if (priv->iflow)
10901096
{
10911097
if (nbuffered == 0 || upper == false)

0 commit comments

Comments
 (0)