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

cpu/esp32: allow external 32 kHz crystal for the RTC hardware timer #13061

Merged
merged 2 commits into from
Feb 7, 2020

Conversation

gschorcht
Copy link
Contributor

@gschorcht gschorcht commented Jan 9, 2020

Contribution description

This PR changes the RTC low-level driver to allow the use of the RTC hardware timer with an external 32.768 kHz crystal.

The RTC hardware timer of ESP32 can be clocked with either an external 32.768 kHz crystal or an internal adjustable 150 kHz RC oscillator. If the the external 32.768 kHz crystal is not available (as on most boards), the internal 150 kHz RC oscillator is used automatically. However, since this internal 150 kHz RC oscillator is not very accurate, the RTC low-level driver uses by default the PLL-controlled 64-bit microsecond system timer to emulate the RTC timer.

To allow the use of the RTC hardware timer for boards with an external 32 kHz crystal, the pseudomodules esp_rtc_timer and esp_rtc_timer_32k have been defined to control which timer is used for RTC as following:

  • default
    Use the emulated RTC timer. The RTC hardware timer with the internal RC 150 kHz oscillator is only used in deep sleep mode and during a reset.

  • esp_rtc_timer
    Use always the RTC hardware timer with the internal 150 kHz RC oscillator.

  • esp_rtc_timer_32k
    Use the RTC hardware timer with the external 32.768 kHz crystal. If the external 32.768 kHz crystal is not available, the RTC hardware timer is used with the internal 150 kHz RC oscillator.

Furthermore, module esp_rtc_timer_32k is enabled by default for board esp32-wrover-kit by this PR.

This PR requires the bootloader images and the automatic XTAL clock detection from PR #13059.

Testing procedure

  1. Use a board with and a board without external 32.768 kHz crystal. Flash and test both boards with

    LOG_LEVEL=4 make BOARD=esp32-wroom-32 -C test/periph_rtc flash test
    

    and

    LOG_LEVEL=4 USEMODULE=esp_rtc_timer_32 make BOARD=esp32-wroom-32 -C test/periph_rtc flash test
    

    All tests should work as expected. Module esp_rtc_timer_32 depends on module esp_rtc_timer so that all cases are covered.

  2. Use a terminal program, reset the boards and check for following output during startup. SLOW is the clock used for RTC timer:

    • with enabled esp_rtc_timer_32k and the board with 32.768 kHz crystal:
      Used clocks in Hz: CPU=80000000 APB=80000000 XTAL=40000000 FAST=8000000 SLOW=32768
      
    • with enabled esp_rtc_timer_32k and the board w/o 32.768 kHz crystal:
      RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain
      Used clocks in Hz: CPU=80000000 APB=80000000 XTAL=40000000 FAST=8000000 SLOW=150000
      
    • w/o module esp_rtc_timer_32k and any board:
      Used clocks in Hz: CPU=80000000 APB=80000000 XTAL=40000000 FAST=8000000 SLOW=150000
      

Issues/PRs references

Depends on PR #13059

@gschorcht gschorcht force-pushed the cpu/esp32/rtc_xtal_32k branch 2 times, most recently from 52c17b0 to 7a3a48c Compare January 9, 2020 16:00
@gschorcht gschorcht added Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ESP Platform: This PR/issue effects ESP-based platforms Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation labels Jan 9, 2020
@gschorcht gschorcht requested a review from benpicco January 10, 2020 07:27
@@ -1,6 +1,7 @@
PSEUDOMODULES += esp32_wrover_kit_camera

USEMODULE += boards_common_esp32
USEMODULE += esp_rtc_timer_32k
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we always want to build the RTC?
I'd rather put

ifneq (,$(filter periph_rtc,$(USEMODULE)))
  USEMODULE += esp_rtc_timer_32k
endif

in the board's Makefile.dep. Or maybe add a new FEATURES_PROVIDED.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

esp_rtc_timer_32 is just a pseudomodule to control the compilation in cpu/esp32/periph/rtc.c and doesn't depend on periph_rtc. RTC is only compiled if module periph_rtc is used.

