mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 06:04:33 +02:00
apll: add lock for apll
This commit is contained in:
@@ -29,8 +29,7 @@
|
||||
#include "esp_private/gdma.h"
|
||||
#endif
|
||||
|
||||
#include "soc/rtc.h"
|
||||
|
||||
#include "soc/clk_ctrl_os.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
@@ -931,19 +930,29 @@ static uint32_t i2s_config_source_clock(i2s_port_t i2s_num, bool use_apll, uint3
|
||||
{
|
||||
#if SOC_I2S_SUPPORTS_APLL
|
||||
if (use_apll) {
|
||||
int div_min = (int)(RTC_APLL_FREQ_MIN / (float)mclk + 1);
|
||||
int div_max = (int)(RTC_APLL_FREQ_MAX / (float)mclk);
|
||||
div_min = div_min < 2 ? 2 : div_min; // APLL / mclk >= 2
|
||||
if (div_min > div_max) {
|
||||
ESP_LOGE(TAG, "mclk frequency is too big for APLL colck source");
|
||||
/* Calculate the expected APLL */
|
||||
int div = (int)((SOC_APLL_MIN_HZ / mclk) + 1);
|
||||
/* apll_freq = mclk * div
|
||||
* when div = 1, hardware will still divide 2
|
||||
* when div = 0, the final mclk will be unpredictable
|
||||
* So the div here should be at least 2 */
|
||||
div = div < 2 ? 2 : div;
|
||||
uint32_t expt_freq = mclk * div;
|
||||
/* Set APLL coefficients to the given frequency */
|
||||
uint32_t real_freq = 0;
|
||||
esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq);
|
||||
if (ret == ESP_ERR_INVALID_ARG) {
|
||||
ESP_LOGE(TAG, "set APLL coefficients failed");
|
||||
return 0;
|
||||
}
|
||||
uint32_t expt_freq = div_min * mclk;
|
||||
rtc_clk_apll_freq_set(expt_freq);
|
||||
if (ret == ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGW(TAG, "APLL is occupied already, it is working at %d Hz", real_freq);
|
||||
}
|
||||
ESP_LOGI(TAG, "APLL expected frequency is %d Hz, real frequency is %d Hz", expt_freq, real_freq);
|
||||
/* Set I2S_APLL as I2S module clock source */
|
||||
i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_APLL);
|
||||
/* In APLL mode, there is no sclk but only mclk, so return 0 here to indicate APLL mode */
|
||||
return expt_freq;
|
||||
return real_freq;
|
||||
}
|
||||
/* Set I2S_D2CLK (160M) as default I2S module clock source */
|
||||
i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK);
|
||||
@@ -1883,6 +1892,13 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
pre_alloc_i2s_obj->i2s_queue = NULL;
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_APLL
|
||||
/* Power up APLL clock */
|
||||
if (i2s_config->use_apll) {
|
||||
periph_rtc_apll_acquire();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Step 7: Set I2S clocks and start. No need to give parameters since configurations has been set in 'i2s_driver_init' */
|
||||
ESP_GOTO_ON_ERROR(i2s_set_clk(i2s_num, 0, 0, 0), err, TAG, "I2S set clock failed");
|
||||
return ESP_OK;
|
||||
@@ -1937,7 +1953,7 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
|
||||
if (p_i2s[i2s_num]->use_apll) {
|
||||
// switch back to PLL clock source
|
||||
i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK);
|
||||
rtc_clk_apll_enable(0, 0, 0, 0, 0);
|
||||
periph_rtc_apll_release();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include "hal/emac_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/clk_ctrl_os.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_sys.h"
|
||||
@@ -56,6 +56,7 @@ typedef struct {
|
||||
bool isr_need_yield;
|
||||
bool flow_ctrl_enabled; // indicates whether the user want to do flow control
|
||||
bool do_flow_ctrl; // indicates whether we need to do software flow control
|
||||
bool use_apll; // Only use APLL in EMAC_DATA_INTERFACE_RMII && EMAC_CLK_OUT
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock;
|
||||
#endif
|
||||
@@ -299,30 +300,20 @@ static void emac_esp32_init_smi_gpio(emac_esp32_t *emac)
|
||||
}
|
||||
}
|
||||
|
||||
static void emac_config_apll_clock(void)
|
||||
static esp_err_t emac_config_apll_clock(void)
|
||||
{
|
||||
/* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
|
||||
rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
|
||||
switch (rtc_xtal_freq) {
|
||||
case RTC_XTAL_FREQ_40M: // Recommended
|
||||
/* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
|
||||
/* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
|
||||
rtc_clk_apll_enable(true, 0, 0, 6, 2);
|
||||
break;
|
||||
case RTC_XTAL_FREQ_26M:
|
||||
/* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
|
||||
/* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
|
||||
rtc_clk_apll_enable(true, 39, 118, 15, 3);
|
||||
break;
|
||||
case RTC_XTAL_FREQ_24M:
|
||||
/* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
|
||||
/* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
|
||||
rtc_clk_apll_enable(true, 255, 255, 12, 2);
|
||||
break;
|
||||
default: // Assume we have a 40M xtal
|
||||
rtc_clk_apll_enable(true, 0, 0, 6, 2);
|
||||
break;
|
||||
uint32_t expt_freq = 50000000; // 50MHz
|
||||
uint32_t real_freq = 0;
|
||||
esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq);
|
||||
ESP_RETURN_ON_FALSE(ret != ESP_ERR_INVALID_ARG, ESP_FAIL, TAG, "Set APLL clock coefficients failed");
|
||||
if (ret == ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGW(TAG, "APLL is occupied already, it is working at %d Hz", real_freq);
|
||||
}
|
||||
// If the difference of real APLL frequency is not within 50 ppm, i.e. 2500 Hz, the APLL is unavailable
|
||||
ESP_RETURN_ON_FALSE(abs(real_freq - expt_freq) <= 2500,
|
||||
ESP_ERR_INVALID_STATE, TAG, "The APLL is working at an unusable frequency");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
|
||||
@@ -429,6 +420,9 @@ static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors)
|
||||
if (emac->intr_hdl) {
|
||||
esp_intr_free(emac->intr_hdl);
|
||||
}
|
||||
if (emac->use_apll) {
|
||||
periph_rtc_apll_release();
|
||||
}
|
||||
for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
|
||||
free(emac->tx_buf[i]);
|
||||
}
|
||||
@@ -546,7 +540,10 @@ static esp_err_t esp_emac_config_data_interface(const eth_mac_config_t *config,
|
||||
}
|
||||
/* Enable RMII clock */
|
||||
emac_ll_clock_enable_rmii_output(emac->hal.ext_regs);
|
||||
emac_config_apll_clock();
|
||||
// Power up APLL clock
|
||||
periph_rtc_apll_acquire();
|
||||
ESP_GOTO_ON_ERROR(emac_config_apll_clock(), err, TAG, "Configure APLL for RMII failed");
|
||||
emac->use_apll = true;
|
||||
} else {
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC clock mode");
|
||||
}
|
||||
@@ -589,6 +586,7 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
|
||||
emac->smi_mdio_gpio_num = config->smi_mdio_gpio_num;
|
||||
emac->flow_control_high_water_mark = FLOW_CONTROL_HIGH_WATER_MARK;
|
||||
emac->flow_control_low_water_mark = FLOW_CONTROL_LOW_WATER_MARK;
|
||||
emac->use_apll = false;
|
||||
emac->parent.set_mediator = emac_esp32_set_mediator;
|
||||
emac->parent.init = emac_esp32_init;
|
||||
emac->parent.deinit = emac_esp32_deinit;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include "soc/clk_ctrl_os.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define DELAY_RTC_CLK_SWITCH 5
|
||||
@@ -14,6 +15,13 @@ 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
|
||||
#if SOC_CLK_APLL_SUPPORTED
|
||||
static const char *TAG = "clk_ctrl_os";
|
||||
// Current APLL frequency, in HZ. Zero if APLL is not enabled.
|
||||
static uint32_t s_cur_apll_freq = 0;
|
||||
static int s_apll_ref_cnt = 0;
|
||||
#endif
|
||||
|
||||
|
||||
bool periph_rtc_dig_clk8m_enable(void)
|
||||
{
|
||||
@@ -51,3 +59,65 @@ void periph_rtc_dig_clk8m_disable(void)
|
||||
}
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
#if SOC_CLK_APLL_SUPPORTED
|
||||
void periph_rtc_apll_acquire(void)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
s_apll_ref_cnt++;
|
||||
if (s_apll_ref_cnt == 1) {
|
||||
// For the first time enable APLL, need to set power up
|
||||
rtc_clk_apll_enable(true);
|
||||
}
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
void periph_rtc_apll_release(void)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
assert(s_apll_ref_cnt > 0);
|
||||
s_apll_ref_cnt--;
|
||||
if (s_apll_ref_cnt == 0) {
|
||||
// If there is no peripheral using APLL, shut down the power
|
||||
s_cur_apll_freq = 0;
|
||||
rtc_clk_apll_enable(false);
|
||||
}
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
}
|
||||
|
||||
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq)
|
||||
{
|
||||
uint32_t o_div = 0;
|
||||
uint32_t sdm0 = 0;
|
||||
uint32_t sdm1 = 0;
|
||||
uint32_t sdm2 = 0;
|
||||
// Guarantee 'periph_rtc_apll_acquire' has been called before set apll freq
|
||||
assert(s_apll_ref_cnt > 0);
|
||||
uint32_t apll_freq = rtc_clk_apll_coeff_calc(expt_freq, &o_div, &sdm0, &sdm1, &sdm2);
|
||||
|
||||
ESP_RETURN_ON_FALSE(apll_freq, ESP_ERR_INVALID_ARG, TAG, "APLL coefficients calculate failed");
|
||||
bool need_config = true;
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
/* If APLL is not in use or only one peripheral in use, its frequency can be changed as will
|
||||
* But when more than one peripheral refers APLL, its frequency is not allowed to change once it is set */
|
||||
if (s_cur_apll_freq == 0 || s_apll_ref_cnt < 2) {
|
||||
s_cur_apll_freq = apll_freq;
|
||||
} else {
|
||||
apll_freq = s_cur_apll_freq;
|
||||
need_config = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
*real_freq = apll_freq;
|
||||
|
||||
if (need_config) {
|
||||
ESP_LOGD(TAG, "APLL will working at %d Hz with coefficients [sdm0] %d [sdm1] %d [sdm2] %d [o_div] %d",
|
||||
apll_freq, sdm0, sdm1, sdm2, o_div);
|
||||
/* Set coefficients for APLL, notice that it doesn't mean APLL will start */
|
||||
rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // SOC_I2S_SUPPORTS_APLL
|
||||
|
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -37,6 +38,39 @@ void periph_rtc_dig_clk8m_disable(void);
|
||||
*/
|
||||
uint32_t periph_rtc_dig_clk8m_get_freq(void);
|
||||
|
||||
#if SOC_CLK_APLL_SUPPORTED
|
||||
/**
|
||||
* @brief Enable APLL power if it has not enabled
|
||||
*/
|
||||
void periph_rtc_apll_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Shut down APLL power if no peripherals using APLL
|
||||
*/
|
||||
void periph_rtc_apll_release(void);
|
||||
|
||||
/**
|
||||
* @brief Calculate and set APLL coefficients by given frequency
|
||||
* @note Have to call 'periph_rtc_apll_acquire' to enable APLL power before setting frequency
|
||||
* @note This calculation is based on the inequality:
|
||||
* xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= SOC_APLL_MULTIPLIER_OUT_MIN_HZ(350 MHz)
|
||||
* It will always calculate the minimum coefficients that can satisfy the inequality above, instead of loop them one by one.
|
||||
* which means more appropriate coefficients are likely to exist.
|
||||
* But this algorithm can meet almost all the cases and the accuracy can be guaranteed as well.
|
||||
* @note The APLL frequency is only allowed to set when there is only one peripheral refer to it.
|
||||
* If APLL is already set by another peripheral, this function will return `ESP_ERR_INVALID_STATE`
|
||||
* and output the current frequency by parameter `real_freq`.
|
||||
*
|
||||
* @param expt_freq Expected APLL frequency (unit: Hz)
|
||||
* @param real_freq APLL real working frequency [output] (unit: Hz)
|
||||
* @return
|
||||
* - ESP_OK: APLL frequency set success
|
||||
* - ESP_ERR_INVALID_ARG: The input expt_freq is out of APLL support range
|
||||
* - ESP_ERR_INVALID_STATE: APLL is refered by more than one peripherals, not allowed to change its frequency now
|
||||
*/
|
||||
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq);
|
||||
#endif // SOC_CLK_APLL_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* This file lists register fields of APLL, located on an internal configuration
|
||||
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||
* rtc_clk_apll_enable function in rtc_clk.c.
|
||||
* rtc_clk_apll_freq_set and rtc_clk_apll_enable function in rtc_clk.c.
|
||||
*/
|
||||
|
||||
#define I2C_APLL 0X6D
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/sens_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
@@ -33,10 +34,6 @@
|
||||
#define RTC_SLOW_CLK_FREQ_8MD256 (RTC_FAST_CLK_FREQ_8M / 256)
|
||||
#define RTC_SLOW_CLK_FREQ_32K 32768
|
||||
|
||||
/* APLL numerator frequency range */
|
||||
#define RTC_APLL_NUMERATOR_FREQ_MAX 500000000 // 500MHz
|
||||
#define RTC_APLL_NUMERATOR_FREQ_MIN 350000000 // 350MHz
|
||||
|
||||
/* BBPLL configuration values */
|
||||
#define BBPLL_ENDIV5_VAL_320M 0x43
|
||||
#define BBPLL_BBADC_DSMP_VAL_320M 0x84
|
||||
@@ -272,7 +269,7 @@ bool rtc_clk_8md256_enabled(void)
|
||||
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0;
|
||||
}
|
||||
|
||||
void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2, uint32_t o_div)
|
||||
void rtc_clk_apll_enable(bool enable)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1);
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0);
|
||||
@@ -283,8 +280,69 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
|
||||
}
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2)
|
||||
{
|
||||
uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (rtc_xtal_freq == 0) {
|
||||
// xtal_freq has not set yet
|
||||
SOC_LOGE(TAG, "Get xtal clock frequency failed, it has not been set yet");
|
||||
abort();
|
||||
}
|
||||
/* Reference formula: apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) / ((o_div + 2) * 2)
|
||||
* ---------------------------------------------- -----------------
|
||||
* 350 MHz <= Numerator <= 500 MHz Denominator
|
||||
*/
|
||||
int o_div = 0; // range: 0~31
|
||||
int sdm0 = 0; // range: 0~255
|
||||
int sdm1 = 0; // range: 0~255
|
||||
int sdm2 = 0; // range: 0~63
|
||||
/* Firstly try to satisfy the condition that the operation frequency of numerator should be greater than 350 MHz,
|
||||
* i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value.
|
||||
* With this condition, as we know the 'o_div' can't be greater than 31, then we can calculate the APLL minimum support frequency is
|
||||
* 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */
|
||||
o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2;
|
||||
if (o_div > 31) {
|
||||
SOC_LOGE(TAG, "Expected frequency is too small");
|
||||
return 0;
|
||||
}
|
||||
if (o_div < 0) {
|
||||
/* Try to satisfy the condition that the operation frequency of numerator should be smaller than 500 MHz,
|
||||
* i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code.
|
||||
* With this condition, as we know the 'o_div' can't be smaller than 0, then we can calculate the APLL maximum support frequency is
|
||||
* 500 MHz / ((0 + 2) * 2) = 125000000 Hz */
|
||||
o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2;
|
||||
if (o_div < 0) {
|
||||
SOC_LOGE(TAG, "Expected frequency is too big");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
|
||||
sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4;
|
||||
// numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
|
||||
float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2;
|
||||
// If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
|
||||
if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) {
|
||||
sdm2++;
|
||||
}
|
||||
// If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
|
||||
else if (numrator > (1.0 / 65536.0) / 2.0) {
|
||||
// Get the closest sdm1
|
||||
sdm1 = (int)(numrator * 65536.0 + 0.5) / 256;
|
||||
// Get the closest sdm0
|
||||
sdm0 = (int)(numrator * 65536.0 + 0.5) % 256;
|
||||
}
|
||||
uint32_t real_freq = (uint32_t)(rtc_xtal_freq * 1000000 * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2));
|
||||
*_o_div = o_div;
|
||||
*_sdm0 = sdm0;
|
||||
*_sdm1 = sdm1;
|
||||
*_sdm2 = sdm2;
|
||||
return real_freq;
|
||||
}
|
||||
|
||||
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2)
|
||||
{
|
||||
uint8_t sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV1;
|
||||
uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
|
||||
if (is_rev0) {
|
||||
@@ -309,50 +367,6 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
|
||||
/* use esp_rom_delay_us so the RTC bus doesn't get flooded */
|
||||
esp_rom_delay_us(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apll_freq_set(uint32_t freq)
|
||||
{
|
||||
if (freq < RTC_APLL_FREQ_MIN || freq > RTC_APLL_FREQ_MAX) {
|
||||
return 0;
|
||||
}
|
||||
/* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
|
||||
uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (rtc_xtal_freq == 0) {
|
||||
// xtal_freq has not set yet
|
||||
abort();
|
||||
}
|
||||
uint32_t o_div = 0;
|
||||
uint32_t sdm0 = 0;
|
||||
uint32_t sdm1 = 0;
|
||||
uint32_t sdm2 = 0;
|
||||
/**
|
||||
* This formula is to satisfy the condition xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz
|
||||
* '+ 1' in this formular is to get the ceil value
|
||||
* We can also choose the condition xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz
|
||||
* Then the formula should be o_div = (uint32_t)(RTC_APLL_NUMERATOR_FREQ_MAX / (float)(freq * 2)) - 2; */
|
||||
o_div = (uint32_t)(RTC_APLL_NUMERATOR_FREQ_MIN / (float)(freq * 2) + 1) - 2;
|
||||
// sdm2 = (uint32_t)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
|
||||
sdm2 = (uint32_t)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4;
|
||||
// numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
|
||||
float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2;
|
||||
// If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
|
||||
if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) {
|
||||
sdm2++;
|
||||
}
|
||||
// If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
|
||||
else if (numrator > (1.0 / 65536.0) / 2.0) {
|
||||
// Get the closest sdm1
|
||||
sdm1 = (uint32_t)(numrator * 65536.0 + 0.5) / 256;
|
||||
// Get the closest sdm0
|
||||
sdm0 = (uint32_t)(numrator * 65536.0 + 0.5) % 256;
|
||||
}
|
||||
rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, o_div);
|
||||
float real_freq = (float)rtc_xtal_freq * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2);
|
||||
SOC_LOGD(TAG, "APLL is working at %d Hz with coefficient [sdm0] %d [sdm1] %d [sdm2] %d [o_div] %d",
|
||||
(uint32_t)(real_freq * 1000000), sdm0, sdm1, sdm2, o_div);
|
||||
return (uint32_t)(real_freq * 1000000);
|
||||
}
|
||||
|
||||
void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* This file lists register fields of APLL, located on an internal configuration
|
||||
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||
* rtc_clk_apll_enable function in rtc_clk.c.
|
||||
* rtc_clk_apll_freq_set and rtc_clk_apll_enable function in rtc_clk.c.
|
||||
*/
|
||||
|
||||
#define I2C_APLL 0X6D
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
@@ -31,10 +32,6 @@ static const char *TAG = "rtc_clk";
|
||||
#define RTC_PLL_FREQ_480M 480
|
||||
#define DELAY_RTC_CLK_SWITCH 5
|
||||
|
||||
/* APLL numerator frequency range */
|
||||
#define RTC_APLL_NUMERATOR_FREQ_MAX 500000000 // 500MHz
|
||||
#define RTC_APLL_NUMERATOR_FREQ_MIN 350000000 // 350MHz
|
||||
|
||||
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
|
||||
// On the ESP32-S2, 480MHz PLL is enabled at reset.
|
||||
static uint32_t s_cur_pll_freq = RTC_PLL_FREQ_480M;
|
||||
@@ -123,12 +120,73 @@ bool rtc_clk_8md256_enabled(void)
|
||||
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0;
|
||||
}
|
||||
|
||||
void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2, uint32_t o_div)
|
||||
void rtc_clk_apll_enable(bool enable)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1);
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2)
|
||||
{
|
||||
uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (rtc_xtal_freq == 0) {
|
||||
// xtal_freq has not set yet
|
||||
SOC_LOGE(TAG, "Get xtal clock frequency failed, it has not been set yet");
|
||||
abort();
|
||||
}
|
||||
/* Reference formula: apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) / ((o_div + 2) * 2)
|
||||
* ---------------------------------------------- -----------------
|
||||
* 350 MHz <= Numerator <= 500 MHz Denominator
|
||||
*/
|
||||
int o_div = 0; // range: 0~31
|
||||
int sdm0 = 0; // range: 0~255
|
||||
int sdm1 = 0; // range: 0~255
|
||||
int sdm2 = 0; // range: 0~63
|
||||
/* Firstly try to satisfy the condition that the operation frequency of numerator should be greater than 350 MHz,
|
||||
* i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value.
|
||||
* With this condition, as we know the 'o_div' can't be greater than 31, then we can calculate the APLL minimum support frequency is
|
||||
* 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */
|
||||
o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2;
|
||||
if (o_div > 31) {
|
||||
SOC_LOGE(TAG, "Expected frequency is too small");
|
||||
return 0;
|
||||
}
|
||||
if (o_div < 0) {
|
||||
/* Try to satisfy the condition that the operation frequency of numerator should be smaller than 500 MHz,
|
||||
* i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code.
|
||||
* With this condition, as we know the 'o_div' can't be smaller than 0, then we can calculate the APLL maximum support frequency is
|
||||
* 500 MHz / ((0 + 2) * 2) = 125000000 Hz */
|
||||
o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2;
|
||||
if (o_div < 0) {
|
||||
SOC_LOGE(TAG, "Expected frequency is too big");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
|
||||
sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4;
|
||||
// numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
|
||||
float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2;
|
||||
// If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
|
||||
if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) {
|
||||
sdm2++;
|
||||
}
|
||||
// If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
|
||||
else if (numrator > (1.0 / 65536.0) / 2.0) {
|
||||
// Get the closest sdm1
|
||||
sdm1 = (int)(numrator * 65536.0 + 0.5) / 256;
|
||||
// Get the closest sdm0
|
||||
sdm0 = (int)(numrator * 65536.0 + 0.5) % 256;
|
||||
}
|
||||
uint32_t real_freq = (uint32_t)(rtc_xtal_freq * 1000000 * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2));
|
||||
*_o_div = o_div;
|
||||
*_sdm0 = sdm0;
|
||||
*_sdm1 = sdm1;
|
||||
*_sdm2 = sdm2;
|
||||
return real_freq;
|
||||
}
|
||||
|
||||
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2)
|
||||
{
|
||||
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM2, sdm2);
|
||||
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM0, sdm0);
|
||||
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_DSDM1, sdm1);
|
||||
@@ -146,50 +204,6 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
|
||||
/* use esp_rom_delay_us so the RTC bus doesn't get flooded */
|
||||
esp_rom_delay_us(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apll_freq_set(uint32_t freq)
|
||||
{
|
||||
if (freq < RTC_APLL_FREQ_MIN || freq > RTC_APLL_FREQ_MAX) {
|
||||
return 0;
|
||||
}
|
||||
/* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
|
||||
uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (rtc_xtal_freq == 0) {
|
||||
// xtal_freq has not set yet
|
||||
abort();
|
||||
}
|
||||
uint32_t o_div = 0;
|
||||
uint32_t sdm0 = 0;
|
||||
uint32_t sdm1 = 0;
|
||||
uint32_t sdm2 = 0;
|
||||
/**
|
||||
* This formula is to satisfy the condition xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz
|
||||
* '+ 1' in this formular is to get the ceil value
|
||||
* We can also choose the condition xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz
|
||||
* Then the formula should be o_div = (uint32_t)(RTC_APLL_NUMERATOR_FREQ_MAX / (float)(freq * 2)) - 2; */
|
||||
o_div = (uint32_t)(RTC_APLL_NUMERATOR_FREQ_MIN / (float)(freq * 2) + 1) - 2;
|
||||
// sdm2 = (uint32_t)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
|
||||
sdm2 = (uint32_t)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * 1000000)) - 4;
|
||||
// numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
|
||||
float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * 1000000)) - 4 - sdm2;
|
||||
// If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
|
||||
if (numrator > 1.0 - (1.0 / 65536.0) / 2.0) {
|
||||
sdm2++;
|
||||
}
|
||||
// If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
|
||||
else if (numrator > (1.0 / 65536.0) / 2.0) {
|
||||
// Get the closest sdm1
|
||||
sdm1 = (uint32_t)(numrator * 65536.0 + 0.5) / 256;
|
||||
// Get the closest sdm0
|
||||
sdm0 = (uint32_t)(numrator * 65536.0 + 0.5) % 256;
|
||||
}
|
||||
rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, o_div);
|
||||
float real_freq = (float)rtc_xtal_freq * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / (((float)o_div + 2) * 2);
|
||||
SOC_LOGD(TAG, "APLL is working at %d Hz with coefficient [sdm0] %d [sdm1] %d [sdm2] %d [o_div] %d",
|
||||
(uint32_t)(real_freq * 1000000), sdm0, sdm1, sdm2, o_div);
|
||||
return (uint32_t)(real_freq * 1000000);
|
||||
}
|
||||
|
||||
void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
|
||||
|
@@ -27,10 +27,16 @@ static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mc
|
||||
cal->a = 1;
|
||||
cal->b = 0;
|
||||
|
||||
uint32_t freq_diff = clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div;
|
||||
uint32_t freq_diff = abs(clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div);
|
||||
if (!freq_diff) {
|
||||
return;
|
||||
}
|
||||
float decimal = freq_diff / (float)clk_cfg->mclk;
|
||||
// Carry bit if the decimal is greater than 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0
|
||||
if (decimal > 125.0 / 126.0) {
|
||||
cal->mclk_div++;
|
||||
return;
|
||||
}
|
||||
uint32_t min = ~0;
|
||||
for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) {
|
||||
// Calculate the closest 'b' in this loop, no need to loop 'b' to seek the closest value
|
||||
|
@@ -1,16 +1,8 @@
|
||||
// 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@@ -191,10 +191,34 @@ config SOC_I2C_SUPPORT_APB
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_APLL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_APLL_MULTIPLIER_OUT_MIN_HZ
|
||||
int
|
||||
default 350000000
|
||||
|
||||
config SOC_APLL_MULTIPLIER_OUT_MAX_HZ
|
||||
int
|
||||
default 500000000
|
||||
|
||||
config SOC_APLL_MIN_HZ
|
||||
int
|
||||
default 5303031
|
||||
|
||||
config SOC_APLL_MAX_HZ
|
||||
int
|
||||
default 125000000
|
||||
|
||||
config SOC_I2S_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_I2S_SUPPORTS_APLL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORTS_PDM_TX
|
||||
bool
|
||||
default y
|
||||
@@ -211,22 +235,6 @@ config SOC_I2S_SUPPORTS_DAC
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_SUPPORTS_APLL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_APLL_MIN_FREQ
|
||||
int
|
||||
default 250000000
|
||||
|
||||
config SOC_I2S_APLL_MAX_FREQ
|
||||
int
|
||||
default 500000000
|
||||
|
||||
config SOC_I2S_APLL_MIN_RATE
|
||||
int
|
||||
default 10675
|
||||
|
||||
config SOC_I2S_TRANS_SIZE_ALIGN_WORD
|
||||
bool
|
||||
default y
|
||||
|
@@ -46,10 +46,6 @@ extern "C" {
|
||||
* - rtc_init: initialization
|
||||
*/
|
||||
|
||||
/* APLL frequency range */
|
||||
#define RTC_APLL_FREQ_MAX 128000000 // 128MHz
|
||||
#define RTC_APLL_FREQ_MIN 16000000 // 16MHz
|
||||
|
||||
/**
|
||||
* @brief Possible main XTAL frequency values.
|
||||
*
|
||||
@@ -255,22 +251,33 @@ bool rtc_clk_8md256_enabled(void);
|
||||
* In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void rtc_clk_apll_enable(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Calculate APLL clock coeffifcients
|
||||
*
|
||||
* @param freq expected APLL frequency
|
||||
* @param o_div frequency divider, 0..31
|
||||
* @param sdm0 frequency adjustment parameter, 0..255
|
||||
* @param sdm1 frequency adjustment parameter, 0..255
|
||||
* @param sdm2 frequency adjustment parameter, 0..63
|
||||
* @param o_div frequency divider, 0..31
|
||||
*
|
||||
* @return
|
||||
* - 0 Failed
|
||||
* - else Sucess
|
||||
*/
|
||||
void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1,
|
||||
uint32_t sdm2, uint32_t o_div);
|
||||
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2);
|
||||
|
||||
/**
|
||||
* @brief Set APLL clock freqency
|
||||
* @param freq Expected APLL freqency (unit: Hz)
|
||||
* @return
|
||||
* - 0: Failed, the expected APLL frequency is out of range
|
||||
* - else: The true APLL clock (unit: Hz)
|
||||
* @brief Set APLL clock coeffifcients
|
||||
*
|
||||
* @param o_div frequency divider, 0..31
|
||||
* @param sdm0 frequency adjustment parameter, 0..255
|
||||
* @param sdm1 frequency adjustment parameter, 0..255
|
||||
* @param sdm2 frequency adjustment parameter, 0..63
|
||||
*/
|
||||
uint32_t rtc_clk_apll_freq_set(uint32_t freq);
|
||||
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2);
|
||||
|
||||
/**
|
||||
* @brief Select source for RTC_SLOW_CLK
|
||||
|
@@ -157,18 +157,23 @@
|
||||
|
||||
#define SOC_I2C_SUPPORT_APB (1)
|
||||
|
||||
/*-------------------------- APLL CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_APLL_SUPPORTED (1)
|
||||
// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)
|
||||
#define SOC_APLL_MULTIPLIER_OUT_MIN_HZ (350000000) // 350 MHz
|
||||
#define SOC_APLL_MULTIPLIER_OUT_MAX_HZ (500000000) // 500 MHz
|
||||
#define SOC_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation
|
||||
#define SOC_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
// ESP32 have 2 I2S
|
||||
#define SOC_I2S_NUM (2)
|
||||
#define SOC_I2S_NUM (2U)
|
||||
#define SOC_I2S_SUPPORTS_APLL (1) // ESP32 support APLL
|
||||
#define SOC_I2S_SUPPORTS_PDM_TX (1)
|
||||
#define SOC_I2S_SUPPORTS_PDM_RX (1)
|
||||
#define SOC_I2S_SUPPORTS_ADC (1) // ESP32 support ADC and DAC
|
||||
#define SOC_I2S_SUPPORTS_DAC (1)
|
||||
|
||||
#define SOC_I2S_SUPPORTS_APLL (1)// ESP32 support APLL
|
||||
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||
#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware
|
||||
#define SOC_I2S_TRANS_SIZE_ALIGN_WORD (1) // I2S DMA transfer size must be aligned to word
|
||||
#define SOC_I2S_LCD_I80_VARIANT (1) // I2S has a special LCD mode that can generate Intel 8080 TX timing
|
||||
|
||||
|
@@ -279,6 +279,26 @@ config SOC_I2C_SUPPORT_APB
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_APLL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_APLL_MULTIPLIER_OUT_MIN_HZ
|
||||
int
|
||||
default 350000000
|
||||
|
||||
config SOC_APLL_MULTIPLIER_OUT_MAX_HZ
|
||||
int
|
||||
default 500000000
|
||||
|
||||
config SOC_APLL_MIN_HZ
|
||||
int
|
||||
default 5303031
|
||||
|
||||
config SOC_APLL_MAX_HZ
|
||||
int
|
||||
default 125000000
|
||||
|
||||
config SOC_I2S_NUM
|
||||
int
|
||||
default 1
|
||||
@@ -291,18 +311,6 @@ config SOC_I2S_SUPPORTS_DMA_EQUAL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_I2S_APLL_MIN_FREQ
|
||||
int
|
||||
default 250000000
|
||||
|
||||
config SOC_I2S_APLL_MAX_FREQ
|
||||
int
|
||||
default 500000000
|
||||
|
||||
config SOC_I2S_APLL_MIN_RATE
|
||||
int
|
||||
default 10675
|
||||
|
||||
config SOC_I2S_LCD_I80_VARIANT
|
||||
bool
|
||||
default y
|
||||
|
@@ -73,10 +73,6 @@ extern "C" {
|
||||
#define DELAY_SLOW_CLK_SWITCH 300
|
||||
#define DELAY_8M_ENABLE 50
|
||||
|
||||
/* APLL frequency range */
|
||||
#define RTC_APLL_FREQ_MAX 128000000 // 128MHz
|
||||
#define RTC_APLL_FREQ_MIN 16000000 // 16MHz
|
||||
|
||||
/* Number of 8M/256 clock cycles to use for XTAL frequency estimation.
|
||||
* 10 cycles will take approximately 300 microseconds.
|
||||
*/
|
||||
@@ -402,21 +398,33 @@ bool rtc_clk_8md256_enabled(void);
|
||||
* In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void rtc_clk_apll_enable(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Calculate APLL clock coeffifcients
|
||||
*
|
||||
* @param freq expected APLL frequency
|
||||
* @param o_div frequency divider, 0..31
|
||||
* @param sdm0 frequency adjustment parameter, 0..255
|
||||
* @param sdm1 frequency adjustment parameter, 0..255
|
||||
* @param sdm2 frequency adjustment parameter, 0..63
|
||||
* @param o_div frequency divider, 0..31
|
||||
*
|
||||
* @return
|
||||
* - 0 Failed
|
||||
* - else Sucess
|
||||
*/
|
||||
void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2, uint32_t o_div);
|
||||
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2);
|
||||
|
||||
/**
|
||||
* @brief Set APLL clock freqency
|
||||
* @param freq Expected APLL freqency (unit: Hz)
|
||||
* @return
|
||||
* - 0: Failed, the expected APLL frequency is out of range
|
||||
* - else: The true APLL clock (unit: Hz)
|
||||
* @brief Set APLL clock coeffifcients
|
||||
*
|
||||
* @param o_div frequency divider, 0..31
|
||||
* @param sdm0 frequency adjustment parameter, 0..255
|
||||
* @param sdm1 frequency adjustment parameter, 0..255
|
||||
* @param sdm2 frequency adjustment parameter, 0..63
|
||||
*/
|
||||
uint32_t rtc_clk_apll_freq_set(uint32_t freq);
|
||||
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2);
|
||||
|
||||
/**
|
||||
* @brief Select source for RTC_SLOW_CLK
|
||||
|
@@ -153,14 +153,19 @@
|
||||
#define SOC_I2C_SUPPORT_REF_TICK (1)
|
||||
#define SOC_I2C_SUPPORT_APB (1)
|
||||
|
||||
/*-------------------------- APLL CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_APLL_SUPPORTED (1)
|
||||
// apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)
|
||||
#define SOC_APLL_MULTIPLIER_OUT_MIN_HZ (350000000) // 350 MHz
|
||||
#define SOC_APLL_MULTIPLIER_OUT_MAX_HZ (500000000) // 500 MHz
|
||||
#define SOC_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation
|
||||
#define SOC_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation
|
||||
|
||||
/*-------------------------- I2S CAPS ----------------------------------------*/
|
||||
// ESP32-S2 have 1 I2S
|
||||
#define SOC_I2S_NUM (1U)
|
||||
#define SOC_I2S_SUPPORTS_APLL (1)// ESP32-S2 support APLL
|
||||
#define SOC_I2S_SUPPORTS_APLL (1) // ESP32-S2 support APLL
|
||||
#define SOC_I2S_SUPPORTS_DMA_EQUAL (1)
|
||||
#define SOC_I2S_APLL_MIN_FREQ (250000000)
|
||||
#define SOC_I2S_APLL_MAX_FREQ (500000000)
|
||||
#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware
|
||||
#define SOC_I2S_LCD_I80_VARIANT (1)
|
||||
|
||||
/*-------------------------- LCD CAPS ----------------------------------------*/
|
||||
|
@@ -1135,7 +1135,6 @@ components/hal/include/hal/esp_flash_err.h
|
||||
components/hal/include/hal/gpio_hal.h
|
||||
components/hal/include/hal/i2c_hal.h
|
||||
components/hal/include/hal/i2c_types.h
|
||||
components/hal/include/hal/i2s_types.h
|
||||
components/hal/include/hal/interrupt_controller_hal.h
|
||||
components/hal/include/hal/interrupt_controller_types.h
|
||||
components/hal/include/hal/ledc_hal.h
|
||||
|
Reference in New Issue
Block a user