Hardware PWM not routed to 40-pin header on Orin Nano Super (JetPack 6 / L4T R36) - sysfs writes succeed but no signal output


Board: Jetson Orin Nano Super Developer Kit (8GB)
JetPack: 6
L4T: R36 (Linux 5.15.148-tegra)
Jetson.GPIO: 2.1.12
Power Mode: MAXN Super


Hi @KevinFFF, @lhoang,

I spent a good chunk of time trying to drive a hobby servo from the 40-pin header on my Orin Nano Super and couldn’t get any of the hardware PWM chips to actually output a signal. The frustrating part is that sysfs happily accepts all the writes and reports everything as enabled, but nothing comes out on the pins.

What I tried (none of these produced output):

Method Pins Tested Result
sysfs pwmchip0 15, 32, 33 Writes succeed, enable=1, no signal
sysfs pwmchip2 15, 32, 33 Same
sysfs pwmchip3 15, 32, 33 Same
Pinmux devmem fix + sysfs 15, 32, 33 Register writes succeed, still no signal
Jetson.GPIO software PWM 33 Signal present but ~200-500us jitter, not usable for servos

Here’s what the silent failure looks like:

echo 0 > /sys/class/pwm/pwmchip0/export
echo 20000000 > /sys/class/pwm/pwmchip0/pwm0/period
echo 1500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
cat /sys/class/pwm/pwmchip0/pwm0/enable  # Returns "1" but no electrical output

I also tried Pin 15, which the JETGPIO library lists as the only hardware PWM output on the Orin Nano. Applied the pinmux fix (busybox devmem 0x2440020 w 0x5), register write went through fine, still nothing on the scope.

On the original Jetson Nano B01, Pins 32/33 are real hardware PWM outputs via sysfs. That doesn’t seem to carry over to the Orin Nano Super.

What actually worked: GPIO bit-bang on Pin 33 using Jetson.GPIO. Just toggling the pin high/low with time.sleep() for the pulse timing. Python’s sleep has about 50us of jitter on this board, which is plenty good enough for hobby servo pulse widths (1000-2000us at 50Hz). I also wrote a C version with clock_nanosleep and RT scheduling, but honestly the Python version works just as well for standard servos.

I put everything in a repo with the full debugging story, wiring, and ready-to-run scripts:

A few questions:

  1. Is hardware PWM intentionally not routed to the header on the Orin Nano Super carrier board, or is there a pinmux/device-tree config I’m missing?
  2. If it’s a carrier board limitation, any chance this could be documented somewhere? The fact that sysfs writes all succeed silently makes this really hard to figure out.
  3. Any plans to fix this in a future JetPack or device tree update?

There’s also some discussion on Reddit where a few other people have run into similar issues.

Happy to grab device tree dumps or pinmux register state if that would help narrow it down. Thanks!


Have you used /opt/nvidia/jetson-io/jetson-io.py to configure PWM for pin 15, 32, 33?

if you prefer devmem way the correct value for pinmux PWM is

HAT pin Signal / SFIO Pinmux register Value read
15 GPIO12 / GP88_PWM1 0x02440020 0x00000404
32 GPIO07 / GP113_PWM7 0x02434080 0x00000404
33 GPIO13 / GP115 0x02434040 0x00000405

Jetson GPIO PWM actually use the sysfs way internally so if you prefer you can use that.

Hi Kyle

Creator of Jetgpio here. You misunderstood my README, I mean that the Orin Nano (official dev kit or clone) provides PWM in pins 32, 33 AND additionally 15.

And yes is hardware PWM, no idea what the status of the python library is but if you want to make it work (really no bitbanging) you should enable the clocks first, that’s the reason why sysfs fails silently and also busybox, enabling the registers is not enough.

What I did is implement a kernel module to manipulate the clocks directly but you don’t have to or use my library at all, you can try to enable the PWM clocks using bash for each clock like so (sudo obviously):

bash -c ‘echo “1” > /sys/kernel/debug/bpmp/debug/clk/pwm1/state’
bash -c ‘echo “1” > /sys/kernel/debug/bpmp/debug/clk/pwm5/state’
bash -c ‘echo “1” > /sys/kernel/debug/bpmp/debug/clk/pwm7/state’

and then try busybox, use the python library or whatever. I letf a convinience script with a service file to have it enabled on boot, it is in the scripts folder in the old version of my library here.

Regards