rtc: add function to en/disable the rtc clock

This commit is contained in:
Cao Sen Miao 2020-11-23 15:35:09 +08:00 committed by Angus Gratton
parent f09b8ae7a4
commit e338a2e3df
16 changed files with 292 additions and 2 deletions

View File

@ -5,8 +5,12 @@ if(${target} STREQUAL "esp32")
list(APPEND requires efuse)
endif()
idf_component_register(SRCS "compare_set.c"
"cpu_util.c"
set(srcs "compare_set.c" "cpu_util.c")
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "clk_ctrl_os.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include
REQUIRES ${requires}
PRIV_REQUIRES efuse

View File

@ -0,0 +1,56 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <freertos/FreeRTOS.h>
#include "soc/clk_ctrl_os.h"
#define DELAY_RTC_CLK_SWITCH 5
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
static uint8_t s_periph_ref_counts = 0;
static uint32_t s_rtc_clk_freq = 0; // Frequency of the 8M/256 clock in Hz
bool periph_rtc_dig_clk8m_enable(void)
{
portENTER_CRITICAL(&periph_spinlock);
if (s_periph_ref_counts == 0) {
rtc_dig_clk8m_enable();
s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100));
if (s_rtc_clk_freq == 0) {
portEXIT_CRITICAL(&periph_spinlock);
return false;
}
}
s_periph_ref_counts++;
portEXIT_CRITICAL(&periph_spinlock);
return true;
}
uint32_t periph_rtc_dig_clk8m_get_freq(void)
{
return s_rtc_clk_freq * 256;
}
void periph_rtc_dig_clk8m_disable(void)
{
portENTER_CRITICAL(&periph_spinlock);
assert(s_periph_ref_counts > 0);
s_periph_ref_counts--;
if (s_periph_ref_counts == 0) {
s_rtc_clk_freq = 0;
rtc_dig_clk8m_disable();
}
portEXIT_CRITICAL(&periph_spinlock);
}

View File

@ -2,3 +2,7 @@ COMPONENT_SRCDIRS := . port/$(IDF_TARGET)
COMPONENT_ADD_INCLUDEDIRS := . include port/$(IDF_TARGET)/private_include
port/$(IDF_TARGET)/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion
ifdef IS_BOOTLOADER_BUILD
COMPONENT_OBJEXCLUDE += clk_ctrl_os.o
endif

View File

@ -0,0 +1,50 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/rtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief This function is used to enable the digital 8m rtc clock,
* to support the peripherals.
*
* @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable`
* function needs to be called same times to disable.
*
* @return true: success for enable the rtc 8M clock, false: rtc 8M clock enable failed
*/
bool periph_rtc_dig_clk8m_enable(void);
/**
* @brief This function is used to disable the rtc digital clock, which should be called
* with the `periph_rtc_dig_clk8m_enable` pairedly
*
* @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable`
* function needs to be called same times to disable.
*/
void periph_rtc_dig_clk8m_disable(void);
/**
* @brief This function is used to get the real clock frequency value of the rtc clock
*
* @return The real clock value
*/
uint32_t periph_rtc_dig_clk8m_get_freq(void);
#ifdef __cplusplus
}
#endif

View File

@ -101,6 +101,7 @@
#define RTC_PLL_FREQ_320M 320
#define RTC_PLL_FREQ_480M 480
#define DELAY_RTC_CLK_SWITCH 5
static void rtc_clk_cpu_freq_to_8m(void);
static void rtc_clk_bbpll_disable(void);
@ -773,6 +774,18 @@ uint32_t rtc_clk_apb_freq_get(void)
return freq_hz - remainder;
}
void rtc_dig_clk8m_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
void rtc_dig_clk8m_disable(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/

View File

@ -167,3 +167,11 @@ void rtc_clk_wait_for_slow_cycle(void)
esp_rom_delay_us(1);
}
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
{
if (cal_val == 0) {
return 0; // cal_val will be denominator, return 0 as the symbol of failure.
}
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val;
}

View File

@ -37,6 +37,7 @@ static const char *TAG = "rtc_clk";
#define RTC_PLL_FREQ_320M 320
#define RTC_PLL_FREQ_480M 480
#define DELAY_RTC_CLK_SWITCH 5
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
static int s_cur_pll_freq;
@ -559,6 +560,18 @@ void rtc_clk_8m_divider_set(uint32_t div)
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
}
void rtc_dig_clk8m_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
void rtc_dig_clk8m_disable(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/

View File

@ -179,3 +179,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor
esp_rom_delay_us(1);
}
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
{
if (cal_val == 0) {
return 0; // cal_val will be denominator, return 0 as the symbol of failure.
}
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val;
}

