Is 4.25 Mbps the hardware limit or only the officially validated baud rate?

Hi,

I am using a Jetson Orin Nano Developer Kit (JetPack 6.x) and I would like to use one of the UART ports for high-speed communication with an external real-time controller.

However, I found inconsistent information regarding the maximum supported UART baud rate.

The latest Jetson Orin Nano Series Data Sheet (DS-11105-001 v1.7) states in the document history:

“UART block frequency from 200 MHz to 68 MHz and baud rate from 12.5 Mbps to 4.25 Mbps.”

So it seems that the official maximum UART baud rate for Orin Nano is 4.25 Mbps.

However, I also found:

  • older Orin datasheets mentioning 12.5 Mbps
  • forum discussions mentioning that the UART controller supports 12.5 Mbaud
  • discussions about using custom baud rates with termios2 (BOTHER).

My questions are:

  1. For the Jetson Orin Nano Developer Kit, what is the actual hardware maximum UART baud rate?
  2. Is 4.25 Mbps a hardware limitation or only the officially validated value?
  3. Is it possible to configure 10 Mbps UART using termios2/BOTHER, or is that beyond the capability of the UART hardware?
  4. Has anyone successfully used UART above 4.25 Mbps on Orin Nano?

Thanks!

Long ago there was a discovery that the clock used with the UART was slightly out of tolerance. The design was inherited from long ago when people did not normally use the higher rates. As a result, some of the higher end rates only worked if there were settings which allowed for better tolerance of those higher rates. This included use of CTS/RTS and two stop bits. With those I think the baud rate approached the higher numbers to around 10 Mbps, but not 12. All of this is from memory though so I couldn’t tell you specifics.

People have often used a separate USB UART for this reason, especially if the device they were communicating with could not enable CTS/RTS or two stop bits.

Hi zhuoyue526,

What’s the exact Jetpack 6 version in use?

On Jetson Orin Nano Developer Kit with standard JetPack/L4T configuration, the practical supported UART maximum should be treated as 4.25 Mbps.
The earlier 12.5/12.75 Mbaud references reflect T234 UART IP capability or special internal validation/override cases, not the default product configuration on general UARTs.
Therefore, using termios2/BOTHER does not make 10 Mbps supported if the underlying UART clock remains limited to 68 MHz.

Hi KevinFFF,

Thank you for your reply.

I am using JetPack 6.2.1 with L4T 36.4.7 on the Jetson Orin Nano Developer Kit.

I checked the BPMP clock limits of the UART controllers and obtained the following results:

serial@3100000 / ttyTHS1: max_rate = 68000000
serial@3140000 / ttyTHS2: max_rate = 68000000
serial@31d0000 / ttyAMA0: max_rate = 204000000

The kernel identifies serial@3100000 and serial@3140000 as TEGRA_UART, while serial@31d0000 is identified as an SBSA UART.

I also noticed that in the default device tree, only serial@3100000 has a pinctrl configuration, while I could not find a pinctrl entry for serial@3140000 or serial@31d0000.

Therefore, I understand that the two TEGRA UART interfaces are limited to 4.25 Mbps because:

68 MHz / 16 = 4.25 Mbps

However, UART-I at serial@31d0000 appears to support a maximum clock of 204 MHz, which would theoretically correspond to:

204 MHz / 16 = 12.75 Mbps

Could you please confirm:

  1. Can UART-I (serial@31d0000, /dev/ttyAMA0) be used for 10 Mbps communication on the Jetson Orin Nano Developer Kit?
  2. Is UART-I physically routed to any accessible pins on the standard developer kit carrier board?
  3. Is a pinmux/device-tree modification required to use UART-I externally?
  4. Under my current standard JetPack/L4T configuration and without modifying the device tree or pinmux, does this mean that I can only use serial@3100000 as an externally accessible UART, with a maximum supported baud rate of 4.25 Mbps?

Thank you.

Thanks for the detailed check.

From the current Jetson Orin Nano Developer Kit documentation, the externally documented UART interfaces are the J14 debug UART and the 40-pin header UART. At this time, I do not see documentation confirming that UART-I (serial@31d0000, /dev/ttyAMA0) is routed to an external connector on the standard developer kit carrier board.

So under the default JetPack/L4T configuration, /dev/ttyAMA0 should not be assumed to be a supported external 10 Mbps UART. Using UART-I externally would require board-routing and pinmux/device-tree confirmation.

If you really need 10MBps you should use an external PCIe UART in the M.2 slot.

Suggestion:

https://www.diodes.com/part/view/PI7C9X7952

(two port part, there are also 4 and 8 port parts)

This chip is rated up to 15 MBps in async mode. You need to choose a suitable baud rate crystal.

Linux should support this chip. Maybe you need to compile the driver as a module.

Thank you for the clarification.

So, for the externally available UART on the Jetson Orin Nano Developer Kit, should I assume that the practical maximum supported baud rate is about 4.25 Mbps?

Also, do you agree with the suggestion below to use an external PCIe UART through an M.2 slot for higher baud rates? I noticed that the M.2 slots on the Developer Kit are mainly intended for NVMe SSDs. Is this approach actually practical and officially supported?

Thank you for your suggestion.

May I ask if you have actually implemented this solution on the Jetson Orin Nano Developer Kit?

Specifically:

Which PCIe UART board did you use?
Which M.2 slot did you connect it to (Key-M or Key-E)?
Was it plug-and-play under JetPack/Linux, or did you need to modify the device tree or compile a custom driver?
Were you able to achieve a stable 10 Mbps UART communication?

I would really appreciate any practical experience or hardware recommendations.

I’ve developed several PCIe addons for NVidia systems, but not this specific chip. I’ve used some MaxLinear chip on an M.2 Type E card, but these ports didn’t need to be fast. That card was used in a ConnectTech board for Xavier NX. So no, I can’t send you a ready-to-use solution, but based on my experience that solution should work.

What I can say:

  • The Diodes/Pericom PCIe UARTs should be detected by the Linux 8250_PCI kernel module out of the box. You may need to tweak module command line parameters in order to match the clock frequency to the hardware.
  • NVidia does not include all kernel modules that are present for example on a Debian or Ubuntu Linux on PC hardware. You might need to compile the module on the Jetson hardware.
  • There is absolutely nothing NVidia specific in this solution. If you are going to design a board it might be easier to test on PC hardware first since the kernel modules are there out of the box.
  • Since this is a PCIe solution you don’t need to mess with device trees. PCIe is auto-config. The bus driver scans the bus, firnds the chip and loads the module that matches vendor/device id.
  • The chip needs a baud rate crystal. The default value is good for the standard baud rate (300,1200, 38400,115200), but you need a faster one for higher speeds. The datasheet says you can go up to 60 MHz. You need to calculate a suitable value in order to get 10 MHz bit rate. Instead of a crystal you also can (and i recommend this) use a crystal oscillator.
  • The UART chip only uses a single lane. If the Type E slot is available it makes sense to design for this. otherwise you can also use a Type M slot and leave the other lanes unused.

Hope that helps.

Linux should have a suitable kernel driver. You don’t need to

Yes, for the externally available UART on the standard Jetson Orin Nano Developer Kit, you should assume the practical maximum baud rate is about 4.25 Mbps.

As for using an external PCIe UART through the M.2 slot, the current Developer Guide describes the two PCIe slots on the developer kit as slots for NVMe storage devices. So I would not describe a PCIe UART card over M.2 as an officially supported standard developer-kit solution.

If higher UART bandwidth is required, that would be more of a custom hardware approach rather than the documented default path on the standard developer kit.

Is there any technical reason? PCIe is PCIe, and the device class I plug in should’t matter except for driver reasons. I’ve used PCIe high-speed cameras (Ximea), CamLink frame grabbers (Epix), Magewell SDI framegrabbers, Intel/Realtek Ethernet cards, Hailo AI accelerators and many more on Jetson Devkits for the last 9 years, and I didn’t have any issues except for incompatible firmware on Intel i210 with TX1/TX2 boards.

Yes, I agree it is technically possible.
PCIe itself is not limited by device type, so a PCIe UART device may work if the hardware and Linux driver support are in place.

My earlier point was only that, in the current Jetson Orin Nano Developer Kit documentation, the M.2 PCIe slots are described as NVMe slots, so this would be considered a custom solution rather than a standard documented UART path on the devkit.

Hi Kevin,

I implemented a UART loopback test on the Jetson Orin Nano Developer Kit using /dev/ttyTHS1 (TX connected directly to RX). The UART is configured with termios2 + BOTHER, and TCGETS2 confirms that the driver accepts the requested baud rate.

The test procedure is:

  • Configure the UART with the requested baud rate.

  • Start a receiver thread before transmission.

  • Transmit a fixed-size buffer (65536 bytes).

  • Call tcdrain() after write().

  • Measure:

    • TX time = from before write() until tcdrain() returns.
    • RX time = from the first received byte until the last received byte.
  • Estimate the baud rate from:

    baud ≈ transmitted_bits / measured_time

The measured results are:

Requested baud Measured result
150000 approximately 150 kbaud
1250000 approximately 1.23–1.24 Mbaud
2000000 approximately 1.91–1.96 Mbaud
2300000 approximately 2.25–2.30 Mbaud

At lower baud rates, the measured rate closely matches the requested value. However, once the requested baud exceeds about 2.5–2.7 Mbaud, the measured throughput seems to saturate around 2.6 Mbaud, even though:

  • TCGETS2 reports 4250000 baud,
  • all transmitted bytes are received correctly,
  • no data corruption occurs.

The result shown above was obtained with a C implementation. I repeated the test using Python and pySerial, and the measured throughput again saturated at approximately 2.5–2.6 Mbps.

From the Jetson documentation and your previous reply, I understand that the theoretical maximum UART baud rate should be around 4.25 Mbps.

