Xavier NX Dev Kit, issues with Jetson.GPIO on R35.4.1

Hello,

I am playing around with the Jetson Xavier NX developer kit trying to flip a GPIO pin up and down while monitoring on a scope.

I am using the verson of Jetson.GPIO that came pre-installed on the system when I flashed it with L4T 35.4.1. I cloned the repo so that I could install the udev rules as it says to do in the README.

I am unable get pin 12 on the 40-pin header to flip up and down nicely. I am seeing the same issue where I see a ~50Hz sine wave with the occasional transition to ground as is detailed in this thread here: Use 40 pin header in python - #8 by Out_of_the_BOTS

However I am using the Nvidia carrier board.

I understand that historically the Jetson.GPIO functionality was broken up until L4T 35.1, released in August 2022.

What gives? Is it still broken? What is the recommended way to flip GPIOs on this dev kit / SoM?
I was planning to build up to producing a 10Hz square wave using PWM, if this functionality is broken too, it would be great if the solution for using PWM is shared also.

Thanks.

Following along the thread I linked, I did do as superuser:

echo 422 > /sys/class/gpio/export

and rebooted.

Now, I see the GPIO pin transition to ~3.2V when 1 is set, but when 0 is set, I see the 50Hz sine wave. The pin does not go to ground until maybe ~20 seconds after a 0 is set. Sometimes it never goes to ground, it will just produce that sine wave indefinitely.

Last thing I’ll add it this. The Jetson.GPIO simple_out.py script is claiming that the carrier board is not supported, but it is 100% the Nvidia one.

dev@tegra-ubuntu:~/jetson-gpio/samples$ sudo python3 simple_out.py 
WARNING: Carrier board is not from a Jetson Developer Kit.
WARNNIG: Jetson.GPIO library has not been verified with this carrier board,
WARNING: and in fact is unlikely to work correctly.
Starting demo now! Press CTRL+C to exit
Outputting 1 to pin 18
Outputting 0 to pin 18
Outputting 1 to pin 18
Outputting 0 to pin 18
Outputting 1 to pin 18

Okay,

I have been doing the legwork to get familiar with all of the different GPIO pin mappings, so that I can further debug this by working directly with sysfs.

Let’s start from the beginning. I want to flip GPIO pin 12 on the 40-pin header. Looking at the classic reference: https://jetsonhacks.com/nvidia-jetson-xavier-nx-gpio-header-pinout/

I see that the pin I am using has the name I2S0_SCLK. Now heading over to the pinmux spreadsheet, I see that I2S0_SCLK corresponds to GPIO3_PT.05.

This is where I think I may be doing something wrong / missing something. As this next step is how you calculate the GPIO number used by sysfs.

Port T has a multiplier of 19 according to tegra194-gpio.h found here: linux/include/dt-bindings/gpio/tegra194-gpio.h at master · torvalds/linux · GitHub

#define TEGRA194_MAIN_GPIO_PORT_T 19

So the base offset of my header pin 12 should be:

(19 * 8) + 5 = 157

Now we need to add in offset added by the kernel, which we find using:

sudo dmesg | grep "registered GPIOs"

The result on my Xavier NX dev kit is this:

dev@tegra-ubuntu:~$ sudo dmesg | grep "registered GPIOs"
[    3.091638] gpiochip0: registered GPIOs 504 to 511 on max77620-gpio
[    5.907877] gpiochip1: registered GPIOs 335 to 503 on tegra194-gpio
[    5.909870] gpiochip2: registered GPIOs 305 to 334 on tegra194-gpio-aon

Which leads me to believe I need to add 335 to this number I calculated earlier, my justification for picking the middle tegra194-gpio range is that Port T is part of the MAIN GPIO controller.

So my final number comes out to:
157 + 335 = 492. This is notably very different from what is in our guide here: https://jetsonhacks.com/nvidia-jetson-xavier-nx-gpio-header-pinout/, which cites 445 as the magic number.

Could somebody shed some light on what I may be doing wrong here?

Also, performing

echo 445 > /sys/class/gpio/export

Creates a node in /sys/class/gpio/ called PR.02, which seems to not be correct either.

Performing

echo 492 > /sys/class/gpio/export

Creates a node called PZ.00, which is also not what I’d expect.

Configuring the direction of these two nodes to out and writing a value of 1 does NOT cause any change in the pin 12 on the 40-pin header.
Could use some insight, thanks in advance.

EDIT:
Through trial and error I figured out that the correct sysfs GPIO number for my pin is 462.
Performing:

  100  echo 462 > /sys/class/gpio/export
  101  cd /sys/class/gpio/
  102  cd PT.05/
  104  cat direction 
  105  echo out > direction 
  106  cat value 
  107  echo 1 > value 
  108  echo 0 > value 
  109  echo 1 > value 
  110  echo 0 > value 

Behaves exactly how I’d expect and allows me to toggle the GPIO pin up and down, with normal 3.3V high and 0v low. ALSO, after doing this I tried to run the simple_out.py example again and got a Device or Resource busy exception. Unexporting the pin with:

echo 462 > /sys/class/gpio/unexport

and re-running simple_out.py makes it work perfectly!

However I am still in need of some clarification on the correct way to reach this 462 number. Thank you.

Hi,

Seems like the calculation of ((TEGRA194_MAIN_GPIO_PORT_##port * 8) + offset) is only valid in rel-32 era. We’ve updated the document for Orin GPIO, but we didn’t notice it’s the same for Xavier because the GPIO driver is shared between these two platforms.
https://docs.nvidia.com/jetson/archives/r35.1/DeveloperGuide/text/HR/JetsonModuleAdaptationAndBringUp/JetsonAgxOrinSeries.html#identifying-the-gpio-number

As you can see in the pinmux spreadsheet, it’s not the case that there are 8 pins for every ports. For example, Port B only has PB.00 and PB.01. In rel-32, the GPIO number is calculated with the aforementioned formula, regardless of how many pins this port actually has, leaving a lot of dummy GPIO pin numbers that cannot actually be used. In rel-35, this is adjusted and only those pins that are physically present are registered.

In short, you can just grep the sysfs for identifying the GPIO number of the pin you want to use:

sudo cat /sys/kernel/debug/gpio | grep PT.05
gpio-462 (PT.05 |cam_pwdn_gpio ) out lo

A full list of tegra194-gpio gives:

gpiochip1: GPIOs 335-503, parent: platform/2200000.gpio, tegra194-gpio:
 gpio-335 (PA.00               |(null)              ) out lo 
 gpio-336 (PA.01               |fixed-regulators:reg) out hi ACTIVE LOW
 gpio-337 (PA.02               )
 gpio-338 (PA.03               |fixed-regulators:reg) out hi 
 gpio-339 (PA.04               )
 gpio-340 (PA.05               )
 gpio-341 (PA.06               )
 gpio-342 (PA.07               )
 gpio-343 (PB.00               )
 gpio-344 (PB.01               )
 gpio-345 (PC.00               )
 gpio-346 (PC.01               )
 gpio-347 (PC.02               )
 gpio-348 (PC.03               )
 gpio-349 (PC.04               )
 gpio-350 (PC.05               )
 gpio-351 (PC.06               )
 gpio-352 (PC.07               )
 gpio-353 (PD.00               )
 gpio-354 (PD.01               )
 gpio-355 (PD.02               )
 gpio-356 (PD.03               )
 gpio-357 (PE.00               )
 gpio-358 (PE.01               )
 gpio-359 (PE.02               )
 gpio-360 (PE.03               )
 gpio-361 (PE.04               )
 gpio-362 (PE.05               )
 gpio-363 (PE.06               )
 gpio-364 (PE.07               )
 gpio-365 (PF.00               )
 gpio-366 (PF.01               )
 gpio-367 (PF.02               )
 gpio-368 (PF.03               )
 gpio-369 (PF.04               )
 gpio-370 (PF.05               )
 gpio-371 (PG.00               |force-recovery      ) in  hi IRQ ACTIVE LOW
 gpio-372 (PG.01               )
 gpio-373 (PG.02               )
 gpio-374 (PG.03               |wifi-enable         ) out hi 
 gpio-375 (PG.04               )
 gpio-376 (PG.05               |phy_reset           ) out hi 
 gpio-377 (PG.06               )
 gpio-378 (PG.07               |cd                  ) in  hi IRQ ACTIVE LOW
 gpio-379 (PH.00               )
 gpio-380 (PH.01               )
 gpio-381 (PH.02               |temp-alert          ) in  hi IRQ 
 gpio-382 (PH.03               |cam_reset_gpio      ) out lo 
 gpio-383 (PH.04               )
 gpio-384 (PH.05               )
 gpio-385 (PH.06               |cam_pwdn_gpio       ) out lo 
 gpio-386 (PH.07               )
 gpio-387 (PI.00               )
 gpio-388 (PI.01               )
 gpio-389 (PI.02               )
 gpio-390 (PI.03               )
 gpio-391 (PI.04               )
 gpio-392 (PJ.00               )
 gpio-393 (PJ.01               )
 gpio-394 (PJ.02               )
 gpio-395 (PJ.03               )
 gpio-396 (PJ.04               )
 gpio-397 (PJ.05               )
 gpio-398 (PK.00               )
 gpio-399 (PK.01               )
 gpio-400 (PK.02               )
 gpio-401 (PK.03               )
 gpio-402 (PK.04               )
 gpio-403 (PK.05               )
 gpio-404 (PK.06               )
 gpio-405 (PK.07               )
 gpio-406 (PL.00               )
 gpio-407 (PL.01               )
 gpio-408 (PL.02               )
 gpio-409 (PL.03               )
 gpio-410 (PM.00               )
 gpio-411 (PM.01               )
 gpio-412 (PM.02               |hdmi2.0_hpd         ) in  hi IRQ 
 gpio-413 (PM.03               )
 gpio-414 (PM.04               )
 gpio-415 (PM.05               |fixed-regulators:reg) out lo 
 gpio-416 (PM.06               |reset_gpio          ) out lo 
 gpio-417 (PM.07               |bt_ext_wake         ) out hi 
 gpio-418 (PN.00               |fixed-regulators:reg) out lo 
 gpio-419 (PN.01               )
 gpio-420 (PN.02               )
 gpio-421 (PO.00               )
 gpio-422 (PO.01               )
 gpio-423 (PO.02               )
 gpio-424 (PO.03               )
 gpio-425 (PO.04               )
 gpio-426 (PO.05               )
 gpio-427 (PP.00               )
 gpio-428 (PP.01               )
 gpio-429 (PP.02               )
 gpio-430 (PP.03               )
 gpio-431 (PP.04               )
 gpio-432 (PP.05               )
 gpio-433 (PP.06               )
 gpio-434 (PP.07               )
 gpio-435 (PQ.00               )
 gpio-436 (PQ.01               )
 gpio-437 (PQ.02               )
 gpio-438 (PQ.03               )
 gpio-439 (PQ.04               )
 gpio-440 (PQ.05               )
 gpio-441 (PQ.06               )
 gpio-442 (PQ.07               )
 gpio-443 (PR.00               )
 gpio-444 (PR.01               )
 gpio-445 (PR.02               )
 gpio-446 (PR.03               )
 gpio-447 (PR.04               )
 gpio-448 (PR.05               )
 gpio-449 (PS.00               )
 gpio-450 (PS.01               )
 gpio-451 (PS.02               )
 gpio-452 (PS.03               )
 gpio-453 (PS.04               )
 gpio-454 (PS.05               )
 gpio-455 (PS.06               )
 gpio-456 (PS.07               )
 gpio-457 (PT.00               )
 gpio-458 (PT.01               )
 gpio-459 (PT.02               )
 gpio-460 (PT.03               )
 gpio-461 (PT.04               )
 gpio-462 (PT.05               |cam_pwdn_gpio       ) out lo 
 gpio-463 (PT.06               |cam_reset_gpio      ) out lo 
 gpio-464 (PT.07               )
 gpio-465 (PU.00               )
 gpio-466 (PV.00               )
 gpio-467 (PV.01               )
 gpio-468 (PV.02               )
 gpio-469 (PV.03               )
 gpio-470 (PV.04               )
 gpio-471 (PV.05               )
 gpio-472 (PV.06               )
 gpio-473 (PV.07               )
 gpio-474 (PW.00               )
 gpio-475 (PW.01               )
 gpio-476 (PX.00               )
 gpio-477 (PX.01               )
 gpio-478 (PX.02               )
 gpio-479 (PX.03               )
 gpio-480 (PX.04               )
 gpio-481 (PX.05               )
 gpio-482 (PX.06               )
 gpio-483 (PX.07               )
 gpio-484 (PY.00               |bt_host_wake        ) in  hi IRQ 
 gpio-485 (PY.01               )
 gpio-486 (PY.02               )
 gpio-487 (PY.03               )
 gpio-488 (PY.04               )
 gpio-489 (PY.05               )
 gpio-490 (PY.06               )
 gpio-491 (PY.07               )
 gpio-492 (PZ.00               )
 gpio-493 (PZ.01               |fixed-regulators:reg) out hi 
 gpio-494 (PZ.02               |fixed-regulators:reg) out lo 
 gpio-495 (PZ.03               )
 gpio-496 (PZ.04               )
 gpio-497 (PZ.05               )
 gpio-498 (PZ.06               )
 gpio-499 (PZ.07               )
 gpio-500 (PFF.00              )
 gpio-501 (PFF.01              )
 gpio-502 (PGG.00              )
 gpio-503 (PGG.01              )

Dave,

Thank you very much for your reply. Can you tell me, was I looking in the wrong place and missed this documentation somewhere? I tried my best to comb through the docs and answer this question myself, if there is a difinitive location for up-to-date docs for stuff like GPIO usage I would love a pointer.

Also, should we even use the Jetson.GPIO library on r35? Or is the official sanctioned use of GPIO on r35 just to use sysfs directly.

Thanks in advance.

I mean we only updated the document for Orin series, as mentioned in the link I posted earlier, but actually it should also be the case for Xavier series, i.e., you cannot rely on the formula to calculate GPIO index anymore.

YES. I think Jetson.GPIO is still fine.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.