How to Enable and Control PWM on AML-S905X-CC

This was a bug on our part. Please update the kernel and try again.

1 Like

I was trying to enable pwm on pin 33:

sudo ldto enable pwm-a
echo 0 > pwmchip0/export 
echo 100000000 > pwmchip0/pwm0/period 
echo 10000000 > pwmchip0/pwm0/duty_cycle
echo 1 > pwmchip0/pwm0/enable 

But I get an error: “-bash: echo: write error: Invalid argument” on this last line. What could this be?

I am encountering the same issue as @Samuel
As additional information, these are the active DTOs I have:

#Overlays active:

Note that the error is not uniform across chips/lines:

  • pwmchip0/pwm0: I can set duty_cycle and period but cannot set enable.
  • pwmchip0/pwm1: I cannot set duty_cycle
  • pwmchip2/pwm0 and pmwchip2/pwm1: works, I can set duty_cycle, period and enable.

Again, by “cannot set” I mean I get “write error: Invalid argument”.

You don’t have permission as you are not the root user. You need to add yourself to the gpio group via sudo adduser USERNAME gpio or run sudo su.

I try both solutions. And still, I wasn´t able to set enable on pins 32, 33 and 35. After rebooting the system I was able to write to pmw0/enable (for pin33 and 32). However, for some reason, I still cannot write (write error: Invalid argument) to pmw1/enable for pin35.

Aditional info

  • Like @technoryt, I was always able to set period and duty_cycle for all pins. I only had issues while setting enable (echo 1 > /sys/class/pwm/pwmchip{x}/pwm[n}/enable ) for pins 32, 33 and 35.

  • I only have one active DTO each time. And I’m using rasbian.

Actually, I rebooted after using ldto merge (so that I do not need to use ldto activate, I don’t think I changed anything else). Now I can successfully use all four PWM lines. I started from the Ubuntu 22.04 Desktop image.

@Samuel: did you manage to use the PWM lines from a non-root user? If I try to add my user to the gpio group as mentioned by @librecomputer, I have the error that the group does not exist. All the directories under /sys/class/pwm are all owned by root:root.