Copy link
Contributor

@benpicco benpicco Feb 5, 2020

Choose a reason for hiding this comment

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

Ah I see - but then it would probably be better semantics to set

FEATURES_PROVIDED += esp_rtc_timer_32k

in Makefile.features

Copy link
Contributor Author

@gschorcht gschorcht Feb 5, 2020

Choose a reason for hiding this comment

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

However, if I am right, we would need an additional FEATURES_OPTIONAL in MCU's Makefile.include to use the esp32_rtc_timer_32k module when the feature is provided.

Copy link
Contributor

@benpicco benpicco Feb 5, 2020

Choose a reason for hiding this comment

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

Yes and then check FEATURES_USED to select the the proper implementation.
Maybe a bit more convoluted, but certainly the 'cleaner' solution.

@benpicco
Copy link
Contributor

On esp32-wroom-32 I get

RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain

RTC still works as before.

Since this automatically falls back to the internal oscillator, is there any reason to not always use esp_rtc_timer_32k?

I also get a slightly smaller binary with this compared to the default behavior.

@gschorcht
Copy link
Contributor Author

Since this automatically falls back to the internal oscillator, is there any reason to not always use esp_rtc_timer_32k?

Yes. esp_rtc_timer and esp_rtc_timer_32k are used to control what timer/clock is used for RTC module:

  • default:
    The PLL-controlled system clock is used to emulate a RTC. The hardware RTC is then only used in deepsleep mode and during reboot.

  • esp_rtc_timer:
    The RTC hardware timer with the internal 150 kHz RC oscillator is always used.

  • esp_rtc_timer_32k:
    The RTC hardware timer with the external 32.768 kHz crystal is always used. If the
    external 32.768 kHz crystal is not available, the RTC hardware timer is used with the internal 150 kHz RC oscillator.

The problem is that the accuracy of the RTC hardware timer with the internal 150 kHz RC oscillator is much worse than the accuracy of the emulated RTC timer. So if you don't have an external 32.768 kHz crystal connected, it is better to use the default configuration with the emulated RTC. Otherwise the system time would drift quite fast (up to 3 seconds per minute).

Therefore, the user has to enable the esp_rtc_timer module explicitly. If the board has a 32.768 kHz crystal connected, module esp_rtc_timer can be used to enable the hardware RTC as the default cofiguration.

@gschorcht
Copy link
Contributor Author

I committed a small change that avoids that module periph_rtc is enabled by default. This avoids the compilation of cpu/esp32/periph/rtc.c.

@gschorcht gschorcht force-pushed the cpu/esp32/rtc_xtal_32k branch from 8edc752 to d024771 Compare February 6, 2020 16:59
Comment on lines +51 to +57
ifneq (,$(filter periph_rtc,$(USEMODULE)))
FEATURES_OPTIONAL += esp_rtc_timer_32k
endif

ifneq (,$(filter esp_rtc_timer_32k,$(FEATURES_USED)))
USEMODULE += esp_rtc_timer_32k
endif
Copy link
Contributor

@benpicco benpicco Feb 6, 2020

Choose a reason for hiding this comment

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

I'm a bit surprised this works, since FEATURES_USED only gets set by Makefile.features, but I guess that's just the magic of makes dynamic variables.
I compile-tested esp32-wrover-kit and there the esp_rtc_timer_32k path gets build, as opposed to esp32-wroom-32 - nice!

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

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

Works as intended - please squash.

@gschorcht gschorcht force-pushed the cpu/esp32/rtc_xtal_32k branch from d024771 to 1e71606 Compare February 6, 2020 23:48
@benpicco benpicco merged commit 66c7c63 into RIOT-OS:master Feb 7, 2020
@gschorcht
Copy link
Contributor Author

@benpicco Thanks for reviewing, testing and merging.

@gschorcht gschorcht deleted the cpu/esp32/rtc_xtal_32k branch February 7, 2020 09:46
@leandrolanzieri leandrolanzieri added this to the Release 2020.04 milestone Feb 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ESP Platform: This PR/issue effects ESP-based platforms Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants