Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: pwm_led: esp32: Driver update #82820

Merged
merged 10 commits into from
Jan 18, 2025

Conversation

raffarost
Copy link
Collaborator

@raffarost raffarost commented Dec 10, 2024

Update LEDC driver in order to address GH reported issues and improve clock management.

Following behaviors are ensured:

  • inverted PWM
  • default signal level after driver init, as configured
  • PWM is now stopped when 0% or 100% duty is selected, to allow using max timer resolution
  • transitions when frequency is updated follows timer overflow (synced transition)
  • transition for 0% or 100% duty is immediate
  • timer can only be shared by two or more channels if frequency is the same. If new value for frequency is requested, it will be rejected to avoid cross-channel interference.

Note: changes were kept in several commits to facilitate review, but can be squashed if requested.

@braiden
Copy link

braiden commented Dec 11, 2024

Thanks for this, I think it can supersede my PR #82177? I'll merge and test.

There's an open comment on my PR that still worth consideration here: I proposed either supporting only one clock source or, moving the clock source to the device tree.

The rationale: All low speed channels share the same clock source. On a device such as esp32 that has multiple clock choices: suppose there are two distinct PWM low-speed channels each using a distinct timer. Then call set_cycles to configure ch0 with a small period selecting APB clock. Then call set_cycles for ch1 with a very long period so it picks REF_TICK clock. ch1 cannot modify the clock w/o squishing or stretching the PWM output already running on ch0. Even though the channel and timer are distinct, clocks are shared (for low speed).

Thoughts? Initialize an immutable clock source in driver init, rather than reconfiguration on-the-fly?

In any-case thanks for PR: LGTM. My issue's not a new bug and exists before and after this PR.

@braiden
Copy link

braiden commented Dec 12, 2024

I tested on esp32c3 working-as-intended but, one suggestion:

Do you think it makes sense to reinitialize/reset the timer only when the clock selection changes, rather than every time the frequency changes? As-is here's what it looks like when I change the freq:

Screenshot_2024-12-11_20-37-29

If the timer had not been reset, the trigger point would be updated on the next overflow resulting in a smooth transition to the new frequency.

@raffarost
Copy link
Collaborator Author

hi @braiden
your comments on clock management are right, there's some good improvement to be done in the driver
I'll try to take into account all the comments and work on it in the next weeks
thanks for your input

@raffarost raffarost changed the title drivers: pwm_led: esp32: fix frequency config drivers: pwm_led: esp32: Driver update Dec 19, 2024
@raffarost
Copy link
Collaborator Author

@epc-ake @braiden can you take a look to see if your concerns were addressed?
if you are okay with the changes I'll open the PR for reviewing

@raffarost raffarost force-pushed the fix/ledc_pwm branch 2 times, most recently from ec8fba7 to 033d38c Compare January 7, 2025 18:15
@raffarost raffarost requested a review from LucasTambor January 7, 2025 18:19
@raffarost
Copy link
Collaborator Author

Thanks for this, I think it can supersede my PR #82177? I'll merge and test.

There's an open comment on my PR that still worth consideration here: I proposed either supporting only one clock source or, moving the clock source to the device tree.

The rationale: All low speed channels share the same clock source. On a device such as esp32 that has multiple clock choices: suppose there are two distinct PWM low-speed channels each using a distinct timer. Then call set_cycles to configure ch0 with a small period selecting APB clock. Then call set_cycles for ch1 with a very long period so it picks REF_TICK clock. ch1 cannot modify the clock w/o squishing or stretching the PWM output already running on ch0. Even though the channel and timer are distinct, clocks are shared (for low speed).

Thoughts? Initialize an immutable clock source in driver init, rather than reconfiguration on-the-fly?

In any-case thanks for PR: LGTM. My issue's not a new bug and exists before and after this PR.

I attempted the testcase you mention above and here's what I get:

START - test_pwm_nsec
[PWM]: 0, [period]: 1000000000, [pulse]: 500000000
D: channel_num=0, speed_mode=1, timer_num=0, clock_src=11, prescaler=488, resolution=19
[PWM]: 1, [period]: 100, [pulse]: 50
D: channel_num=1, speed_mode=1, timer_num=1, clock_src=4, prescaler=256, resolution=3
 PASS - test_pwm_nsec in 0.024 seconds

Signals are fine on the oscilloscope. The condition you mention makes sense when the same timer is used instead, and for this situation a check is now made on pwm_set to avoid using the same timer while setting different frequencies. Timers can still be shared using the same frequency but setting different duty cycles on the channels.

@epc-ake
Copy link
Contributor

epc-ake commented Jan 9, 2025

Hi @raffarost
I tried out this PR.
I tried it using the led_shell and pwm_shell (CONFIG_LED_SHELL and CONFIG_PWM_SHELL enabled. )

