Skip to content

HWCDC.h needs a clearTxBuffer() function for ESP32C3 USBCDC to work properly #7779

Closed
@specternecter

Description

@specternecter

Related area

Board Support

Hardware specification

Support for ESP32C3

Is your feature request related to a problem?

https://github.com/espressif/arduino-esp32/issues/6089

Describe the solution you'd like

It needs a function to clear the TX Buffer or anything in there will be printed when port is opened, It would seem that data should be held and printed when the port is opened, but that's actually a significant problem as the sketch below demonstrates.

Describe alternatives you've considered

I tried toggling the setTxBufferSize() but it only slightly helps. I tried many others that didn't help at all and mostly only created more problems. As a temporary solution, I added the waitForCDC variable to mask the issue, but it's designed so that the board will only run if the port is open when the variable is set to true.

Additional context

The following sketch demonstrates why this function is necessary. The USBSerial example in the IDE is absolutely wrong for the ESP32C3. I fixed it, along with fixing many other issues I've seen people post about or personally experienced. If you run this proposed example sketch, leave the port closed for at least 15 seconds and then open it. The longer it's closed, the more noticeable the need for a clearTxBuffer() function is. It will print the bootloader start message and the first 13 counts, then start printing what it's supposed to print.

#if !ARDUINO_USB_CDC_ON_BOOT
  #error USB CDC Ob Boot must be enabled to use this sketch
#endif

volatile bool usbActive; // when port is open, this is true. When closed, it's false.
bool waitForCDC = false; /* device resets every time port is CLOSED. This waits for
                           port to be open before running. */
unsigned long timer; // for non-blocking delay
unsigned long secondsActive = 0; // counts how many seconds since last start

static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
    arduino_hw_cdc_event_data_t * data = (arduino_hw_cdc_event_data_t*)event_data;
    switch (event_id){
      case ARDUINO_HW_CDC_CONNECTED_EVENT:
      
        // ***** clearTxBuffer() should go here *****
        
        Serial.println("\nCDC CONNECTED\n");
        usbActive = true;
        break;
      case ARDUINO_HW_CDC_BUS_RESET_EVENT:
        Serial.println("CDC BUS RESET");
        break;
      case ARDUINO_HW_CDC_RX_EVENT:
        Serial.printf("CDC RX EVENT [%u]: ", data->rx.len);
        {
          uint8_t buf[data->rx.len];
          size_t len = Serial.read(buf, data->rx.len);
          Serial.write(buf, len);
        }
        Serial.println();
        break;
      case ARDUINO_HW_CDC_TX_EVENT:
        // No example provided
        break;
      case ARDUINO_HW_CDC_MAX_EVENT:
        // No example provided
        break;
      default:
        break;
  }
}

void setup() {
  Serial.setTxBufferSize(256); // already the default, but setting for example purposes
  Serial.setRxBufferSize(256); // already the default, but setting for example purposes
  Serial.onEvent(usbEventCallback); // monitors port for status changes
  Serial.begin(); // start the CDC port

  if(waitForCDC){ // stays here until port open if waitForCDC == true
    if(usbActive == false){
      while(usbActive == false){} // wait here on start until CDC port is opened
      delay(1000);
    }
  }
  timer = millis() + 1000; // set timer to 1 second from now
}

void loop() {
  if(usbActive){
    Serial.setTxTimeoutMs(100); // recommended value when port is open.
  } else {
    //The following is ABSOLUTELY NECESSARY when the port is closed!
    //Otherwise, Serial writes will hang and sketch may not run properly.
    Serial.setTxTimeoutMs(0); // NECESSARY value when port is closed.
  }
  if(millis() > timer){ // if 1 second has passed
    secondsActive++; // increment seconds count
    Serial.print("Seconds Active: "); Serial.println(secondsActive);
    timer = millis() + 1000; // reset timer to 1 second from now
  }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions