Skip to content

esp32: Fix UART rxidle and machine.Timer on ESP32-C2,C6 #17844

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

Merged
merged 2 commits into from
Aug 7, 2025

Conversation

projectgus
Copy link
Contributor

@projectgus projectgus commented Aug 6, 2025

Summary

  • Fixes a regression in ESP32-C6 when updating to IDF v5.4.1 - the 80MHz PLL is no longer enabled by default, so the RXIDLE UART interrupt never fires. Found via tests/extmod_hardware/machine_uart_irq_rxidle.py.
  • Adds a related fix, which is that the ESP32 machine.Timer implementation assumed the default timer source clock was the APB clock but it's a different clock on some chips, leading to incorrect timer periods (ESP32-C2 used 26MHz but should be 40MHz, ESP32-C6 used 40MHz but should be 80MHz).

Testing

  • Ran the extmod_hardware/machine_uart_*.py tests on ESP32-C2,C3,C6,S2 and original. All passing now.
  • Ran a homemade periodic 1 second machine.Timer test on ESP32-C2,C6 and S2. Verified incorrect tick period on C2 and C6 that is fixed with this PR. Will submit a proper unit test for this, later.

(Note: Some of these tests were run on the first version of this PR. I re-ran the latest version on C2, C6 and original ESP32.)

Trade-offs and Alternatives

  • Calling esp_clk_tree_src_get_freq_hz() to get a constant clock frequency seems inelegant compared to calculating it at compile time, but this isn't called very often (initially I thought it was being called from the ISR, which made it seem worse, but it's not!)

This work was funded through GitHub sponsors

@projectgus
Copy link
Contributor Author

@dpgeorge While testing this I reproduced a hard fault which might be the same one that you were seeing. I think that's a pre-existing bug not a regression, so I'll submit in a second PR that could be left until after the 1.26 release.

@projectgus projectgus force-pushed the bugfix/esp32c6_uart_rxidle branch from 6d122b3 to c10bcd2 Compare August 6, 2025 07:39
@dpgeorge dpgeorge added this to the release-1.26.0 milestone Aug 6, 2025
@dpgeorge
Copy link
Member

dpgeorge commented Aug 6, 2025

Thanks for debugging and fixing this so quickly!

I tested on ESP32-C6 and it does indeed fix the uart_irq_rxidle test. I'll need to eventually run the full test suite on C6 and some other SoCs, but this does look good.

2. Call esp_clk_tree_get_src_clk_freq() at runtime - which will work to return the same (constant) value, but currently the timer implementation would call this from the ISR and it seems a bit heavyweight for that.

How about calling esp_clk_tree_src_get_freq_hz() at start-up and caching the result in a variable? Then could use that variable directly, instead of calling a function.

@projectgus projectgus force-pushed the bugfix/esp32c6_uart_rxidle branch from c10bcd2 to fcaa4d7 Compare August 7, 2025 00:09
@projectgus
Copy link
Contributor Author

How about calling esp_clk_tree_src_get_freq_hz() at start-up and caching the result in a variable? Then could use that variable directly, instead of calling a function.

Yes, this is better - have changed (and re-tested on OG ESP32 and C6, same timer results.) I got a bit hung up on "this should be compile-time calculated!" 😆

Possibly caching it isn't even worth it, it's not a particularly expensive function call to make relative to the frequency of the timer ISR. (But, then again, caching it only costs 4 bytes of RAM so it's not a big trade-off either way.)

@projectgus projectgus force-pushed the bugfix/esp32c6_uart_rxidle branch from fcaa4d7 to 28b171b Compare August 7, 2025 00:12
@projectgus
Copy link
Contributor Author

Possibly caching it isn't even worth it, it's not a particularly expensive function call to make relative to the frequency of the timer ISR. (But, then again, caching it only costs 4 bytes of RAM so it's not a big trade-off either way.)

Uh, I looked again and it doesn't call this function from the Timer ISR anyway (in retrospect it's unclear why it would need to), so I've pulled out the caching as well.

@projectgus projectgus force-pushed the bugfix/esp32c6_uart_rxidle branch from 28b171b to 8cdbfd3 Compare August 7, 2025 00:16
@projectgus projectgus changed the title Bugfix/esp32c6 uart rxidle esp32: Fix UART rxidle and machine.Timer on ESP32-C2,C6 Aug 7, 2025
@dpgeorge
Copy link
Member

dpgeorge commented Aug 7, 2025

I retested this on ESP32 and ESP32-C6, and the UART IRQ tests pass.

Copy link
Member

@dpgeorge dpgeorge left a comment

Choose a reason for hiding this comment

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

Tested again with the full test suite on ESP32 and ESP32-C6. There are no new failures, and extmod_hardware/machine_uart_irq_rxidle.py now passes on C6.

Otherwise the PLL is not enabled.  These changes are adapted from
`timer_legacy.h` in ESP-IDF.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
Also future-proofs this code for other chips. Apart form C6 and C2, all
currently supported chips use APB clock for GPTIMER_CLK_SRC_DEFAULT.

ESP32-C2 uses 40MHz PLL but APB_CLK_FREQ was 26MHz.
ESP32-C6 uses 80MHz PLL but APB_CLK_FREQ was 40MHz.

Implementation now gets the correct frequency from ESP-IDF.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
@dpgeorge dpgeorge force-pushed the bugfix/esp32c6_uart_rxidle branch from 8cdbfd3 to 593ae04 Compare August 7, 2025 06:56
@dpgeorge dpgeorge merged commit 593ae04 into micropython:master Aug 7, 2025
9 checks passed
@dpgeorge
Copy link
Member

dpgeorge commented Aug 7, 2025

Now merged. Thanks again for the fast turn around on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants