1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #13061 from gschorcht/cpu/esp32/rtc_xtal_32k

cpu/esp32: allow external 32 kHz crystal for the RTC hardware timer
This commit is contained in:
benpicco 2020-02-07 10:24:22 +01:00 committed by GitHub
commit 66c7c63c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 25 deletions

View File

@ -10,5 +10,6 @@ FEATURES_PROVIDED += periph_spi
# unique features provided by the board
FEATURES_PROVIDED += sdcard_spi
FEATURES_PROVIDED += esp_spi_ram
FEATURES_PROVIDED += esp_rtc_timer_32k
FEATURES_PROVIDED += arduino

View File

@ -33,6 +33,7 @@ The Espressif ESP-WROVER-KIT is a development board that uses the ESP32-WROVER m
- 3.2" SPI LCD panel
- RGB LED
- USB bridge with JTAG interface
- external 32.768 kHz crystal for RTC
Furthermore, many GPIOs are broken out for extension. The USB bridge based on FDI FT2232HL provides a JTAG interface for OCD debugging through the USB interface.
@ -90,6 +91,7 @@ ESP-WROVER-KIT has the following on-board components
- 3.2" SPI LCD panel
- RGB LED
- USB bridge with JTAG interface
- external 32.768 kHz crystal for RTC
The following table shows the default board configuration sorted according to the defined functionality of GPIOs for different hardware options. This configuration can be overridden by \ref esp32_app_spec_conf "application-specific configurations".
@ -192,7 +194,7 @@ GPIO39 | ADC_LINE(3) | ADC_LINE(3) | ADC_LINE(3) | CA
- GPIO2 cannot be used as PWM_DEV(0) channel 1 / LED0 when SPI_DEV(0) is used in any way. Reason is that GPIO2 is the MISO signal when SPI_DEV(0) is used and is therefore an input. PWM channels are outputs.
- It might be necessary to remove the SD card or the peripheral hardware attached to the SPI_DEV(0) interface for flashing RIOT. Reason is that the **SPI_DEV(0)** interface uses the HSPI interface with the GPIO2 pin as the MISO signal, which has bootstrapping functionality.
- GPIO16 and GPIO17 are used for the built-in SPI RAM and are not available on the I/O expansion connector, even though they are labeled there.
- GPIO32 and GPIO33 are attached to a 32 kHz crystal by default. GPIO32 and GPIO33 are standard connected to a 32 kHz crystal. To make them available as a GPIO on the I/O expansion connector, SMD resistors would need to be removed and soldered.
- GPIO32 and GPIO33 are attached to a 32 kHz crystal by default. To make them available as a GPIO on the I/O expansion connector, SMD resistors would need to be removed and soldered. Module `esp_rtc_timer_32k` is enabled by default.
For detailed information about the configuration of ESP32 boards, see
section Peripherals in \ref esp32_riot.

View File

@ -43,6 +43,18 @@ ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
USEMODULE += pthread
endif
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
ifneq (,$(filter esp_rtc_timer_32k,$(USEMODULE)))
USEMODULE += esp_rtc_timer
endif
ifneq (,$(filter periph_i2c,$(USEMODULE)))
ifneq (,$(filter esp_i2c_hw,$(USEMODULE)))
USEMODULE += core_thread_flags

View File

@ -93,6 +93,7 @@ PSEUDOMODULES += esp_log_colored
PSEUDOMODULES += esp_log_tagged
PSEUDOMODULES += esp_log_startup
PSEUDOMODULES += esp_rtc_timer
PSEUDOMODULES += esp_rtc_timer_32k
PSEUDOMODULES += esp_spi_ram
PSEUDOMODULES += esp_spiffs
PSEUDOMODULES += esp_wifi_any
@ -110,7 +111,6 @@ USEMODULE += periph
USEMODULE += periph_adc_ctrl
USEMODULE += periph_hwrng
USEMODULE += periph_flash
USEMODULE += periph_rtc
USEMODULE += periph_uart
USEMODULE += riot_freertos
USEMODULE += random

View File

@ -38,9 +38,10 @@
5. [PWM Channels](#esp32_pwm_channels)
6. [SPI Interfaces](#esp32_spi_interfaces)
7. [Timers](#esp32_timers)
8. [UART Interfaces](#esp32_uart_interfaces)
9. [CAN Interfaces](#esp32_can_interfaces)
10. [Other Peripherals](#esp32_other_peripherals)
8. [RTC Timer](#esp32_rtc_timer)
9. [UART Interfaces](#esp32_uart_interfaces)
10. [CAN Interfaces](#esp32_can_interfaces)
11. [Other Peripherals](#esp32_other_peripherals)
7. [Special On-board Peripherals](#esp32_special_on_board_peripherals)
1. [SPI RAM Modules](#esp32_spi_ram)
2. [SPIFFS Device](#esp32_spiffs_device)
@ -118,6 +119,8 @@ Module | Default | Short description
[esp_log_startup](#esp32_esp_log_module) | not used | enable additional startup information
[esp_log_tagged](#esp32_esp_log_module) | not used | add additional information to the log output
[esp_now](#esp32_esp_now_network_interface) | not used | enable the ESP-NOW network device
[esp_rtc_timer](#esp32_rtc_timer) | not used | enable RTC hardware timer with internal 150 kHz RC oscillator
[esp_rtc_timer_32k](#esp32_rtc_timer) not used | enable RTC hardware timer with external 32.768 kHz crystal.
[esp_spi_ram](#esp32_spi_ram) | not used | enable SPI RAM
[esp_spiffs](#esp32_spiffs_device) | not used | enable SPIFFS for on-board flash memory
[esp_wifi](#esp32_wifi_network_interface) | not used | enable the Wifi network device
@ -416,6 +419,8 @@ esp_log_colored | Enable colored log output, see section [Log output](#esp32_esp
esp_log_startup | Enable additional startup information, see section [Log output](#esp32_esp_log_module).
esp_log_tagged | Add additional information to the log output, see section [Log output](#esp32_esp_log_module).
esp_now | Enable the built-in WiFi module with the ESP-NOW protocol as `netdev` network device, see section [ESP-NOW Network Interface](#esp32_esp_now_network_interface).
esp_rtc_timer | Enable RTC hardware timer with internal 150 kHz RC oscillator.
esp_rtc_timer_32k | Enable RTC hardware timer with external 32.768 kHz crystal.
esp_spiffs | Enable the optional SPIFFS drive in on-board flash memory, see section [SPIFFS Device](#esp32_spiffs_device).
esp_spi_ram | Enable the optional SPI RAM, see section [SPI RAM Modules](#esp32_spi_ram).
esp_wifi | Enable the built-in WiFi module as `netdev` network device, see section [WiFi Network Interface](#esp32_wifi_network_interface).
@ -826,6 +831,38 @@ to application's makefile.
Timers are MCU built-in features and not board-specific. There is nothing to be configured.
\anchor esp32_rtc_timer
## <a name="esp32_rtc_timer"> RTC Timer </a> &nbsp;[[TOC](#esp32_toc)]
The RTC hardware timer of the ESP32 can be clocked with either an external
32.768 kHz crystal or the internal adjustable 150 kHz RC oscillator. If the
the external 32.768 kHz crystal is not available, 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`
can be used to control which timer is used by the RTC low-level driver
as following:
- **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.
If none of the modules above is enabled, the PLL-driven **emulated RTC timer**
is used. In this case, the RTC hardware timer with the internal RC 150 kHz
oscillator is only used in deep sleep mode and during a reset.
@note The accuracy of the emulated RTC timer is better than the accuracy of the
RTC hardware timer with the internal 150 kHz RC oscillator. If you have not
connected an external 32.768 kHz crystal, you should use the default
configuration.
\anchor esp32_uart_interfaces
## <a name="esp32_uart_interfaces"> UART Interfaces </a> &nbsp;[[TOC](#esp32_toc)]
@ -920,7 +957,6 @@ when needed.
The ESP32 port of RIOT also supports:
- hardware number generator with 32 bit
- RTC device
- CPU-ID function
- Vref measurement function
- power management functions

View File

@ -218,8 +218,13 @@ gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] = {
_NOT_EXIST, /* gpio29 */
_NOT_EXIST, /* gpio30 */
_NOT_EXIST, /* gpio31 */
#if MODULE_ESP_RTC_TIMER_32K
_NOT_EXIST, /* gpio32 used for external 32K crystal */
_NOT_EXIST, /* gpio33 used for external 32K crystal */
#else
_GPIO, /* gpio32 */
_GPIO, /* gpio33 */
#endif
_GPIO, /* gpio34 */
_GPIO, /* gpio35 */
_GPIO, /* gpio36 */

View File

@ -20,11 +20,28 @@
*/
/*
* If module esp_rtc_timer is enabled, the 48-bit RTC hardware timer is used
* directly. Otherwise the PLL driven 64-bit microsecond system timer is used
* to emulate a RTC timer (default). This emulated RTC timer results into much
* better accuracy. The Advantage of using RTC hardware timer over system timer
* is that it would also continue in deep sleep mode and after software reset.
* The RTC low-level driver uses either the RTC hardware timer directly or the
* PLL-controlled 64-bit microsecond system timer to emulate an RTC timer. The
* RTC hardware timer can be clocked with either an external 32.768 kHz crystal
* or an internal adjustable 150 kHz RC oscillator. Which RTC timer is used,
* is controlled by modules as following:
*
* default
* Since the RTC hardware timer with the 150 kHz RC oscillator is less
* accurate than the emulated RTC timer, the emulated RTC timer is used by
* default. In this case, the RTC hardware timer is only used with the
* internal 150 kHz oscillator in deep sleep mode and during a reset.
*
* module `esp_rtc_timer`
* To use the RTC hardware timer with the 150 kHz Oscilator, the module
* `esp_rtc_timer` has to be enabled.
*
* module `esp_rtc_timer_32k`
* To use the RTC hardware timer with the external 32.768 kHz crystal, the
* module 'esp_rtc_timer_32k` has to be enabled. If the module
* `esp_rtc_timer_32k` is used, but no external 32.768 kHz crystal is
* available, the RTC low-level driver uses the RTC hardware driver,
* but with the internal 150 kHz RC oscillator.
*/
#define ENABLE_DEBUG (0)
@ -51,6 +68,9 @@
#define TIMER_SYSTEM_INT_MASK BIT(0)
#define TIMER_SYSTEM_INT_SRC ETS_TG0_T0_LEVEL_INTR_SOURCE
/* RTC timer interrupt source */
#define TIMER_RTC_INT_SRC ETS_RTC_CORE_INTR_SOURCE
#define RTC_CLK_CAL_FRACT 19 /* fractional bits of calibration value */
/* we can't include soc/rtc.h because of rtc_init declaration conflicts */
@ -64,7 +84,7 @@ static time_t _sys_alarm_time = 0;
#define RTC_BSS_ATTR __attribute__((section(".rtc.bss")))
/* save several time stamps */
/* save several time stamps in RTC memory */
static uint64_t RTC_BSS_ATTR _rtc_time_init_us; /* RTC time on init in us */
static uint64_t RTC_BSS_ATTR _rtc_time_init; /* RTC time on init in cycles */
static uint64_t RTC_BSS_ATTR _rtc_time_set_us; /* RTC time on set in us */
@ -164,19 +184,12 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
_sys_alarm_time = mktime(time);
time_t _sys_time_offset = _sys_alarm_time - _sys_time_set;
/*
* RTC doesn't provide alarm functionality in active mode. At least
* the RTC main timer seems not to work. Therefore we always use the
* system timer for alarms. The Advantage of using RTC over system timer
* is that it also continues in deep sleep and after software reset.
*/
#if 0 /* TODO should be MODULE_ESP_RTC_TIMER */
#if MODULE_ESP_RTC_TIMER
/* determine the offset of alarm time to current time in RTC time */
uint64_t _rtc_time_alarm;
_rtc_time_alarm = _rtc_time_set + _sys_time_offset * rtc_clk_slow_freq_get_hz();
DEBUG("%s sys=%d sys_alarm=%d rtc=%lld rtc_alarm=%lld\n", __func__,
DEBUG("%s sys=%ld sys_alarm=%ld rtc=%lld rtc_alarm=%lld\n", __func__,
_sys_get_time(), _sys_time_offset, _rtc_get_time_raw(), _rtc_time_alarm);
/* set the timer value */
@ -193,7 +206,7 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
RTCCNTL.int_ena.rtc_main_timer = 1;
/* route all RTC interrupt sources to the same level type interrupt */
intr_matrix_set(PRO_CPU_NUM, DPORT_PRO_RTC_CORE_INTR_MAP_REG, CPU_INUM_RTC);
intr_matrix_set(PRO_CPU_NUM, ETS_RTC_CORE_INTR_SOURCE, CPU_INUM_RTC);
/* set interrupt handler and enable the CPU interrupt */
xt_set_interrupt_handler(CPU_INUM_RTC, _rtc_timer_handler, NULL);
@ -238,7 +251,7 @@ void rtc_clear_alarm(void)
_rtc_alarm_cb = NULL;
_rtc_alarm_arg = NULL;
#if 0 /* TODO should be MODULE_ESP_RTC_TIMER, see rtc_set_alarm */
#if MODULE_ESP_RTC_TIMER
/* disable RTC timer alarm and disable the RTC timer interrupt */
RTCCNTL.slp_timer1.main_timer_alarm_en = 0;
@ -301,10 +314,12 @@ static void IRAM_ATTR _rtc_timer_handler(void* arg)
{
irq_isr_enter();
#if 0 /* TODO should be MODULE_ESP_RTC_TIMER */
#if MODULE_ESP_RTC_TIMER
/* check for RTC timer interrupt */
/* check for RTC timer interrupt */
if (RTCCNTL.int_st.rtc_main_timer) {
/* disable RTC timer alarm */
RTCCNTL.slp_timer1.main_timer_alarm_en = 0;
/* clear the interrupt */
RTCCNTL.int_clr.rtc_main_timer = 1;
/* call back registered function */

View File

@ -215,8 +215,13 @@ static void IRAM system_clk_init (void)
/* set FAST_CLK to internal low power clock of 8 MHz */
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
#if MODULE_ESP_RTC_TIMER_32K
/* set SLOW_CLK to external 32.768 kHz crystal clock */
rtc_select_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
#else
/* set SLOW_CLK to internal low power clock of 150 kHz */
rtc_select_slow_clk(RTC_SLOW_FREQ_RTC);
#endif
LOG_STARTUP("Switching system clocks can lead to some unreadable characters\n");
@ -326,11 +331,13 @@ static NORETURN void IRAM system_init (void)
periph_init();
/* print system time */
#ifdef MODULE_PERIPH_RTC
struct tm _sys_time;
rtc_get_time(&_sys_time);
LOG_STARTUP("System time: %04d-%02d-%02d %02d:%02d:%02d\n",
_sys_time.tm_year + 1900, _sys_time.tm_mon + 1, _sys_time.tm_mday,
_sys_time.tm_hour, _sys_time.tm_min, _sys_time.tm_sec);
#endif
/* print the board config */
#ifdef MODULE_ESP_LOG_STARTUP