First I had some trouble with the led_shell and setting led brightness.
I had set the pwm frequency to a low 100 HZ. That caused the following errors.

<err> pwm_ledc_esp32: Error finding timer config for channel 0 for requested frequency
<err> pwm_ledc_esp32: Error finding timer config for channel 0 for requested frequency

I got the same errors when trying to set a 100Hz frequency with the pwm_shell:
pwm usec ledc@60019000 0 1000 900

Increasing it to 1000Hz fixed it though.

Is there a reason why low frequencies are not supported?
e.g. low frequencies could be nice to let an LED blink.

@raffarost
Copy link
Collaborator Author

Hi @raffarost I tried out this PR. I tried it using the led_shell and pwm_shell (CONFIG_LED_SHELL and CONFIG_PWM_SHELL enabled. )

First I had some trouble with the led_shell and setting led brightness. I had set the pwm frequency to a low 100 HZ. That caused the following errors.

<err> pwm_ledc_esp32: Error finding timer config for channel 0 for requested frequency
<err> pwm_ledc_esp32: Error finding timer config for channel 0 for requested frequency

I got the same errors when trying to set a 100Hz frequency with the pwm_shell: pwm usec ledc@60019000 0 1000 900

Increasing it to 1000Hz fixed it though.

Is there a reason why low frequencies are not supported? e.g. low frequencies could be nice to let an LED blink.

hello @epc-ake
which device are you using? S3?
As the clock source is automatically selected, this can happen indeed, while the configuration (possibly HAL) needs further checks. With ESP32 I tested from 1 Hz to 10 Mhz, but it looks like I need to test more on other devices :)
Thanks for the input, I'll have a look.

@epc-ake
Copy link
Contributor

epc-ake commented Jan 9, 2025

which device are you using? S3?

Yes I'm using the esp32s3.

@raffarost
Copy link
Collaborator Author

I included the fix that is already in place in the driver, so now it reaches 10 Hz on S3 and preserves the original functionality.

@epc-ake
Copy link
Contributor

epc-ake commented Jan 9, 2025

I included the fix that is already in place in the driver, so now it reaches 10 Hz on S3 and preserves the original functionality.

confirmed 👍

@raffarost raffarost marked this pull request as ready for review January 9, 2025 18:29
@zephyrbot zephyrbot added platform: ESP32 Espressif ESP32 area: PWM Pulse Width Modulation labels Jan 9, 2025
wmrsouza
wmrsouza previously approved these changes Jan 9, 2025
sylvioalves
sylvioalves previously approved these changes Jan 10, 2025
sylvioalves
sylvioalves previously approved these changes Jan 13, 2025
marekmatej
marekmatej previously approved these changes Jan 13, 2025
Copy link

@marekmatej marekmatej left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a nits, LTGM

drivers/pwm/pwm_led_esp32.c Outdated Show resolved Hide resolved
epc-ake and others added 10 commits January 16, 2025 09:34
This PR enables the PWM to be inverted by making use of the
`PWM_POLARITY_INVERTED` flag.
It also fixes an overflow bug when setting duty-cycle to 100 percent.

Signed-off-by: Armin Kessler <ake@espros.com>
Set pwm init state to value defined in flags field.
Furthermore 100 percent is now actually 100 percent and not 99.

Signed-off-by: Armin Kessler <ake@espros.com>
At driver init channels frequency are unknown, thus timer config
may take place only at set_cycles(). To avoid phase shifts,
timers are only reconfigured if a new frequency is requested.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Disable PWM output for duty 0% or 100%, to allow using max timers
resolution. Move timer reset to init function in order to ensure
smooth frequency transitions.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Cleanup and functions organization. Clock source selection added
to init to allow proper setting of default level when signal is
inverted.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Include condition to block pwm_set operation when the same timer
is shared but a different frequency is requested. First set
operation will take precedence.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Update clock management to better support new devices.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Clang check for formatting.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Add inverted flag to bindings, as pwms field is supposed
to be used by application only.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Add test cases to include coverage for ESP32 HS channels.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
@raffarost
Copy link
Collaborator Author

raffarost commented Jan 17, 2025

Hi @kartben
Is this PR missing something we can do (to have it merged)?

@kartben kartben merged commit 713375a into zephyrproject-rtos:main Jan 18, 2025
24 checks passed
@kartben
Copy link
Collaborator

kartben commented Jan 18, 2025

Hi @kartben Is this PR missing something we can do (to have it merged)?

It was missing approval from the assignee, PWM maintainer @anangl
Given this really only touched esp32 specific code, I've taken the liberty to merge.

@raffarost raffarost deleted the fix/ledc_pwm branch January 18, 2025 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: PWM Pulse Width Modulation platform: ESP32 Espressif ESP32
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants