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

pwm_led_esp32: Move perihperal setup to driver init. #82177

Closed
wants to merge 1 commit into from

Conversation

braiden
Copy link

@braiden braiden commented Nov 27, 2024

Fixes for #81801

Move as much peripheral initialization as possible into driver init.

Prior to this change ledc_hal_timer_rst is called every time the PWM period or duty is changed. Since ledc_hal_timer_rst resets this timer, it causes unwanted phase shifts.

Also move pwm_led_esp32_configure_pinctrl to diver init. This was also called when PWM period or duty changed, and can call a short negative glitch if the ouput is high when pwm api method is called.

Tested on esp32c3. Phase no longer shifts, and period update only on timer overflow.

Copy link

Hello @braiden, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

for (int i = 0; i < config->channel_len; i++) {
struct pwm_ledc_esp32_channel_config *channel = &config->channel_config[i];
ledc_hal_init(&data->hal, channel->speed_mode);
ledc_hal_timer_rst(&data->hal, channel->timer_num);
Copy link
Author

@braiden braiden Nov 27, 2024

Choose a reason for hiding this comment

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

While calling ledc_hal_timer_rst appears to work, I'm a little uncertain on when this method actually needs to be called. The TRM doesn't state. I know it needs to be called, simply removing ledc_hal_timer_rst results in no output.

ESP-IDF calls this method during ledc_timer_config, but only after more thoroughly configuring the timer then I can. I can't completely configure the timer, because I don't know what clock source to pick. That's because (on some hardware) the driver may pick different clocks to optimize timer resolution based on the requested PWM period in application code.

I considered leaving ledc_hal_timer_rst where it was, and only calling it the first time (and maybe when the clock selection changed).

I also considered adding some sort of hint to DT so init could pick a good timer source.

... but, I didn't want to complicate the code more than necessary to fix the issue.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@braiden This driver needs some updates!

The original idea was to optimize the clock source selection according to a given period and cycle, in such manner that the user wouldn't need to care about it. But this no longer applies after some changes in the driver. I believe ledc_hal_timer_rst must be called when updating the clock source, but since it does not change anymore, no problem on keeping it where it is for now.

Thanks for the PR and feel free to contribute in anyway to make it better.

Copy link
Author

@braiden braiden Dec 2, 2024

Choose a reason for hiding this comment

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

I think the esp32 still has two clock to choose from? So it might be possible for the clock to change if pwm duty is set very slow then very fast. (I'll check code to confirm).

If so, I think its safer I keep ledc_hal_timer_rst where was before my change, and skip reset only if clock hasn't changed by the current call to pwm_set.

Copy link
Author

@braiden braiden Dec 3, 2024

Choose a reason for hiding this comment

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

ESP32 & ESP32s2 can select either APB (80mhz), or REF_TICK (10mhz) falling back on the slower clock if period is too slow: source. The clock can change at run-time if application code requests periods that might select different clocks.

I tested on ESP32 both with and without my fix applied. In both cases there was no PWM output when REF_TICK was selected. I think this PR is still safe since its not changing any behavior here. (although the only ESP32s i had available to test with are ESP32-D0WDQ6 and require CONFIG_ESP32_USE_UNSUPPORTED_REVISION)

I can follow-up with another PR for REF_TICK. What's the best way to discuss, should I log a bug and discuss there?

sylvioalves
sylvioalves previously approved these changes Nov 28, 2024
LucasTambor
LucasTambor previously approved these changes Nov 28, 2024
@kartben
Copy link
Collaborator

kartben commented Nov 28, 2024

@braiden thanks for the PR! Could you address the tiny compliance error please, then amend your commit and force push to your branch? Thanks!

@sylvioalves
Copy link
Collaborator

@braiden I missed before: fix the typo in the commit message "peripherals".

@kartben
Copy link
Collaborator

kartben commented Nov 28, 2024

You may also want to have the message say "Fixes #81801" instead of what you have now, as I think otherwise github doesn't properly link that PR to the issue. Thank you!

edit: I just manually established the linkage

@kartben kartben linked an issue Nov 28, 2024 that may be closed by this pull request
wmrsouza
wmrsouza previously approved these changes Nov 29, 2024
@braiden
Copy link
Author

braiden commented Dec 1, 2024

Sorry, I somehow closed this PR trying to fix compliance error, new PR here:

#82387

@henrikbrixandersen
Copy link
Member

Sorry, I somehow closed this PR trying to fix compliance error, new PR here:

#82387

I've reopened it. Please close the duplicate.

fixes zephyrproject-rtos#81801

Move as much peripheral initialization as possible into driver init.

Prior to this change `ledc_hal_timer_rst` is called every time the PWM
period or duty is changed. Since `ledc_hal_timer_rst` resets this timer,
it causes unwanted phase shifts.

Also move `pwm_led_esp32_configure_pinctrl` to diver init. This was also
called when PWM period or duty changed, and can call a short negative
glitch if the ouput is high when pwm api method is called.

Signed-off-by: Braiden Kindt <braiden@kindt.dev>
@braiden
Copy link
Author

braiden commented Dec 9, 2024

I've addressed all comments. Please take a look.

@braiden
Copy link
Author

braiden commented Dec 14, 2024

I'm closing this PR as its being addressed in #82820

@braiden braiden closed this Dec 14, 2024
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.

drivers: pwm: pwm_led_esp32 outputs glitchy waveforms
7 participants