golemparts / rppal

A Rust library that provides access to the Raspberry Pi's GPIO, I2C, PWM, SPI and UART peripherals.
MIT License
1.23k stars 96 forks source link

Pi5 HW PWM not working #154

Open johansmitsnl opened 2 months ago

johansmitsnl commented 2 months ago

I'm on version 0.19.0 and this includes the commit 6bbc5ef8993982e1917aa07f3715a9e97e0fe97c.

This code works on a Pi4 but on my Pi5 I'm getting errors and don't know why.

I have set dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4 in the config. Also with the permission udev rules:

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*\
'"
$ pinctrl get 12,13
12: a0    pd | lo // GPIO12 = PWM0_CHAN0
13: a0    pd | lo // GPIO13 = PWM0_CHAN1
$  ls -l /sys/class/pwm
total 0
lrwxrwxrwx 1 root gpio 0 Sep  1 08:43 pwmchip0 -> ../../devices/platform/soc/107d517a80.pwm/pwm/pwmchip0/
lrwxrwxrwx 1 root gpio 0 Sep  1 08:43 pwmchip2 -> ../../devices/platform/axi/1000120000.pcie/1f00098000.pwm/pwm/pwmchip2/
lrwxrwxrwx 1 root gpio 0 Sep  1 08:43 pwmchip6 -> ../../devices/platform/axi/1000120000.pcie/1f0009c000.pwm/pwm/pwmchip6/

WHen I wanto to initialize the PWM pin:

    let servo_1 = Pwm::with_period(
        Channel::Pwm0,
        Duration::from_millis(SERVO_PWM_PERIOD_MS),
        Duration::from_micros(SERVO_PWM_PULSE_MAX_US),
        Polarity::Normal,
        true,
    )
    .expect("Should be able to connect to PWM pin");

When check the output of DeviceInfo It does read correctly:

rppal::system::DeviceInfo::new() = Ok(
    DeviceInfo {
        model: RaspberryPi5,
        soc: Bcm2712,
        peripheral_base: 1073741824,
        gpio_offset: 851968,
        gpio_lines: 28,
        gpio_interface: Rp1,
        pwm_chip: 2,
        pwm_channels: [
            2,
            3,
        ],
    },
)

I'm getting the error Io(Os { code: 13, kind: PermissionDenied, message: "Permission denied" }).

What am I'm missing here or is there still a bug somewhere?

golemparts commented 2 months ago

Hi @johansmitsnl. Getting a Permission Denied error from with_period typically means RPPAL can't export the channel, which it does by creating /sys/class/pwm/pwmchip2/pwm2. The first thing I would check is make sure the user you're logged in as is part of the gpio group.

johansmitsnl commented 2 months ago

Hi @golemparts. the user is part of the group:

uid=1000(piuser) gid=1000(piuser) groups=1000(piuser),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),102(input),105(render),106(netdev),993(gpio),994(i2c),995(spi)

I noticed with the current udev rules the permissions are wrong:

lrwxrwxrwx 1 root root     0 Sep  4 18:41 device -> ../../../1f00098000.pwm/
--w------- 1 root root 16384 Sep  4 18:41 export
-r--r--r-- 1 root root 16384 Sep  4 18:41 npwm
drwxr-xr-x 2 root root     0 Sep  4 18:41 power/
lrwxrwxrwx 1 root root     0 Jan  1  1970 subsystem -> ../../../../../../../class/pwm/
-rw-r--r-- 1 root root 16384 Jan  1  1970 uevent
--w------- 1 root root 16384 Sep  4 18:41 unexport

But when I chown them with sudo chown root:gpio -Rf * . and I try to touch of make a dir in: /sys/class/pwm/pwmchip2/pwm2 I get the permission denied:

touch /sys/class/pwm/pwmchip2/pwm2
touch: cannot touch '/sys/class/pwm/pwmchip2/pwm2': Permission denied

But even when I use sudo to create the directory I also get permission denied.

golemparts commented 2 months ago

I had some time to look into the hardware PWM code some more. My earlier mention of the creation of /sys/class/pwm/pwmchip2/pwm2 causing the Permission Denied error wasn't accurate, as the creation of pwm2 is triggered by writing a 2 (for channel 0) to /sys/class/pwm/pwmchip2/export.

I checked the permissions on my Pi 5, which are different from yours:

--w--w---- 1 root gpio 16384 Sep  4 11:41 export
-r--r--r-- 1 root gpio 16384 Sep  4 11:41 npwm
drwxrwxr-x 2 root gpio     0 Sep  4 11:41 power
lrwxrwxrwx 1 root gpio     0 Sep  4 11:41 subsystem -> ../../../../../../../class/pwm
-rw-rw-r-- 1 root gpio 16384 Sep  4 11:41 uevent
--w--w---- 1 root gpio 16384 Sep  4 11:41 unexport

I don't actually recall having to edit /etc/udev/rules.d/99-com.rules anymore, so it's possible that recommendation in the documentation is no longer needed for more recent versions of Raspberry Pi OS. Could you check what permissions it defaults to after deleting those rules and rebooting?