View File

@ -37,6 +37,7 @@ static const char *TAG = "rtc_clk";
#define RTC_PLL_FREQ_320M 320
#define RTC_PLL_FREQ_480M 480
#define DELAY_RTC_CLK_SWITCH 5
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
// On the ESP32-S2, 480MHz PLL is enabled at reset.
@ -539,6 +540,18 @@ void rtc_clk_8m_divider_set(uint32_t div)
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
}
void rtc_dig_clk8m_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
void rtc_dig_clk8m_disable(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/

View File

@ -184,3 +184,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor
esp_rom_delay_us(1);
}
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
{
if (cal_val == 0) {
return 0; // cal_val will be denominator, return 0 as the symbol of failure.
}
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val;
}

View File

@ -38,6 +38,7 @@ static const char *TAG = "rtc_clk";
#define RTC_PLL_FREQ_320M 320
#define RTC_PLL_FREQ_480M 480
#define DELAY_RTC_CLK_SWITCH 5
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
static int s_cur_pll_freq = RTC_PLL_FREQ_480M;
@ -556,6 +557,18 @@ void rtc_clk_8m_divider_set(uint32_t div)
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
}
void rtc_dig_clk8m_enable(void)
{
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
void rtc_dig_clk8m_disable(void)
{
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}
/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/

View File

@ -178,3 +178,11 @@ void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any mor
esp_rom_delay_us(1);
}
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
{
if (cal_val == 0) {
return 0; // cal_val will be denominator, return 0 as the symbol of failure.
}
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val;
}

View File

@ -459,6 +459,29 @@ uint64_t rtc_time_get(void);
*/
void rtc_clk_wait_for_slow_cycle(void);
/**
* @brief Enable the rtc digital 8M clock
*
* This function is used to enable the digital rtc 8M clock to support peripherals.
* For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above.
*/
void rtc_dig_clk8m_enable(void);
/**
* @brief Disable the rtc digital 8M clock
*
* This function is used to disable the digital rtc 8M clock, which is only used to support peripherals.
*/
void rtc_dig_clk8m_disable(void);
/**
* @brief Caculate the real clock value after the clock calibration
*
* @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal`
* @return The real value of the clock has been measured
*/
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
/**
* @brief sleep configuration for rtc_sleep_init function
*/

View File

@ -562,6 +562,29 @@ uint64_t rtc_deep_slp_time_get(void);
*/
void rtc_clk_wait_for_slow_cycle(void);
/**
* @brief Enable the rtc digital 8M clock
*
* This function is used to enable the digital rtc 8M clock to support peripherals.
* For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above.
*/
void rtc_dig_clk8m_enable(void);
/**
* @brief Disable the rtc digital 8M clock
*
* This function is used to disable the digital rtc 8M clock, which is only used to support peripherals.
*/
void rtc_dig_clk8m_disable(void);
/**
* @brief Caculate the real clock value after the clock calibration
*
* @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal`
* @return The real value of the clock has been measured
*/
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
/**
* @brief Power down flags for rtc_sleep_pd function
*/

View File

@ -588,6 +588,29 @@ uint64_t rtc_deep_slp_time_get(void);
*/
void rtc_clk_wait_for_slow_cycle(void);
/**
* @brief Enable the rtc digital 8M clock
*
* This function is used to enable the digital rtc 8M clock to support peripherals.
* For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above.
*/
void rtc_dig_clk8m_enable(void);
/**
* @brief Disable the rtc digital 8M clock
*
* This function is used to disable the digital rtc 8M clock, which is only used to support peripherals.
*/
void rtc_dig_clk8m_disable(void);
/**
* @brief Caculate the real clock value after the clock calibration
*
* @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal`
* @return The real value of the clock has been measured
*/
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
/**
* @brief Power down flags for rtc_sleep_pd function
*/

View File

@ -562,6 +562,29 @@ uint64_t rtc_deep_slp_time_get(void);
*/
void rtc_clk_wait_for_slow_cycle(void);
/**
* @brief Enable the rtc digital 8M clock
*
* This function is used to enable the digital rtc 8M clock to support peripherals.
* For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above.
*/
void rtc_dig_clk8m_enable(void);
/**
* @brief Disable the rtc digital 8M clock
*
* This function is used to disable the digital rtc 8M clock, which is only used to support peripherals.
*/
void rtc_dig_clk8m_disable(void);
/**
* @brief Caculate the real clock value after the clock calibration
*
* @param cal_val average slow clock period in microseconds, can be return from `rtc_clk_cal`
* @return The real value of the clock has been measured
*/
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
/**
* @brief Power up flags for rtc_sleep_pd function
*/