Need to configure non-root PWM access

Hello,

We have been using Navio2 with software built on the examples provided here https://docs.emlid.com/navio2/ for a university class for a couple of years. We are currently working on migrating toward ROS and we have been able to port everything over except for the Servo example.

The problem is that the Servo example (and the ROS node which was developed from the example) need access to the PWM pins without root access. I have searched the internet and tried several fixes including those at the following links: https://www.raspberrypi.org/forums/viewtopic.php?t=194174, https://raspberrypi.stackexchange.com/questions/66890/accessing-pwm-module-without-root-permissions. But I have not found anything that will allow me to succesfully write PWM duty cycle without using sudo

There seems to have been a kernel patch issued for udev not being properly triggered by PWM object creation https://github.com/raspberrypi/linux/issues/1983. It seems like this could be related to my issue but I have no way to apply this patch to the pre-built image. I have upgraded to the most current Navio2 image and successfully updated using sudo apt-get update && sudo apt-get dist-upgrade.

My other idea as to the source of the problem is that the commands in /etc/udev/rules.d/99-com.rules are not correct for the specific implementation on this hardware in which case I would need help figuring out which files I need to change permissions on.

Any suggestions are appreciated.

Thanks,

Shawn

1 Like

Please let me know if something is missing from this post. I am really stuck trying to solve this problem. I have tried to implement all the fixes I can find online to no avail. Following udev rule templates for other RaspberryPi devices (found via web search) does not seem to help (due to the differences in naming the devices).

Any help would be appreciated.

Posting more information here since no one has been willing or able to help.

Output from udevadm monitor while executing sudo ./Servo in another terminal:

KERNEL[163.395126] change /devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0 (pwm)
UDEV [163.401049] change /devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0 (pwm)

This is what my rules file looks like. Most of this is as provided from the Navio2 image but I have added lines with DRIVER==“spi-bcm2835aux” and SUBSYSTEMS==“pwm*” (testscript.sh is just creating a text file with touch so I can see if the rule is running):

SUBSYSTEM==“input”, GROUP=“input”, MODE=“0660”
SUBSYSTEM==“i2c-dev”, GROUP=“i2c”, MODE=“0660”
SUBSYSTEM==“spidev”, GROUP=“spi”, MODE=“0660”
SUBSYSTEM==“bcm2835-gpiomem”, GROUP=“gpio”, MODE=“0660”

ACTION==“add|change”, DRIVER==“spi-bcm2835aux”, GROUP=“gpio”, MODE=“0660”, RUN+=“/bin/sh /usr/bin/testscript.sh”

ACTION==“add|change”, SUBSYSTEMS==“pwm*”, GROUP=“gpio”, MODE=“0660” , RUN+=“/bin/sh /usr/bin/testscript.sh”

SUBSYSTEM==“gpio”, GROUP=“gpio”, MODE=“0660”
SUBSYSTEM==“gpio*”, PROGRAM=“/bin/sh -c ’
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;
chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;
chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath
'”

KERNEL==“ttyAMA[01]”, PROGRAM=“/bin/sh -c ’
ALIASES=/proc/device-tree/aliases;
if cmp -s $ALIASES/uart0 $ALIASES/serial0; then
echo 0;
elif cmp -s $ALIASES/uart0 $ALIASES/serial1; then
echo 1;
else
exit 1;
fi
'”, SYMLINK+=“serial%c”

KERNEL==“ttyS0”, PROGRAM=“/bin/sh -c ’
ALIASES=/proc/device-tree/aliases;
if cmp -s $ALIASES/uart1 $ALIASES/serial0; then
echo 0;
elif cmp -s $ALIASES/uart1 $ALIASES/serial1; then
echo 1;
else
exit 1;
fi
'”, SYMLINK+=“serial%c”

I’m far from a udev rules expert but I am trying to learn some things to make this work. Most RaspberryPi tutorials for making PWM accessible by non-root users are not helpful because Navio2 is not using the PWM functionality built-in to the RaspberryPi. This means finding the KERNEL to match for the proper udev rule is a job left to the user. I have been hacking continuously to try to figure this out and I have some more command outputs to post.