johansmitsnl commented 2 months ago

Without the udev rules the permissions are not of the GPIO group:

$ stat /sys/class/pwm/pwmchip2/export
  File: /sys/class/pwm/pwmchip2/export
  Size: 16384       Blocks: 0          IO Block: 16384  regular file
Device: 0,18    Inode: 23381       Links: 1
Access: (0200/--w-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-09-05 19:14:28.863921234 +0200
Modify: 2024-09-05 19:14:28.863283257 +0200
Change: 2024-09-05 19:14:28.863283257 +0200
 Birth: -

I don't run as root but as a normal user so this can't work since the permission is 200 and not even writable for the group.

I changes the udev rule to this:

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* &&\
    chown root:gpio /sys/class/pwm/pwmchip*/export &&\
    chmod 220 /sys/class/pwm/pwmchip*/export &&\
    chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\

This makes sure the permission is correct on the export path.

But this is also not sufficient due to permission lacking write permission on the new created pwm2 directory:

$ ls -l /sys/class/pwm/pwmchip2/pwm2
-r--r--r-- 1 root root 16384 Sep  5 19:27 capture
-rw-r--r-- 1 root root 16384 Sep  5 19:27 duty_cycle
-rw-r--r-- 1 root root 16384 Sep  5 19:27 enable
-rw-r--r-- 1 root root 16384 Sep  5 19:27 period
-rw-r--r-- 1 root root 16384 Sep  5 19:27 polarity
drwxr-xr-x 2 root root     0 Sep  5 19:27 power/
-rw-r--r-- 1 root root 16384 Sep  5 19:27 uevent

By manually adding chmod -R g+rw on the pwm2 dir it still isn't solved and I still get the permission denied error.

$ ls -l /sys/class/pwm/pwmchip2/pwm2=
-r--rw-r-- 1 root gpio 16384 Sep  5 19:27 capture
-rw-rw-r-- 1 root gpio 16384 Sep  5 19:32 duty_cycle
-rw-rw-r-- 1 root gpio 16384 Sep  5 19:32 enable
-rw-rw-r-- 1 root gpio 16384 Sep  5 19:32 period
-rw-rw-r-- 1 root gpio 16384 Sep  5 19:32 polarity
drwxrwxr-x 2 root gpio     0 Sep  5 19:27 power/
-rw-rw-r-- 1 root gpio 16384 Sep  5 19:27 uevent
golemparts commented 2 months ago

If this is happening with a fresh install of a recent Raspberry Pi OS release, I think at this point it's better if you ask about this on the official Raspberry Pi forum, as this does not appear to be an RPPAL issue but a linux one, and I'm not familiar enough with how best to solve permission issues like this.

I'd appreciate it if you can let me know when you've found a solution, as it may be useful to people who run into the same problem.

johansmitsnl commented 2 months ago

Yes this is a fresh install of 1 week ago. I'll let you know the outcome but I'm on holiday for the next 3 weeks so it might take some time for me to reply.

johansmitsnl commented 2 months ago

Created a question on the pi forum

johansmitsnl commented 1 week ago

No response on the forum but I did a reinstall on the pi.

Now the permissions are the same as yours but I have an issue with the Channel::Pwm1 that fails. The Channel::Pwm0 does not panic.

Now my output of the directory is like this:

ls -l /sys/class/pwm/pwmchip2/
total 0
lrwxrwxrwx 1 root gpio     0 Oct 30 20:32 device -> ../../../1f0009c000.pwm
--w--w---- 1 root gpio 16384 Oct 30 20:42 export
-r--r--r-- 1 root gpio 16384 Oct 30 20:32 npwm
drwxrwxr-x 2 root gpio     0 Oct 30 20:32 power
lrwxrwxrwx 1 root gpio     0 Oct 30 20:32 subsystem -> ../../../../../../../class/pwm
-rw-rw-r-- 1 root gpio 16384 Oct 30 20:32 uevent
--w--w---- 1 root gpio 16384 Oct 30 20:40 unexport

Full firmware config:

# /boot/firmware/config.txt

# For more options and information see
# http://rptl.io/configtxt
# Some settings may impact device functionality. See link above for details

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

# Additional overlays and parameters are documented
# /boot/firmware/overlays/README

# Automatically load overlays for detected cameras
camera_auto_detect=1

# Automatically load overlays for detected DSI displays
display_auto_detect=1

# Automatically load initramfs files, if found
auto_initramfs=1

# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2

# Don't have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel's default instead.
disable_fw_kms_setup=1

# Run in 64-bit mode
arm_64bit=1

# Disable compensation for displays with overscan
disable_overscan=1

# Run as fast as firmware / board allows
arm_boost=1

[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1

[cm5]
dtoverlay=dwc2,dr_mode=host
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4

[all]

Maybe a suggestion where to look as all permissions seem correct?

golemparts commented 2 days ago

Glad to hear a fresh install fixed the initial problem. I'm not sure what would cause an issue with PWM1 when PWM0 is working. Your configuration looks correct. What error are you getting?