Does attachCts() work for XBAR pins on Teensy 4.1, Teensyduino 1.55?

Status
Not open for further replies.

CTRL

Member
Hi,

I thought, for Teensy 4.1, attachCts() accepts XBAR pins as well as the hardware-fixed CTS pin, as mentioned for instance in:

https://forum.pjrc.com/threads/49358-T3-6-USB-Host-Bluetooth?p=278928&viewfull=1#post278928

But it doesn't work as expected when I try today, using the following code:

Code:
#define DEBUG_MSG(...) { Serial.printf("%s(): ", __func__); Serial.printf(__VA_ARGS__); Serial.flush(); }

#define espSerial Serial3
#define ESPSERIAL_RTS_PIN 36
#define ESPSERIAL_CTS_PIN 30

void setup() {
    while (!Serial)
      ;
    espSerial.begin(115200);

    bool r;
    r = espSerial.attachRts(ESPSERIAL_RTS_PIN);
    DEBUG_MSG("espSerial.attachRts() returned %d\n", r);
    r = espSerial.attachCts(ESPSERIAL_CTS_PIN);
    DEBUG_MSG("espSerial.attachCts() returned %d\n", r);

    delay(1000);
    espSerial.print("AT+GMR\r\n");
}

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

Both attachCts() and attachRts() return 1, meaning the attaching was successful. But transmission does not work.

The problem is unlikely from wiring or anything other than the use of pin 30. In fact, I've confirmed that everything works well when I change "#define ESPSERIAL_CTS_PIN 30" to 19 (= originally assigned CTS for Serial3) and change wiring from 30 to 19. In this case transmission works well in both directions.

I took a quick look at the source of attachCts() in Teensyduino 1.55, and found that it has some code to deal with XBAR pins. I also found that pin 30 is an XBAR pin, due the following part of HardwareSerial.cpp of Teensyduino core. I tried a few times with some other SerialX (eg Serial8) and with some other XBAR pins, but it didn't work.

Code:
const pin_to_xbar_info_t PROGMEM pin_to_xbar_info[] = {
	{0,  17, 1, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x1},
	{1,  16, 1, nullptr, 0},
	{2,   6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x0},
	{3,   7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x0},
	{4,   8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x0},
	{5,  17, 3, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x0},
	{7,  15, 1, nullptr, 0 },
	{8,  14, 1, nullptr, 0},
	{30, 23, 1, &IOMUXC_XBAR1_IN23_SELECT_INPUT, 0x0},
	{31, 22, 1, &IOMUXC_XBAR1_IN22_SELECT_INPUT, 0x0},
	{32, 10, 1, nullptr, 0},
	{33,  9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x0},

#ifdef ARDUINO_TEENSY41
	{36, 16, 1, nullptr, 0},
	{37, 17, 1, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x3},
	{42,  7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x1},
	{43,  6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x1},
	{44,  5, 3, &IOMUXC_XBAR1_IN05_SELECT_INPUT, 0x1},
	{45,  4, 3, &IOMUXC_XBAR1_IN04_SELECT_INPUT, 0x1},
	{46,  9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x1},
	{47,  8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x1}
#else	
	{34,  7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x1},
	{35,  6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x1},
	{36,  5, 3, &IOMUXC_XBAR1_IN05_SELECT_INPUT, 0x1},
	{37,  4, 3, &IOMUXC_XBAR1_IN04_SELECT_INPUT, 0x1},
	{38,  9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x1},
	{39,  8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x1}
#endif
};

I'm curious, but I could't proceed to investigate the Teensyduino code further, because I don't understand the notion of "XBAR" yet. (By the way, what is a good source to learn about XBAR, other than the IMXRT manual?)

Any comment/help will be greatly appreciated!
 
Here is a simple program to test CTS by connecting one of the PWM pins to the CTS pin.

Code:
elapsedMillis timeout;
int count;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial1.attachCts(30); // connect pins 2 & 30
  analogWriteFrequency(2, 40);
  analogWrite(2, 128);
  timeout = 0;
  count = 0;
}

void loop() {
  Serial1.write(0x5A);
  count++;
  if (timeout > 1000) {
    timeout -= 1000;
    Serial.print(count);
    Serial.println("  bytes per second");
    count = 0;
  }
}

When I run this on a Teensy 4.1 with a wire connecting pins 2 and 30, these are the waveforms I see.