ubuntu@lepotato:~$ sudo adduser ubuntu gpio
[sudo] password for ubuntu: 
adduser: The group `gpio' does not exist.

Check the group ownership of the files under /sys/class/pwm. Different OSes use different groups based on udev rules.

1 Like

@librecomputer: Regarding your last post. All the files under sys/class/pwm/pwmchip{X} belong to the gpio group. Except for the pwmchip{X}, which are owned by root group. So, I tried to change the group of these directories (assuming that it should be gpio) but nothing changed:

inl@raspberrypi:~ $ sudo chgrp gpio /sys/class/pwm/pwmchip0
inl@raspberrypi:~ $ ls -l /sys/class/pwm/
total 0
lrwxrwxrwx 1 root root 0 Jan 18 16:43 pwmchip0 → …/…/devices/platform/soc/c1100000.bus/c11086c0.pwm/pwm/pwmchip0

By way, it is not very clear to me which group should own these directories. Should It be gpio?

For some reason, now I can control pin35, but cannot control pin33 anymore (refer to my previous post). Why could this be?

@technoryt: Regarding your question, I believe so, at least for pins 12 and 13. Relative to your comment, my user was already a member of gpio group.

1 Like

Permissions are setup by udev and can be arbitrarily customized.

You need to enable pwm-ef rather than pwm-e or pwm-f. They’re a combo pair.

Once you add yourself to a group. You need to logout and log back in to have it take effect. Also the permission should have group write.

1 Like

Hello, I am new to this space and have no idea what do I do. So I tried enabling pin 32 and 33.

ls -al /sys/class/pwm # see the pwmchip{n} to hardware mapping
echo {0,1} | sudo tee /sys/class/pwm/pwmchip0/export
echo 1000000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/period
echo 500000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm0/enable
Overlay pwm-ef: already exists
total 0
drwxr-xr-x  2 root root 0 Dec 31  1969 .
drwxr-xr-x 75 root root 0 Dec 31  1969 ..
lrwxrwxrwx  1 root root 0 Apr  8 13:48 pwmchip0 -> ../../devices/platform/soc/c1100000.bus/c11086c0.pwm/pwm/pwmchip0
lrwxrwxrwx  1 root root 0 Apr  8 13:52 pwmchip2 -> ../../devices/platform/soc/c1100000.bus/c1108550.pwm/pwm/pwmchip2
0 1
tee: /sys/class/pwm/pwmchip0/export: Invalid argument
tee: /sys/class/pwm/pwmchip0/pwm0/period: No such file or directory
tee: /sys/class/pwm/pwmchip0/pwm0/duty_cycle: No such file or directory
tee: /sys/class/pwm/pwmchip0/pwm0/enable: No such file or directory

I am not sure what is wrong and why, or even the right way to do that. Also, what do I use for python to control PWM? Is periphery good? Also weird thing is that It says in spreadsheet that port 32 is controlled by chip 1 and not 0…

1 Like

You have to echo 0 or 1 based on which PWM you want to export. {0,1} is an invalid entry. You have to replace all things in {} with the proper value as outlined in the OP.

1 Like

Ok that worked. But how do I control it? When I try using periphery, it gives me

periphery.pwm.PWMError: [Errno 19] Exporting PWM channel: No such device

I do not understand channels and how do I find right one for pin 32.

Here is what I got from activating pin 32:

yasushiko@raspberrypi:~ $ sudo ldto enable pwm-e # replace x with one of the dtos in list above
ls -al /sys/class/pwm # see the pwmchip to hardware mapping
echo 0 | sudo tee /sys/class/pwm/pwmchip0/export
echo 1000000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/period
echo 500000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm0/enable
Overlay pwm-e: applied
total 0
drwxr-xr-x  2 root root 0 Dec 31  1969 .
drwxr-xr-x 87 root root 0 Dec 31  1969 ..
lrwxrwxrwx  1 root root 0 Apr  8 19:28 pwmchip0 -> ../../devices/platform/soc/c1100000.bus/c11086c0.pwm/pwm/pwmchip0

You set the period and the duty cycle to what you want via sysfs per the 3rd and 4th commands.

But if I want to control it through periphery, how do I do that? I want to control Victor SPX. Also, could I control two of them at the same time? What is chip, and what is channel when I set up periphery in the code down below?

# Open PWM chip 0, channel 10
pwm = PWM(0, 10)

Chip is pwmchip0 and channel is pwm0 so 0,0.

Either I am dumb or something is wrong. Here is code that I used and nothing happens… Code runes no errors but nothing mover or motor even detects PWM signal. Checked with Arduino, and all works with first try. I also tried running default code for periphery and did not work too. I enabled pwm on pin 32 and tried other pins. I also checked if pwmchip is mapping and it is. And I do not have an oscilloscope to check if anything comes out. I did not move jumper, do I need to? What am I doing wrong?

from periphery import PWM
import time

# Open PWM chip 0, channel 0
pwm = PWM(0, 0)

# Set frequency to 15 kHz
pwm.frequency = 15e3

# Enable PWM output

# Set duty cycle to 20%
pwm.duty_cycle = 0.20

# Wait for 10 seconds

# Disable PWM output

# Close PWM

I even tried rung by command line and here is what I got:

yasushiko@raspberrypi:~ $ sudo ldto enable pwm-e
ls -al /sys/class/pwm
echo 0 | sudo tee /sys/class/pwm/pwmchip0/export
echo 15000000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/period
echo 7500000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm0/enable
Overlay pwm-e: applied
total 0
drwxr-xr-x  2 root root 0 Dec 31  1969 .
drwxr-xr-x 87 root root 0 Dec 31  1969 ..
lrwxrwxrwx  1 root root 0 Apr 12 21:22 pwmchip0 -> ../../devices/platform/soc/c1100000.bus/c11086c0.pwm/pwm/pwmchip0

But nothing happened. Controller continued blinking like I didn’t receive anything.

I’m seeing the same behavior on my Le Potato - did something change recently?

I’m running this system image: 2022-09-22-raspbian-bullseye-arm64-lite+aml-s905x-cc.img

…and this kernel: Linux potato 6.1.22-04692-gac1e6970fbc0 #1 SMP PREEMPT_DYNAMIC Mon Apr 3 22:49:07 UTC 2023 aarch64 GNU/Linux

For this initial test, what I want to do is get a 1KHz signal at 50% duty cycle on pin 11. This is how I am enabling it.

john@potato:~ $ sudo ldto enable pwm-ao-a
Overlay pwm-ao-a: applied

john@potato:~ $ echo 0 | sudo tee /sys/class/pwm/pwmchip0/export

john@potato:~ $ echo 1000000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/period

john@potato:~ $ echo 500000 | sudo tee /sys/class/pwm/pwmchip0/pwm0/duty_cycle

john@potato:~ $ echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm0/enable

I’m monitoring the pin with an oscilloscope and I’m not getting any output at all. I have tried a few different PWM pins and I’m getting the same experience across the board.

EDIT: I went through an tested every single pin and combination. pwm-a / pwm0 /pin33 seems to be working correctly. No others are.

1 Like

Did you reset the overlays, reboot, and then merge again?

1 Like

So I’m trying to control a pwm fan on CoreELEC for AML-S905X-CC. The Wiring Tool explicitly states it is not supported on CoreELEC. The usual commands for libgpiod do not seem to be available. Only c11086c0.pwm seems to be listed in sysfs. The npwm for this chip indicates there are 4 pwm’s available on this chip. When exporting, pwm0 and 2 are busy, but 1 and 3 are available to be exported.

If I understand correctly, pwm1 on this chip should correspond to pin 35. I’ve read that 25khz is appropriate, so I’ve set the period to 40000, the duty_cycle to 20000 and enable to 1. Nothing seems to change.

Could someone point me in the right direction?

You have to look at the code for CoreELEC. It’s based on the Amlogic kernel rather than upstream.

This is the upstream device tree:

pwm_ef = "/soc/bus@c1100000/pwm@86c0";

The header maps are here: GPIO Pin Header Maps and Wiring Tool for Libre Computer Boards

E and F are on pin 32 and 35 respectively.

Even after setting the PWM to the right frequency, you need to toggle the GPIO pinmux register to the PWM function from the GPIO function. Not sure how that is done in the Amlogic kernel. This should be setting 1 bit in memory based on the datasheet:

For example exposing PWM_E on GPIOX_16 is controlled by REG5 (PERIPHS_PIN_MUX_5 0xc88344c4) bit 15.