SPI TX Time Variability

System Specs:

Model: Jetson AGX Orin – Jetpack 5.1 [L4T 35.2.1]

Platform:

  • Distribution: Ubuntu 20.04 (Focal)
  • Kernel Release: 5.10.104-tegra

Good morning,

I am working with SPI communication on the Jetson AGX Orin and am encountering variability in TX times when sending data via SPI. While most transfers complete in approximately 100µs, I frequently observe significant outliers, which can impact applications requiring fast and consistent communication. I’ve attached a graph illustrating this variation.

I reviewed the Orin Jetson Series Pinmux Config Template to identify potential optimisations, but couldn’t figure out any obvious changes in order to make progress. Additionally, I have tested with Jetson clocks enabled to ensure maximum performance, which has noticeably improved results compared to when they are disabled (the graph attached reflects that).

I’d appreciate any guidance on improving SPI transfer consistency. Are there specific configurations, kernel parameters, or NVIDIA documentation that might help us reduce these outliers? Any relevant examples or insights would be greatly appreciated.

Thanks in advance for your help!

Hi,
On Jetson platforms, we support using peripherals like CAN, SPI, I2C, UART… etc. for the user.
For CAN usage:
https://docs.nvidia.com/jetson/archives/r36.3/DeveloperGuide/HR/ControllerAreaNetworkCan.html
For the connection of peripheral on the devkit, please refer to expansion-headers guide and carrier board specification:
https://docs.nvidia.com/jetson/archives/r36.3/DeveloperGuide/HR/ConfiguringTheJetsonExpansionHeaders.html

For pin configuration, please refer to pinmux spreadsheet:
https://developer.nvidia.com/embedded/secure/jetson/agx_orin/jetson_agx_orin_pinmux_config_template.xlsm

By default, the configuration is used for the devkit. If you are using the custom carrier board, please configure it according to your custom board design.

There are also several examples which have been verified from us, please check
https://elinux.org/Jetson/L4T/peripheral/
Please share the full dmesg and device tree for us to check your status in detail.

Thanks!

Hi carolyuu,

Thank you for replying and for the docs and links provided.

Please find the dmesg log and also the .dts file content below. For clarity, this is how I obtained them:

  1. sudo dmesg > dmesg.log
  2. dtc -I dtb -O dts -o tegra234-p3701-0000-p3737.dts /boot/dtb/kernel_tegra234-p3701-0000-p3737-0000.dtb

Please note that I changed the .dts file extension to .txt only so I could upload the file as the file uploader does not seem to support .dts extension.

tegra234-p3701-0000-p3737_dts.txt (525.8 KB)
dmesg.log (87.3 KB)

Please let me know if you can spot anything in there that may be related to the issue in discussion.

Thanks!

Hi francisco.silverio,

Are you using the devkit or custom board for AGX Orin?

Is your issue about the delay in SPI data transaction rather than it transfer failed?

It seems no error in the dmesg you shared.

Could you update to the latest Jetpack 5.1.4(r35.6.0) to verify if there’s still similar issue?

Please also try to apply the patch from Orin NX SPI delay between transfers - #21 by KevinFFF to check if it could help.

Hi KevinFFF,

Thank you for your reply.

I am using the AGX Orin Developer Kit with no custom configuration. The only modification I made was enabling the SPI pins via jetson-io.py. I have since tested this on Jetpack 6.2 (L4T 36.4.3), and I’m still encountering similar issues with SPI performance.

Here are the details of my setup:

Model: NVIDIA Jetson AGX Orin Developer Kit - Jetpack 6.2 [L4T 36.4.3]
NV Power Mode[0]: MAXN
Serial Number: [XXX Show with: jetson_release -s XXX]
Hardware:
 - P-Number: p3701-0000
 - Module: NVIDIA Jetson AGX Orin
Platform:
 - Distribution: Ubuntu 22.04 Jammy Jellyfish
 - Release: 5.15.148-tegra
jtop:
 - Version: 4.3.1
 - Service: Active
Libraries:
 - CUDA: 12.6.68
 - cuDNN: 9.3.0.75
 - TensorRT: 10.3.0.30
 - VPI: 3.2.4
 - Vulkan: 1.3.204
 - OpenCV: 4.12.0-dev - with CUDA: YES

I’ve modified the spidev_test.c code from this repository to print the time it takes for SPI transfers (specifically the write time), and I keep getting values around 300 microseconds, with jitter present as well. Below is an example output:

$ sudo ./spidev_test -D /dev/spidev0.0 -v -p "TestTransferTime"

spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
SPI write took: 306 microseconds
TX | 54 65 73 74 54 72 61 6E 73 66 65 72 54 69 6D 65 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | TestTransferTime
RX | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | ................

Even with higher frequencies (10 MHz, 20 MHz), the results remain the same. I am not testing loopback feedback—there’s nothing connected to the MOSI and MISO pins, so I am only measuring the transfer time itself. Is this method appropriate for testing?

Since I’ve encountered the same jitter and latency issues with both Jetpack 5.1 and Jetpack 6.2, I wanted to ask if the patch mentioned in this forum post would still be applicable to my setup. If so, could you provide some instructions on how to apply it?

Thanks again for your support!

I think it is available for JP5.x and would help for the delay issue in SPI.
If you are using JP6.x, please use the following one:

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 9fa66500ab54..020c8217ee11 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -155,6 +155,7 @@
 #define RX_FIFO_FULL_COUNT_ZERO			SPI_RX_FIFO_FULL_COUNT(0)
 #define MAX_HOLD_CYCLES				16
 #define SPI_DEFAULT_SPEED			25000000
+#define AUTOSUSPEND_TIMEOUT			300 /* in millisec */
 
 struct tegra_spi_soc_data {
 	bool has_intr_mask_reg;
@@ -1024,7 +1025,8 @@ static int tegra_spi_setup(struct spi_device *spi)
 	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
 	spin_unlock_irqrestore(&tspi->lock, flags);
 
-	pm_runtime_put(tspi->dev);
+	pm_runtime_mark_last_busy(tspi->dev);
+	pm_runtime_put_autosuspend(tspi->dev);
 	return 0;
 }
 
@@ -1425,6 +1427,8 @@ static int tegra_spi_probe(struct platform_device *pdev)
 
 	init_completion(&tspi->xfer_completion);
 
+	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
+	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	if (!pm_runtime_enabled(&pdev->dev)) {
 		ret = tegra_spi_runtime_resume(&pdev->dev);
@@ -1453,7 +1457,8 @@ static int tegra_spi_probe(struct platform_device *pdev)
 	tspi->spi_cs_timing1 = tegra_spi_readl(tspi, SPI_CS_TIMING1);
 	tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2);
 	tspi->def_command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2);
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(&pdev->dev);
 	ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
 				   tegra_spi_isr_thread, IRQF_ONESHOT,
 				   dev_name(&pdev->dev), tspi);
@@ -1477,6 +1482,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	if (!pm_runtime_status_suspended(&pdev->dev))
 		tegra_spi_runtime_suspend(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	tegra_spi_deinit_dma_param(tspi, false);
 exit_rx_dma_free:
 	tegra_spi_deinit_dma_param(tspi, true);
@@ -1528,7 +1534,8 @@ static int tegra_spi_resume(struct device *dev)
 	tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1);
 	tegra_spi_writel(tspi, tspi->def_command2_reg, SPI_COMMAND2);
 	tspi->last_used_cs = master->num_chipselect + 1;
-	pm_runtime_put(dev);
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 
 	return spi_master_resume(master);
 }

And also apply the patch from Jetson orin nano SPI Speed not changing - #9 by KevinFFF in case you hit any CS related issue.

To apply the patch and rebuild kernel image, please refer to Kernel Customization — NVIDIA Jetson Linux Developer Guide for details.