~ $ udevadm monitor --property
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[45.960182] change /devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0 (pwm)
ACTION=change
DEVPATH=/devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0
EXPORT=pwm1
SEQNUM=1233
SUBSYSTEM=pwm

UDEV [45.966165] change /devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0 (pwm)
ACTION=change
DEVPATH=/devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0
EXPORT=pwm1
SEQNUM=1233
SUBSYSTEM=pwm
USEC_INITIALIZED=45965788

From this I can find the devpath but then running the other udevadm tools is not helpful, for example:

~ $ udevadm trigger /devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0
unable to open the device ‘/devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0’
~ $ udevadm trigger /devices/platform/soc/3f215080.spi/
unable to open the device ‘/devices/platform/soc/3f215080.spi/’
~ $ udevadm trigger /devices/platform/soc/3f215080.spi
unable to open the device ‘/devices/platform/soc/3f215080.spi’

I can’t believe there aren’t any replies on this.

As an organization we have purchased hundreds of Navio2 boards. To the credit of Emlid, we haven’t had problems very often and the provided documentation is great and has gotten us to where we are today.

I don’t have a complete understanding of how Navio2 is outputing RC PWM commands. This is by design. If we wanted to design our own hardware and write drivers we could have done that.

If anyone has any suggestions including how to get people to actually read these posts and provide some kind of assistance please let me know.

I see other people active on this forum currently including Emlid folks. If someone wants to let me know what I need to do in order to get some support please let me know.

In the meantime, I will post another solution that I have tried that does not work. Using these rules added to the rules file:

SUBSYSTEM==“pwm*”, PROGRAM=“/bin/sh -c ’
chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;
chown -R root:gpio /sys/devices/platform/soc/.pwm/pwm/pwmchip && chmod -R 770 /sys/devices/platform/soc/.pwm/pwm/pwmchip
'”
Which is taken from here: https://raspberrypi.stackexchange.com/questions/66890/accessing-pwm-module-without-root-permissions

I am still not able to run the Servo example without sudo. Although, I have made some progress, it looks like the gpio group has been added to the permissions for the symbolic link pwmchip0:

~ $ ls -l /sys/class/pwm/
total 0
lrwxrwxrwx 1 root gpio 0 Oct 9 12:53 pwmchip0 → …/…/devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0

However, this does not seem to be allowing non-root users to write duty-cycle. I have been able to manually call chown and chmod on the directory /sys/devices/platform/soc/3f215080.spi/spi_master/spi1/spi1.0/pwm/pwmchip0/pwm1 and this seems to allow non-root users to access PWM; however, this is not a very clean solution. You must first call the servo example as root (sudo ./Servo) to create the directories in question, then manually call chmod and chown and then you must call the servo example again, as a non-root user and it works.

Is support no longer being provided for Navio2 or is everyone just too busy?

I am still trying to solve this problem. I am now running the latest Navio2 image and switched over to the newest Navio2 example code at https://github.com/emlid/Navio2. I was previously running the latest Navio2 image with a legacy version of the Navio2 example code.

There is now no output from udevadm monitor when running the Servo example.

Any advice?

I’m sure you’ll get help yet. The forum is a great place for information but sometimes you have to wait a bit. Your question is fairly advanced so many of us can’t provide help. You’ll have to just wait for an expert user or one of the Emlid team. They will see your post.

2 Likes

Hi @shawn1231,

We’re looking into this question right now and write back once we have any advice on this.

Hi @shawn1231,

Sorry it took so long to get back to you!

We recommend using this udev rule to configure non-root PWM access:

SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
        chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
        chown -R root:gpio /sys/devices/platform/soc/*.spi/spi_master/spi1/spi1.0/pwm/pwmchip0 && chmod -R 770 /sys/devices/platform/soc/*.spi/spi_master/spi1/spi1.0/pwm/pwmchip0\
'"

It should work on RPi 3.

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