Hi! I have some noob-ish questions about the Teensy 4.0 UARTS and the associated hardwareserial.cpp code.
HW Configuration
Multiple, identical custom PCBs using Teensy 4.0 as an MCU module, all connected with a RS-485 serial bus using a custom protocol (some similarities to DMX-512).
One board is configured as a bus master, the rest are receive-only slaves. I'm using this RS-485 transceiver (https://www.maxlinear.com/ds/sp3070e-sp3078e.pdf) which supports up to 128 nodes. Here's a photo of the board (just to make this post more visually interesting):
Operational Concept
The master will transmit a small number of variable-length packets at a fixed cycle rate of 33 Hz (~30ms). The slaves will use the receive time of the first byte of the first packet in a cycle to synchronize their processing. The target data rate is 250 Kbps (40 us per byte). The master will cap the per-cycle transmit data quantity at about 380 bytes, which takes about 15ms or half of the cycle time. The slave devices will use the "sync" condition (1st byte received) to trigger their time-critical processing, and after that's done they will read and process the serial data received during that cycle. That's non-time-critical, as long as they finish before the start of the next cycle. This data is used to configure the synchronous processing in the following cycle.
Hardware Questions
I've seen conflicting information about the hardware buffers/FIFOs supported by the T4 processor. The RT1060 family reference manual seems to say that all 8 of the UARTs have only a 1 byte receive buffer, but elsewhere I've see multiple people say that two of the UARTs have a 4-byte FIFO (or 8-byte). That's somewhat important to me, as it relates to the software questions below. Which is correct?
Software Questions
I'd like to use Serial.available() to poll for the sync condition, but defer reading any of the data (other than maybe the first one or two bytes) until later in the cycle. The implies that the software receive buffer in hardwareserial.cpp must be at least 380 bytes. If I'm looking at the correct version on GitHub ( don't know where to find the version #), it looks like the receive buffer is hardcoded to 64 bytes.
I've see other posts talking about modifying hardwareserial.cpp to change the buffer sizes, but I had a hard time following the discussion and recommendations. Can someone please lay it out for me a little more clearly (assuming this is a reasonable thing to do)? It may be a little more challenging because I'm using Visual Studio Code with PlatformIO (MacOS), not the normal Arduino IDE. Also, I'm I'm not very familiar with C++ (only C) or the details of the board-specific build process.
If it's correct that the T4 UARTs have a 1-deep receive buffer, I assume that Serial.available() will return a non-zero value pretty much immediately upon receipt of the first byte. Is that correct? But...if it DID have a deeper FIFO, is it true that an interrupt wouldn't be triggered until the FIFO was full, or at some (configurable?) high-water mark? And then, is there a configurable IDLE timeout that will trigger in interrupt even if the high-water mark isn't reached? Just curious.
I'm also curious why the rx/tx buffer sizes aren't configurable except by re-compiling. This seems like a reasonable parameter for Serial.begin() or something similar. Not whining.
Sorry for being long-winded. Thanks for any help you can provide.
HW Configuration
Multiple, identical custom PCBs using Teensy 4.0 as an MCU module, all connected with a RS-485 serial bus using a custom protocol (some similarities to DMX-512).
One board is configured as a bus master, the rest are receive-only slaves. I'm using this RS-485 transceiver (https://www.maxlinear.com/ds/sp3070e-sp3078e.pdf) which supports up to 128 nodes. Here's a photo of the board (just to make this post more visually interesting):
Operational Concept
The master will transmit a small number of variable-length packets at a fixed cycle rate of 33 Hz (~30ms). The slaves will use the receive time of the first byte of the first packet in a cycle to synchronize their processing. The target data rate is 250 Kbps (40 us per byte). The master will cap the per-cycle transmit data quantity at about 380 bytes, which takes about 15ms or half of the cycle time. The slave devices will use the "sync" condition (1st byte received) to trigger their time-critical processing, and after that's done they will read and process the serial data received during that cycle. That's non-time-critical, as long as they finish before the start of the next cycle. This data is used to configure the synchronous processing in the following cycle.
Hardware Questions
I've seen conflicting information about the hardware buffers/FIFOs supported by the T4 processor. The RT1060 family reference manual seems to say that all 8 of the UARTs have only a 1 byte receive buffer, but elsewhere I've see multiple people say that two of the UARTs have a 4-byte FIFO (or 8-byte). That's somewhat important to me, as it relates to the software questions below. Which is correct?
Software Questions
I'd like to use Serial.available() to poll for the sync condition, but defer reading any of the data (other than maybe the first one or two bytes) until later in the cycle. The implies that the software receive buffer in hardwareserial.cpp must be at least 380 bytes. If I'm looking at the correct version on GitHub ( don't know where to find the version #), it looks like the receive buffer is hardcoded to 64 bytes.
I've see other posts talking about modifying hardwareserial.cpp to change the buffer sizes, but I had a hard time following the discussion and recommendations. Can someone please lay it out for me a little more clearly (assuming this is a reasonable thing to do)? It may be a little more challenging because I'm using Visual Studio Code with PlatformIO (MacOS), not the normal Arduino IDE. Also, I'm I'm not very familiar with C++ (only C) or the details of the board-specific build process.
If it's correct that the T4 UARTs have a 1-deep receive buffer, I assume that Serial.available() will return a non-zero value pretty much immediately upon receipt of the first byte. Is that correct? But...if it DID have a deeper FIFO, is it true that an interrupt wouldn't be triggered until the FIFO was full, or at some (configurable?) high-water mark? And then, is there a configurable IDLE timeout that will trigger in interrupt even if the high-water mark isn't reached? Just curious.
I'm also curious why the rx/tx buffer sizes aren't configurable except by re-compiling. This seems like a reasonable parameter for Serial.begin() or something similar. Not whining.
Sorry for being long-winded. Thanks for any help you can provide.