Add Half Duplex support for HardwareSerial (T3.x, T4.x, TLC)

KurtE

Senior Member+
As I mentioned yesterday in the thread: https://forum.pjrc.com/threads/6265...lf-duplex-UART?p=252017&viewfull=1#post252017

Awhile ago I had a version of Core that had support for Serial Half duplex that was working for most Serial ports for T3.x and T4.x.

It was part of an earlier Pull request, which had other things as well. Much of which was pulled in earlier:
https://github.com/PaulStoffregen/cores/pull/419

So as there has been maybe three threads in the last week or so talking about need for half duplex, I decided to migrate those changes back to the current sources (master)

And go through a test cycle and flesh out the pieces I was missing.

So I moved it over and tested on T4.1 for Serial1-8, found a bug in earlier stuff for the TX Select input information for Serial1, which I fixed.

I then tested on T3.5 and worked for Serial1-6

Then went to T3.6 to add support for Serial6 (LPUART not UART)... Now working:

Side Note:
This was a royal pain, as nothing I tried worked... Finally this morning, I tried another version of the code and Serial6 was not working in normal mode either... So then tried HiLow test and found out D48 did not work on this board :0 I think a solder joint on the SMT pads... So hard to get to... So pulled out different T3.6 that had bottom pads... Would not start, but figured out USB port connections a bit off... pressed on USB connector now working...

Also added support for T-LC - and tested on Serial1-3...

So issued Pull Request: https://github.com/PaulStoffregen/cores/pull/489/

In case anyone wishes to try out, here is simple test sketch...
Code:
#define DEBUG_PIN 2
#define LOOP_DELAY_MS 50

#ifndef SERIAL_HALF_DUPLEX
#error Requires Teensy core with half duplex support
#endif
#define FORMAT SERIAL_HALF_DUPLEX
// Serial3 information - Say this is our Main Serial port
#define SERIALM Serial6
#define SERIALE Serial1
#define SERIAL_BAUD 115200
elapsedMillis  em_last_recv;
uint8_t receive_buffer[80];
uint8_t receive_index = 0;

void setup() {
  while (!Serial && millis() < 5000) ; // wait up to 5 seconds for terminal monitor
  pinMode(DEBUG_PIN, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);

  // Setup Serial3 for Half duplex:
  //SERIALM.setTX(53);
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#ifdef FORMAT
  Serial.printf("Serial ports using format %x\n", FORMAT);
  SERIALM.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we arer
#else
  Serial.println("Serial ports using default format");
  SERIALM.begin(SERIAL_BAUD); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD); // would probably want to see how close we arer
#endif
  
  Serial.println("After Serial begins"); Serial.flush();
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#if 0
  Serial.printf("LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
  LPUART0_CTRL = LPUART0_CTRL & ~(LPUART_CTRL_TE);
  Serial.printf("After turn of TE? LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
#endif
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
  em_last_recv = 0;
}

uint32_t loop_count = 0;

void loop() {
  // Lets see if we have anything coming in on the Echo PORT
  if (SERIALE.available()) {
    digitalWriteFast(5, HIGH);
    while (SERIALE.available()) {
      uint8_t ch = SERIALE.read();
      receive_buffer[receive_index++] = ch;
      if (ch == '\n') {
        receive_buffer[receive_index] = 0;  // Null terminate.
        // BUGBUG:: Put in line instead of calls
        SERIALE.write((char*)receive_buffer);
        receive_index = 0;
      }
      em_last_recv = 0;
    }
    digitalWriteFast(5, LOW);
  }

  // Lets see if we have anything coming in on the main port
  if (SERIALM.available()) {
    digitalWriteFast(4, HIGH);
    while (SERIALM.available()) {
      uint8_t ch = SERIALM.read();
      Serial.write(ch);
      em_last_recv = 0;
    }
    digitalWriteFast(4, LOW);
  }

  if (em_last_recv > LOOP_DELAY_MS) {
    digitalToggleFast(13);
    // output new packet
    SERIALM.printf("Loop: %d\n", loop_count++);
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
    em_last_recv = 0;
  }
}

@Paul let me know if this looks reasonable and/or if you see anything you would like changed!

Kurt
 
Back
Top