Teensy 4.0 CTS pins

Status
Not open for further replies.

Wolfgang

Member
Hello,

I have checked the UART reference page but it hasn't been updated to include the Teensy 4, so l turned to looking at the code for HardwareSerial*.cpp (with thanks to Silvelock for the lead).

I see that Serial5 (UART8) is defined as “no CTS pin”:

Code:
static HardwareSerial::hardware_t UART8_Hardware = {
	4, IRQ_LPUART8, &IRQHandler_Serial5, &serial_event_check_serial5,
	CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON),
	#if defined(ARDUINO_TEENSY41)
	{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {46, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}},
	{{20,2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 1}, {47, 2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 0}},
	#else
	{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {38, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}},
	{{20,2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 1}, {39, 2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 0}},
	#endif
	0xff, // No CTS pin
	0, // No CTS
	IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial5(&IMXRT_LPUART8, &UART8_Hardware, tx_buffer5, SERIAL5_TX_BUFFER_SIZE,
	rx_buffer5,  SERIAL5_RX_BUFFER_SIZE);

Does this mean that I cannot use CTS at all on Serial5, or that I have to choose my own pin and pass it to attachCts()?
 
From my quick look through, it appears I may have missed this one when I defined the Serial5 object...

It appears like: pin 35 should work in mode 2... This is one of the pins on the SD Connector on bottom.

The data above should be changed to:
Code:
static HardwareSerial::hardware_t UART8_Hardware = {
	4, IRQ_LPUART8, &IRQHandler_Serial5, &serial_event_check_serial5,
	CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON),
	#if defined(ARDUINO_TEENSY41)
	{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {46, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}},
	{{20,2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 1}, {47, 2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 0}},
	#else
	{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {38, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}},
	{{20,2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 1}, {39, 2, &IOMUXC_LPUART8_TX_SELECT_INPUT, 0}},
	#endif
	35, // CTS pin
	 2, // CTS
	IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial5(&IMXRT_LPUART8, &UART8_Hardware, tx_buffer5, SERIAL5_TX_BUFFER_SIZE,
	rx_buffer5,  SERIAL5_RX_BUFFER_SIZE);

If you try it, let me know and will issue Pull request back to core.
 
It appears like: pin 35 should work in mode 2... This is one of the pins on the SD Connector on bottom.

Thanks KurtE, looks like we crossed posts. ☺

Ok, this conflicts with my SDIO use, so looks like I'll have to choose another port. The guy doing the routing for the motherboard will not be too happy. 😁
 
If you try it, let me know and will issue Pull request back to core.

If we were to make the above change to the source, will it not interfere with SDIO usage? i.e., would the user still need to use attachCts() for it to have any effect?

I figure that SDIO is a lot more popular than CTS on Serial5.

With that said, I can try easily to see if the above change works. I'll get back to you.
 
Yes you can only use a Pin for one thing at a time... So if you try to use it for CTS it would take it away from SD which is DATA0 signal...
Code:
35	SD_B0_02	3.14	Serial5(8) CTS		SPI2(1) MOSI	PWM1_A1			IO-06			DATA0

Edit: forgot to say, it only hurts SD if you acaully use the CTS... i.e. just having it in the table, hurts nothing.

Simply the AtachCts simply checks this value against the pin you passed in, to make sure it is valid. And if it is, then the other changes tells the system what configuration mode we need change the pin to.
 
About to test. There is something I don't understand, please see line 4:

Code:
void setup() {
  Serial.begin(115200);
  Serial5.begin(57600);
  Serial5.attachCts(35); // ←←← Why do I need to enter a pin number here?
}

void loop() {
  if (Serial.available()) {
    Serial5.write(Serial.read());
  }

  if (Serial5.available()) {
    Serial.write(Serial5.read());
  }
}
 
Because in theory, there could be Serial ports on one or more Teensy boards that may have more than one possible pin that works for this...
 
Why do I need to enter a pin number

attachCts(pin) is meant to be a generic API which can work on all future boards. So even when only 1 pin is capable of acting as CTS, we use this function where you have to specify the pin number. The idea is to keep the same function on all future boards, which may offer a choice of pins, or even be able to route signals to any pin.

