Skip to content

[ESP32-S3] UART0 pins cannot be assigned to UART1 or UART2 in 3.3.6 and later #12402

@nomakewan

Description

@nomakewan

Board

ESP32-S3 N16R8

Device Description

Both the ESP32-S3 N16R8 dev kit and a fully custom PCB using the ESP32-S3 N16R8 as a bare microcontroller with no CP2102 bridge chip.

Hardware Configuration

Board is in USB-CDC mode (pins 19/20 are connected to USB-C port), eFuse UART_PRINT_CONTROL is set to 0b11, eFuse DIS_PAD_JTAG is set to 0b1.

Version

v3.3.7

Type

Bug

IDE Name

Arduino IDE and VSCode with PlatformIO

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

yes

Upload speed

115200

Description

(Continued from #12277 and #12386)

On Arduino-ESP32 3.3.6 and later frameworks, pin 43 (by default, UART0 TX) cannot be reassigned to TX for UART1 or UART2. On Arduino-ESP32 3.3.5 or earlier, pin 43 can be reassigned to any UART peripheral on the micro without any issues.

Sketch

#include <Arduino.h>

#define TEST_INTERVAL 5000  // ms between tests
#define BAUD_RATE 115200
#define TEST_TIMEOUT 1000   // ms to wait for response

unsigned long serial1ToSerial0Success = 0;
unsigned long serial1ToSerial0Fail = 0;

unsigned long lastTestTime = 0;

void printUARTStatus(const char* name, HardwareSerial &serial) {
  Serial.printf("\n=== %s Status ===\n", name);
  Serial.printf("  Bytes available to read: %d\n", serial.available());
}

void printStats() {
  Serial.println("\n========== Serial Test Statistics ==========");
  Serial.printf("Serial1 -> Serial0: %lu passed, %lu failed (%.1f%% success)\n",
                serial1ToSerial0Success,
                serial1ToSerial0Fail,
                (serial1ToSerial0Success + serial1ToSerial0Fail) > 0
                  ? (100.0 * serial1ToSerial0Success / (serial1ToSerial0Success + serial1ToSerial0Fail))
                  : 0.0);
  Serial.println("============================================\n");
}

bool testSerialPair(HardwareSerial &sender, HardwareSerial &receiver, const char* direction) {
  static unsigned long testCounter = 0;
  testCounter++;
  String testMessage = String("TEST:") + testCounter + ":" + millis();

  Serial.printf("[%s] Sending: %s\n", direction, testMessage.c_str());

  // Clear receiver buffer
  while (receiver.available()) {
    receiver.read();
  }

  // Send test message
  sender.println(testMessage);
  sender.flush();

  // Debug: Check UART status after sending
  Serial.printf("[%s] After flush, checking receiver status...\n", direction);
  if (strcmp(direction, "S1->S0") == 0) {
    printUARTStatus("Serial0 (receiver)", receiver);
  } else {
    printUARTStatus("Serial1 (receiver)", receiver);
  }

  // Wait for response
  unsigned long startTime = millis();
  String received = "";
  bool success = false;
  int bytesRead = 0;

  while (millis() - startTime < TEST_TIMEOUT) {
    if (receiver.available()) {
      char c = receiver.read();
      bytesRead++;
      if (c == '\n') {
        break;
      }
      if (c != '\r') {
        received += c;
      }
    }
    delay(1);
  }

  // Verify received message
  Serial.printf("[%s] Read %d bytes, received: '%s'\n", direction, bytesRead, received.c_str());

  if (received == testMessage) {
    Serial.printf("[%s] SUCCESS - Message verified\n", direction);
    success = true;
  } else {
    Serial.printf("[%s] FAILED - Expected: %s, Got: %s\n",
                  direction, testMessage.c_str(),
                  received.length() > 0 ? received.c_str() : "(nothing)");
    success = false;
  }

  return success;
}

void setup() {
  setCpuFrequencyMhz(160);
  Serial.begin(115200);
  Serial0.end();

  Serial1.begin(9600, SERIAL_8N1, 44, 43);
  Serial0.begin(9600, SERIAL_8N1, 11, 10);
}

// The main loop of the program which manages all system operations which must occur on every loop.
void loop() {
  unsigned long currentTime = millis();

  if (currentTime - lastTestTime >= TEST_INTERVAL) {
    lastTestTime = currentTime;

    Serial.println("\n--- Testing Serial1 -> Serial0 ---");
    bool success = testSerialPair(Serial1, Serial0, "S1->S0");
    //bool success = testSerialPair(Serial0, Serial1, "S0->S1");
    if (success) {
      serial1ToSerial0Success++;
    } else {
      serial1ToSerial0Fail++;
    }

    if ((serial1ToSerial0Success + serial1ToSerial0Fail) % 2 == 0) {
      printStats();
    }
  }
}

Debug Message

=========== Before Setup Start ===========
Chip Info:
------------------------------------------
  Model             : ESP32-S3
  Package           : 0
  Revision          : 0.02
  Cores             : 2
  CPU Frequency     : 160 MHz
  XTAL Frequency    : 40012
  Embedded Flash    : No
  Embedded PSRAM    : No
  2.4GHz WiFi       : Yes
  Classic BT        : No
  BT Low Energy     : Yes
  IEEE 802.15.4     : No
------------------------------------------
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   390152 B ( 381.0 KB)
  Free Bytes        :   350972 B ( 342.7 KB)
  Allocated Bytes   :    33596 B (  32.8 KB)
  Minimum Free Bytes:   345824 B ( 337.7 KB)
  Largest Free Block:   294900 B ( 288.0 KB)
------------------------------------------
Flash Info:
------------------------------------------
  Chip Size         : 16777216 B (16 MB)
  Block Size        :    65536 B (  64.0 KB)
  Sector Size       :     4096 B (   4.0 KB)
  Page Size         :      256 B (   0.2 KB)
  Bus Speed         : 80 MHz
  Flash Frequency   : 80 MHz (source: 80 MHz, divider: 1)
  Bus Mode          : QIO
------------------------------------------
Partitions Info:
------------------------------------------
                nvs : addr: 0x00009000, size:    20.0 KB, type: DATA, subtype: NVS
            otadata : addr: 0x0000E000, size:     8.0 KB, type: DATA, subtype: OTA
               app0 : addr: 0x00010000, size:  1280.0 KB, type:  APP, subtype: OTA_0
               app1 : addr: 0x00150000, size:  1280.0 KB, type:  APP, subtype: OTA_1
             spiffs : addr: 0x00290000, size:  1408.0 KB, type: DATA, subtype: SPIFFS
           coredump : addr: 0x003F0000, size:    64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
  Compile Date/Time : Feb 23 2026 16:10:07
  Compile Host OS   : windows
  ESP-IDF Version   : v5.5.2-729-g87912cd291
  Arduino Version   : 3.3.7
------------------------------------------
Board Info:
------------------------------------------
  Arduino Board     : ESP32S3_DEV
  Arduino Variant   : esp32s3
  Arduino FQBN      : esp32:esp32:esp32s3:UploadSpeed=921600,USBMode=hwcdc,CDCOnBoot=cdc,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,CPUFreq=160,FlashMode=qio,FlashSize=16M,PartitionScheme=default,DebugLevel=debug,PSRAM=disabled,LoopCore=1,EventsCore=1,EraseFlash=none,JTAGAdapter=default,ZigbeeMode=default
============ Before Setup End ============
[  3586][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 19 already has type USB_DM (45) with bus 0x3fc98358
[  3586][I][esp32-hal-periman.c:141] perimanSetPinBus(): Pin 20 already has type USB_DP (46) with bus 0x3fc98358
[  3587][D][esp32-hal-uart.c:294] _uartDetachBus_RX(): _uartDetachBus_RX: RX pin already detached for UART0
[  3588][D][esp32-hal-uart.c:313] _uartDetachBus_TX(): _uartDetachBus_TX: TX pin already detached for UART0
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
  Total Size        :   390152 B ( 381.0 KB)
  Free Bytes        :   346228 B ( 338.1 KB)
  Allocated Bytes   :    37796 B (  36.9 KB)
  Minimum Free Bytes:   341080 B ( 333.1 KB)
  Largest Free Block:   294900 B ( 288.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
  GPIO : BUS_TYPE[bus/unit][chan]
  --------------------------------------  
    10 : UART_TX[0]
    11 : UART_RX[0]
    19 : USB_DM
    20 : USB_DP
    43 : UART_TX[1]
    44 : UART_RX[1]
============ After Setup End =============

--- Testing Serial1 -> Serial0 ---
[S1->S0] Sending: TEST:1:5000
[S1->S0] After flush, checking receiver status...

=== Serial0 (receiver) Status ===
  Bytes available to read: 0
[S1->S0] Read 0 bytes, received: ''
[S1->S0] FAILED - Expected: TEST:1:5000, Got: (nothing)

--- Testing Serial1 -> Serial0 ---
[S1->S0] Sending: TEST:2:10000
[S1->S0] After flush, checking receiver status...

=== Serial0 (receiver) Status ===
  Bytes available to read: 0
[S1->S0] Read 0 bytes, received: ''
[S1->S0] FAILED - Expected: TEST:2:10000, Got: (nothing)

========== Serial Test Statistics ==========
Serial1 -> Serial0: 0 passed, 2 failed (0.0% success)
============================================

Other Steps to Reproduce

Please note that while the debug sketch fails on Arduino-ESP32 3.3.6 and 3.3.7, it will work properly on 3.3.5 and earlier. This is not a hardware problem, nor is it in any way related to devkit boards having a CP2102 bridge chip onboard (our custom hardware has no such bridge chip and experiences the same issue with 3.3.6 and later frameworks).

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

Labels

Area: UARTRelated to the UART peripheral or its functionality.Status: Awaiting triageIssue is waiting for triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions