]> granicus.if.org Git - esp-idf/commitdiff
esp32: add support for 8MD256 and external 32k as slow clock options
authorIvan Grokhotkov <ivan@espressif.com>
Sun, 12 Aug 2018 22:12:01 +0000 (01:12 +0300)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 22 Aug 2018 03:46:24 +0000 (11:46 +0800)
components/esp32/Kconfig
components/esp32/clk.c

index 7824823a4458823f38703bf2f68ce62b9320ca07..b04a7eb2f6bd604c2e437dd473eec80bbee837f1 100644 (file)
@@ -683,18 +683,39 @@ choice ESP32_RTC_CLOCK_SOURCE
     default ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
     help
         Choose which clock is used as RTC clock source.
+        
+        - "Internal 150kHz oscillator" option provides lowest deep sleep current
+          consumption, and does not require extra external components. However
+          frequency stability with respect to temperature is poor, so time may
+          drift in deep/light sleep modes.
+        - "External 32kHz crystal" provides better frequency stability, at the
+          expense of slightly higher (1uA) deep sleep current consumption.
+        - "External 32kHz oscillator" allows using 32kHz clock generated by an
+          external circuit. In this case, external clock signal must be connected
+          to 32K_XP pin. Amplitude should be <1.2V in case of sine wave signal,
+          and <1V in case of square wave signal. Common mode voltage should be
+          0.1 < Vcm < 0.5Vamp, where Vamp is the signal amplitude.
+          Additionally, 1nF capacitor must be connected between 32K_XN pin and
+          ground. 32K_XN pin can not be used as a GPIO in this case.
+        - "Internal 8.5MHz oscillator divided by 256" option results in higher
+          deep sleep current (by 5uA) but has better frequency stability than
+          the internal 150kHz oscillator. It does not require external components.  
 
 config ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
     bool "Internal 150kHz RC oscillator"
 config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
     bool "External 32kHz crystal"
+config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC
+    bool "External 32kHz oscillator at 32K_XP pin"
+config ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256
+    bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
 endchoice
 
 config ESP32_RTC_CLK_CAL_CYCLES
     int "Number of cycles for RTC_SLOW_CLK calibration"
     default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
     default 1024 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
-    range 0 27000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
+    range 0 27000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL || ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC || ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256
     range 0 32766 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
     help
         When the startup code initializes RTC_SLOW_CLK, it can perform
index 5e7fd3371402a991b2bcf72b6193c57dde042d70..17afaa1b342a6fcc467e9b1dba39d52ff854c809 100644 (file)
 
 #define MHZ (1000000)
 
-static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk);
+/* Indicates that this 32k oscillator gets input from external oscillator, rather
+ * than a crystal.
+ */
+#define EXT_OSC_FLAG    BIT(3)
+
+/* This is almost the same as rtc_slow_freq_t, except that we define
+ * an extra enum member for the external 32k oscillator.
+ * For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
+ */
+typedef enum {
+    SLOW_CLK_150K = RTC_SLOW_FREQ_RTC,          //!< Internal 150 kHz RC oscillator
+    SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
+    SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256,     //!< Internal 8 MHz RC oscillator, divided by 256
+    SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
+} slow_clk_sel_t;
+
+static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
 
 // g_ticks_us defined in ROMs for PRO and APP CPU
 extern uint32_t g_ticks_per_us_pro;
@@ -71,8 +87,12 @@ void esp_clk_init(void)
 
     rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
 
-#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
-    select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
+#if defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL)
+    select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
+#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC)
+    select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
+#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256)
+    select_rtc_slow_clk(SLOW_CLK_8MD256);
 #else
     select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
 #endif
@@ -117,12 +137,12 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
     g_ticks_per_us_app = ticks_per_us;
 }
 
-static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
+static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
 {
+    rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
     uint32_t cal_val = 0;
-    uint32_t freq_hz = ((slow_clk == RTC_SLOW_FREQ_32K_XTAL) ? 32768 : 150000);
     do {
-        if (slow_clk == RTC_SLOW_FREQ_32K_XTAL) {
+        if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
             /* 32k XTAL oscillator needs to be enabled and running before it can
              * be used. Hardware doesn't have a direct way of checking if the
              * oscillator is running. Here we use rtc_clk_cal function to count
@@ -131,17 +151,23 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
              * will time out, returning 0.
              */
             ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
-            rtc_clk_32k_enable(true);
+            if (slow_clk == SLOW_CLK_32K_XTAL) {
+                rtc_clk_32k_enable(true);
+            } else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
+                rtc_clk_32k_enable_external();
+            }
             // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
             if (SLOW_CLK_CAL_CYCLES > 0) {
                 cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
                 if (cal_val == 0 || cal_val < 15000000L) {
-                    slow_clk = RTC_SLOW_FREQ_RTC;
                     ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
+                    rtc_slow_freq = RTC_SLOW_FREQ_RTC;
                 }
             }
+        } else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
+            rtc_clk_8m_enable(true, true);
         }
-        rtc_clk_slow_freq_set(slow_clk);
+        rtc_clk_slow_freq_set(rtc_slow_freq);
 
         if (SLOW_CLK_CAL_CYCLES > 0) {
             /* TODO: 32k XTAL oscillator has some frequency drift at startup.