FWIW, "attachCts" wasn't my choice. Cristian Maglie (of Arduino) came up with this name. The idea was for it to be used in some hypothetical future where Arduino will support RTS/CTS flow control on their boards. As far as I know, that day has not yet come. Since that conversation happened years ago, I doubt they'll remember. As seems unlikely they'll ever really support hardware flow control. But still, the name and API was decided years ago, so we use that convention on Teensy.
 
Brilliant, thanks for the info! I just noticed that this had been answered before, sorry about that.

I am about to test with an XBee radio as the CTS-capable device. CTS is enabled and I have confirmed this by seeing the CTS signal go high when I hammer the UART.

Anyone have any ideas for a good and simple test design?
 
Last edited:
I have tested with and without CTS and it doesn't seem to make a difference. :p

This is the test sketch:

Code:
#define HOST_SERIAL Serial
#define RADIO_SERIAL Serial5

unsigned count = 0, len=256, burst = 10, wait = 500;

void setup() {
  HOST_SERIAL.begin(115200);
  RADIO_SERIAL.begin(57600);
  RADIO_SERIAL.attachCts(35);
  delay(3000);
}

void loop() {
  while (count<100) {
    for (unsigned i=0; i<len; i++) {
      RADIO_SERIAL.write(count);
    }
    HOST_SERIAL.println(++count);
    if (count && !(count % burst)) {
      HOST_SERIAL.println("W");
      delay(wait);
    }
  }
}

It sends 100 packets of size len in bursts of burst with a pause of wait in between. I try this with and without attachCts(35). I either do not lose packets (for values of len=64, burst=16, so ≤1*KiB) or I do lose packets (e.g., len=64, burst=17) regardless of the CTS setting.

What is the expected behaviour? Does Serial5.write() block while /CTS is de-asserted (high), assuming that the tx buffer is already full? Does it fail?
 
I have tested with and without CTS and it doesn't seem to make a difference. :p

Now it does make a difference. I was plugged on the opposite end of my board, on an NC pin. Apologies for the confusion.

I'd still be interested to know what happens when CTS is de-asserted though.
 
Pinout summary

For reference, here is a table with the RTS / CTS pinout from the imxrt1062 according to the manual ± any typos of mine.

The TL;DR version is, if you need RTS / CTS on the Teensy 4.0, your choices are Serial3 and/or Serial5 (and for the latter, as of Teensduino 1.51, mind KurtE's post earlier in this thread):

Code:
Teensy serial | CTS Pin | RTS Pin
--------------|---------|---------
Serial3       |      19 |      18 
Serial5       |      35 |      34

The full pinout is as follows (check for typos!):

Code:
Teensy 4.0 CTS / RTS:

Teensy serial | Hardware UART | CTS (i.MX RT1062) | CTS Pin | RTS (i.MX RT1062) | RTS Pin
--------------|---------------|-------------------|---------|-------------------|--------
Serial1       | UART6         | GPIO_EMC_30       |      NC | GPIO_EMC_29       |     NC
Serial2       | UART4         | GPIO_EMC_17       |      NC | GPIO_EMC_18       |     NC 
Serial3       | UART2         | GPIO_AD_B1_00     |      19 | GPIO_AD_B1_01     |     18
Serial4       | UART3         | GPIO_EMC_15       |      NC | GPIO_AD_B1_05     |     NC
Serial4       | UART3         | GPIO_AD_B1_04     |      NC | GPIO_EMC_16       |     NC
Serial5       | UART8         | GPIO_SD_B0_02     |      35 | GPIO_SD_B0_03     |     34
Serial6       | UART1         | GPIO_AD_B0_14     |      NC | GPIO_AD_B0_15     |     NC
Serial7       | UART7         | GPIO_SD_B1_06     |      NC | GPIO_SD_B1_07     |     NC

Note that UART3 does have a choice of pins, although apparently only one pair of them (GPIO_AD_B1_04, GPIO_SD_B0_03) will be exposed in 4.1 as pins 40, 42.

HTH.
 
Status
Not open for further replies.
Back
Top