file.png

I also see this printed in the serial monitor window, indicating half of the possible 960 bytes each second are actually transmitting.

Code:
480  bytes per second
480  bytes per second
480  bytes per second
480  bytes per second
480  bytes per second
480  bytes per second
480  bytes per second
480  bytes per second
 
Tried again with Serial3 and also RTS on pin 36, just to try verifying as close as possible to the original case.

Code:
elapsedMillis timeout;
int count;

void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  Serial3.attachRts(36);
  Serial3.attachCts(30); // connect pins 2 & 30
  analogWriteFrequency(2, 40);
  analogWrite(2, 128);
  timeout = 0;
  count = 0;
}

void loop() {
  Serial3.write(0x5A);
  count++;
  if (timeout > 1000) {
    timeout -= 1000;
    Serial.print(count);
    Serial.println("  bytes per second");
    count = 0;
  }
}

Viewing TX3 (pin 14) instead of TX1, I see the same waveforms on my scope, and again it's printing 480 bytes per second.

I don't know why it's not working for communicating with that ESP board, but from this simple test it looks like CTS on pin 30 does indeed work, for both Serial1 and Serail3.
 
Thanks for your prompt replies!

I tested a while with your code. I think I found a wrong behavior of CTS: when I use the hardware CTS pin (19 for Serial3), it transmits when CTS is LOW, but when I use the XBAR CTS pin (30), it transmits when CTS is HIGH.

So, for the (second) test code using PWM, the transmission count is the same for both 19 and 30, and thus it looked like working... but it isn't indeed. If I connect both 19 and 30 to 2 and change analogWrite to "analogWrite(2, 16)", and if run your code with "Serial3.attachCts(30)", I get 80 bytes per second. But when I run the code with "Serial3.attachCts(19)", I get 920 bytes per seconds.

I don't understand how XBAR works yet, but as a very vague guess, perhaps what the IMXRT manual calls "AOI" might do something we don't want...
 
Yikes, yes, you're right. The polarity is backwards! That's definitely a bug in Teensy 4 hardware serial when CTS is connected by XBAR.
 
I'm looking at AOI in the IMXRT manual, to see at least what AOI could do for this issue. What I saw so far seems to tell that we can invert XBAR CTS input, using AOI, to implement an workaround for this "bug" ... Would it be possible, Paul?
 
I'm looking at the reference manual now. Sadly, I don't see a way to get the signal into either AOI. Their inputs can only come from XBAR2 and XBAR3. I don't see any path from the pins or from XBAR1 to the XBAR2 & XBAR3 inputs.

Pretty stunning to think NXP designed the chip this way, with the wrong CTS polarity when used by XBAR. Maybe I'm still missing something?
 
I looked a while ago, and as you found AOI looks like it can only work with xbar2, 3... as you mentioned.

At one point though of experimenting to see if one could find some route from IO pins like that maybe redirect through to some other pin, which may be part of some other sub-system that can then route through... Decided that was way to convoluted, for what I was looking at...

As for the XBar stuff with Hardwareserial... There was also an PR awhile ago but updates at least for setRX...
https://github.com/PaulStoffregen/cores/pull/593
 
Thanks for the information. I think now I have a slightly better understanding, including about inputs to AOI.

I think, too, it is rather surprising that the IMXRT has this sort of hardware bug that inverts CTS.

In the meantime, would it be helpful, to users, to mention this XBAR behavior on the updated UART page (https://www.pjrc.com/teensy/td_uart.html) at the least temporarily? I think the fact that some UART pins can be changed to XBAR pins must be helpful to users like me (e.g. I spent some time to find this fact, partly because the UART page didn't have this information previously). In spite of the unexpected XBAR inverting behavior/bug/feature(?), using XBAR pins for UART is still useful, especially because some default pin assignments may be inconvenient when other features (I2C, SD, flash) are used ...
 
I've updated the serial documentation page with this:

CTS polarity is inverted when connected through XBAR. Normally CTS is active low, meaning Teensy is allowed to transmit data when CTS is low, and must pause if CTS is driven high. But when using XBAR, Teensy transmits when the pin is logic high and pauses transmission while the pin is low.

The XBAR mentions in the pins table have a little red * which links to this footnote about CTS polarity.
 
Status
Not open for further replies.
Back
Top