My questions are:

  1. Is there any known hardware or driver limitation that would explain why the measured throughput saturates around 2.6 Mbps?
  2. Is there a recommended way from NVIDIA to verify the actual physical UART baud rate on Jetson (for example using specific registers or only an oscilloscope)?
  3. Is it possible to achieve 4–4.25 Mbps on /dev/ttyTHS1 in loopback mode? If so, are there additional UART, DMA, FIFO, clock, or driver settings that need to be configured? Or what should I check?

Any suggestions would be greatly appreciated.

Thank you!

Do you have an oscilloscope which can view the actual data TX and RX? It should be that period is about equal to 1/baud.

Possibility one is that the data rate is correct, but the system is not sending or receiving fast enough, and possibility two is that actual data rate slowed (or perhaps a mix, but it should be more obvious if the baud and period are approximately matching). The programmed clock rate won’t be a good test unless you know what divider is being used, although baud versus period might tell you if something is significantly “off” from what it should be.

Thank you for your reply.

Yes, I noticed this thread as well.

I’ll try to measure the UART TX and RX signal with an oscilloscope to verify the actual baud rate.

I do not think this points to a hard UART limit at 2.6 Mbaud.

We have seen /dev/ttyTHS1 loopback run at 3.6864 Mbaud with 0 errors, and we have also verified 4 Mbaud in loopback on Jetson. So if your result always saturates around 2.5–2.6 Mbaud, it is more likely related to the test method or software timing than to an actual UART baud ceiling.

In particular, measuring from write() to tcdrain(), or from first RX byte to last RX byte, does not directly measure the physical UART line rate because it also includes software scheduling and buffering effects.

If you want to verify the real baud on the wire, please check the TX signal directly with an oscilloscope or logic analyzer. You can also try a simpler loopback test with RTS/CTS connected if hardware flow control is enabled.

Thank you for the clarification.In my final system, the UART has to be converted to RS422, so unfortunately I cannot use RTS/CTS hardware flow control on the complete communication path. I performed some measurements with an oscilloscope. I agree now that the UART itself can reach approximately 4.25 Mbaud. My remaining questions are mainly about the electrical loading of the UART pins and real-time scheduling. I used the following Python code for these tests. During the experiments, I varied the timeout value and also tested both with and without the read() operation as experimental variables.

For Fig. 1 and Fig. 2, I tested a direct loopback on the Jetson UART. Fig. 1 shows TX measured with TX and RX disconnected, while Fig. 2 shows TX when TX and RX are connected for loopback. After connecting RX, the LOW level no longer reaches close to 0 V. I also noticed that when I added several additional Dupont wires, the received data became unreliable. Therefore, I suspect that the UART pins may be relatively sensitive to capacitive loading(oscilloscope probe) or additional wiring.

For Fig. 3 and Fig. 4, I connected a TTL-to-RS422 converter based on the SP3490E and powered the converter. I measured the TXD and RXD signals on the TTL side. Again, the LOW level was significantly raised compared with the unloaded TX signal.

According to the carrier-board documentation, the header signals appear to pass through TI TXB0108 level translators. Could the drive characteristics of the TXB0108 be responsible for this behavior when an external UART/RS422 transceiver is connected? Would you recommend adding an external buffer/driver between the Jetson UART pins and the RS422 transceiver instead of driving the transceiver input directly from the header?

I also observed another behavior during the RS422 loopback test.In Fig. 5 and Fig. 6, when I continuously call only write() and comment out read(), the spacing between transmitted data blocks becomes irregular. When I enable read() again, the spacing becomes much more regular.

Interestingly, in a Jetson-only TX-RX loopback test, both the write-only and write+read cases behave normally, so this phenomenon seems to appear mainly after the external RS422 converter is connected.

My second question concerns deterministic timing. My target application runs periodically, and I tested different timeout/write_timeout values. Most cycles complete normally, but occasionally a timeout still occurs. For a hard or near-hard real-time application, are there recommended Jetson configurations for UART communication, for example:

  • PREEMPT_RT / Jetson Real-Time Kernel
  • real-time thread priority (SCHED_FIFO)
  • CPU affinity / isolated CPU core
  • UART interrupt or DMA-related settings

In particular, can /dev/ttyTHS1 be used with a bounded and deterministic latency, or should occasional scheduling jitter still be expected even with the real-time kernel?

Thank you again for your help.

Thanks for sharing the scope plots.
Since you can now measure about 4.25 Mbaud on the line, this does not look like a UART clock-limit issue anymore.

It looks more like signal loading / signal-integrity on the devkit header path. The header-side UART signals go through TXB0108 level shifters, so your observation that the waveform becomes more sensitive after adding loopback wiring or the RS422 converter is reasonable.

For a multi-Mbaud RS422 design, I would keep the wiring and probe loading as small as possible, and I would consider using a stronger external buffer / line-driver path instead of relying on the devkit header path directly.

For latency, Jetson does provide a PREEMPT_RT kernel for Orin Nano / NX, but it is documented as Developer-Preview quality, and NVIDIA also notes that UEFI runtime services may increase latency. So lower jitter may be possible, but some scheduling jitter should still be expected.