Merge branch 'feature/experimental_feature_mspi_120_ddr' into 'master'

mspi: experimental feature mspi 120 mhz ddr

Closes IDF-7073

See merge request espressif/esp-idf!22952
This commit is contained in:
Armando (Dou Yiwen) 2023-04-03 18:03:58 +08:00
commit ebaf987dc8
15 changed files with 297 additions and 69 deletions

View File

@ -522,3 +522,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
menu "Component config"
source "$COMPONENT_KCONFIGS_SOURCE_FILE"
endmenu
config IDF_EXPERIMENTAL_FEATURES
bool "Make experimental features visible"
default "n"
help
By enabling this option, ESP-IDF experimental feature options will be visible.
Note you should still enable a certain experimental feature option to use it, and you
should read the corresponding risk warning and known issue list carefully.

View File

@ -139,43 +139,45 @@ void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t le
/*-------------------------------------------------------------------------------------------------
* SPI1 Timing Tuning APIs
* These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for
* configuring SPI1 timing tuning related registers to find best tuning parameter
*
* These APIs are only used in `mspi_timing_tuning.c` for configuring SPI1 timing
* tuning related registers to find best tuning parameter for Flash and PSRAM
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Tune Flash Din Mode and Num of SPI1
* @param din_mode Din mode
* @param din_num Din num
* @brief Tune Flash timing registers for SPI1 accessing Flash
*
* @param[in] params Timing parameters
*/
void mspi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num);
void mspi_timing_config_flash_set_tuning_regs(const mspi_timing_tuning_param_t *params);
/**
* @brief Tune Flash extra dummy of SPI1
* @param extra_dummy extra dummy bits
* @brief Tune PSRAM timing registers for SPI1 accessing PSRAM
*
* @param[in] params Timing parameters
*/
void mspi_timing_config_psram_set_tuning_regs(const mspi_timing_tuning_param_t *params);
/*-------------------------------------------------------------------------------------------------
* APIs for coordination with ESP Flash driver
*-------------------------------------------------------------------------------------------------*/
/**
* SPI1 register info get APIs. These APIs inform `mspi_timing_tuning.c` (driver layer) of the SPI1 flash settings.
* In this way, other components (e.g.: esp_flash driver) can get the info from it (`mspi_timing_tuning.c`).
*/
void mspi_timing_config_flash_tune_dummy(uint8_t extra_dummy);
/**
* @brief Tune PSRAM Din Mode and Num of SPI1
* @param din_mode Din mode
* @param din_num Din num
*/
void mspi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num);
/**
* @brief Tune PSRAM extra dummy of SPI1
* @param extra_dummy extra dummy bits
*/
void mspi_timing_config_psram_tune_dummy(uint8_t extra_dummy);
/**
* SPI1 register info get APIs. These APIs inform `spi_flash_timing_tuning.c` (driver layer) of the SPI1 flash settings.
* In this way, other components (e.g.: esp_flash driver) can get the info from it (`spi_flash_timing_tuning.c`).
* @brief Get CS timing
*
* @param[out] setup_time Setup time
* @param[out] hold_time Hold time
*/
void mspi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time);
/**
* @brief Get Flash clock reg val
*
* @return Flash clock reg val
*/
uint32_t mspi_timing_config_get_flash_clock_reg(void);

View File

@ -15,8 +15,11 @@
#include "soc/io_mux_reg.h"
#include "esp_private/mspi_timing_tuning.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "hal/spi_flash_hal.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "hal/clk_tree_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "mspi_timing_config.h"
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/cache.h"
@ -107,7 +110,7 @@ static void init_spi1_for_tuning(bool is_flash)
* We use different SPI1 timing tuning config to read data to see if current MSPI sampling is successful.
* The sampling result will be stored in an array. In this array, successful item will be 1, failed item will be 0.
*/
static void sweep_for_success_sample_points(uint8_t *reference_data, const mspi_timing_config_t *config, bool is_flash, uint8_t *out_array)
static void sweep_for_success_sample_points(const uint8_t *reference_data, const mspi_timing_config_t *config, bool is_flash, uint8_t *out_array)
{
uint32_t config_idx = 0;
uint8_t read_data[MSPI_TIMING_TEST_DATA_LEN] = {0};
@ -116,20 +119,21 @@ static void sweep_for_success_sample_points(uint8_t *reference_data, const mspi_
memset(read_data, 0, MSPI_TIMING_TEST_DATA_LEN);
#if MSPI_TIMING_FLASH_NEEDS_TUNING
if (is_flash) {
mspi_timing_config_flash_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num);
mspi_timing_config_flash_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len);
mspi_timing_config_flash_set_tuning_regs(&(config->tuning_config_table[config_idx]));
mspi_timing_config_flash_read_data(read_data, MSPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(read_data));
}
#endif
#if MSPI_TIMING_PSRAM_NEEDS_TUNING
if (!is_flash) {
mspi_timing_config_psram_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num);
mspi_timing_config_psram_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len);
mspi_timing_config_psram_set_tuning_regs(&(config->tuning_config_table[config_idx]));
mspi_timing_config_psram_read_data(read_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
}
#endif
if (memcmp(reference_data, read_data, sizeof(read_data)) == 0) {
out_array[config_idx] = 1;
ESP_EARLY_LOGD(TAG, "%d, good", config_idx);
} else {
ESP_EARLY_LOGD(TAG, "%d, bad", config_idx);
}
}
}
@ -164,14 +168,77 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u
*out_end_index = match_num == size ? size : end;
}
#if (MSPI_TIMING_FLASH_DTR_MODE || MSPI_TIMING_PSRAM_DTR_MODE) && (MSPI_TIMING_CORE_CLOCK_MHZ == 240)
static bool get_working_pll_freq(const uint8_t *reference_data, bool is_flash, uint32_t *out_max_freq, uint32_t *out_min_freq)
{
uint8_t read_data[MSPI_TIMING_TEST_DATA_LEN] = {0};
rtc_cpu_freq_config_t previous_config;
rtc_clk_cpu_freq_get_config(&previous_config);
uint32_t big_num = MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX * 2; //This number should be larger than MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX, for error handling
uint32_t max_freq = 0;
uint32_t min_freq = big_num;
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
//BBPLL CALIBRATION START
regi2c_ctrl_ll_bbpll_calibration_start();
for (int pll_mhz_tuning = MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MIN; pll_mhz_tuning <= MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX; pll_mhz_tuning += 8) {
/**
* pll_mhz = xtal_mhz * (oc_div + 4) / (oc_ref_div + 1)
*/
clk_ll_bbpll_set_frequency_for_mspi_tuning(xtal_freq, pll_mhz_tuning, ((pll_mhz_tuning / 4) - 4), 9);
memset(read_data, 0, MSPI_TIMING_TEST_DATA_LEN);
if (is_flash) {
mspi_timing_config_flash_read_data(read_data, MSPI_TIMING_FLASH_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
} else {
mspi_timing_config_psram_read_data(read_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
}
if (memcmp(read_data, reference_data, MSPI_TIMING_TEST_DATA_LEN) == 0) {
max_freq = MAX(pll_mhz_tuning, max_freq);
min_freq = MIN(pll_mhz_tuning, min_freq);
//Continue to find successful cases
continue;
}
if (max_freq != 0) {
//The first fail case after successful case(s) is the end
break;
}
//If no break, no successful case found, continue to find successful cases
}
//restore PLL config
clk_ll_bbpll_set_freq_mhz(previous_config.source_freq_mhz);
clk_ll_bbpll_set_config(previous_config.source_freq_mhz, xtal_freq);
//WAIT CALIBRATION DONE
while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
//BBPLL CALIBRATION STOP
regi2c_ctrl_ll_bbpll_calibration_stop();
*out_max_freq = max_freq;
*out_min_freq = min_freq;
return (max_freq != 0);
}
#endif //Frequency Scanning
#if MSPI_TIMING_FLASH_DTR_MODE || MSPI_TIMING_PSRAM_DTR_MODE
static uint32_t select_best_tuning_config_dtr(mspi_timing_config_t *config, uint32_t consecutive_length, uint32_t end)
static uint32_t select_best_tuning_config_dtr(mspi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_flash)
{
#if (MSPI_TIMING_CORE_CLOCK_MHZ == 160)
//Core clock 160M DTR best point scheme
uint32_t best_point;
(void) reference_data;
(void) is_flash;
uint32_t best_point = 0;
//Define these magic number in macros in `spi_timing_config.h`. TODO: IDF-3663
//These numbers will probably be same on other chips, if this version of algorithm is utilised
if (consecutive_length <= 2 || consecutive_length >= 6) {
//tuning is FAIL, select default point, and generate a warning
best_point = config->default_config_id;
@ -187,6 +254,41 @@ static uint32_t select_best_tuning_config_dtr(mspi_timing_config_t *config, uint
}
return best_point;
#elif (MSPI_TIMING_CORE_CLOCK_MHZ == 240)
uint32_t best_point = 0;
uint32_t current_point = end + 1 - consecutive_length;
bool ret = false;
//This `max_freq` is the max pll frequency that per MSPI timing tuning config can work
uint32_t max_freq = 0;
uint32_t temp_max_freq = 0;
uint32_t temp_min_freq = 0;
for (; current_point <= end; current_point++) {
if (is_flash) {
mspi_timing_config_flash_set_tuning_regs(&(config->tuning_config_table[current_point]));
} else {
mspi_timing_config_psram_set_tuning_regs(&(config->tuning_config_table[current_point]));
}
ret = get_working_pll_freq(reference_data, is_flash, &temp_max_freq, &temp_min_freq);
if (ret && temp_min_freq <= MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_LOW && temp_max_freq >= MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_HIGH && temp_max_freq > max_freq) {
max_freq = temp_max_freq;
best_point = current_point;
}
ESP_EARLY_LOGD(TAG, "sample point %d, max pll is %d mhz, min pll is %d\n", current_point, temp_max_freq, temp_min_freq);
}
if (max_freq == 0) {
ESP_EARLY_LOGW(TAG, "freq scan tuning fail, best point is fallen back to index %d", end + 1 - consecutive_length);
best_point = end + 1 - consecutive_length;
} else {
ESP_EARLY_LOGD(TAG, "freq scan success, max pll is %dmhz, best point is index %d", max_freq, best_point);
}
return best_point;
#else
//won't reach here
abort();
@ -221,19 +323,19 @@ static uint32_t select_best_tuning_config_str(mspi_timing_config_t *config, uint
}
#endif
static void select_best_tuning_config(mspi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, bool is_flash)
static void select_best_tuning_config(mspi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_flash)
{
uint32_t best_point = 0;
if (is_flash) {
#if MSPI_TIMING_FLASH_DTR_MODE
best_point = select_best_tuning_config_dtr(config, consecutive_length, end);
best_point = select_best_tuning_config_dtr(config, consecutive_length, end, reference_data, is_flash);
#elif MSPI_TIMING_FLASH_STR_MODE
best_point = select_best_tuning_config_str(config, consecutive_length, end);
#endif
s_flash_best_timing_tuning_config = config->tuning_config_table[best_point];
} else {
#if MSPI_TIMING_PSRAM_DTR_MODE
best_point = select_best_tuning_config_dtr(config, consecutive_length, end);
best_point = select_best_tuning_config_dtr(config, consecutive_length, end, reference_data, is_flash);
#elif MSPI_TIMING_PSRAM_STR_MODE
best_point = select_best_tuning_config_str(config, consecutive_length, end);
#endif
@ -241,7 +343,7 @@ static void select_best_tuning_config(mspi_timing_config_t *config, uint32_t con
}
}
static void do_tuning(uint8_t *reference_data, mspi_timing_config_t *timing_config, bool is_flash)
static void do_tuning(const uint8_t *reference_data, mspi_timing_config_t *timing_config, bool is_flash)
{
/**
* We use SPI1 to tune the timing:
@ -256,7 +358,7 @@ static void do_tuning(uint8_t *reference_data, mspi_timing_config_t *timing_conf
init_spi1_for_tuning(is_flash);
sweep_for_success_sample_points(reference_data, timing_config, is_flash, sample_result);
find_max_consecutive_success_points(sample_result, MSPI_TIMING_CONFIG_NUM_DEFAULT, &consecutive_length, &last_success_point);
select_best_tuning_config(timing_config, consecutive_length, last_success_point, is_flash);
select_best_tuning_config(timing_config, consecutive_length, last_success_point, reference_data, is_flash);
}
#endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING

View File

@ -290,40 +290,33 @@ void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t le
* These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for
* configuring SPI1 timing tuning related registers to find best tuning parameter
*-------------------------------------------------------------------------------------------------*/
void mspi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num)
void mspi_timing_config_flash_set_tuning_regs(const mspi_timing_tuning_param_t *params)
{
/**
* 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless
* SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning
* 2. We use SPI1 to get the best Flash timing tuning (mode and num) config
*/
mspi_timing_config_flash_set_din_mode_num(0, din_mode, din_num);
mspi_timing_config_flash_set_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
mspi_timing_config_flash_set_extra_dummy(1, params->extra_dummy_len);
}
void mspi_timing_config_flash_tune_dummy(uint8_t extra_dummy)
{
mspi_timing_config_flash_set_extra_dummy(1, extra_dummy);
}
void mspi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num)
void mspi_timing_config_psram_set_tuning_regs(const mspi_timing_tuning_param_t *params)
{
/**
* 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless
* SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning
* 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config
*/
mspi_timing_config_psram_set_din_mode_num(0, din_mode, din_num);
}
mspi_timing_config_psram_set_din_mode_num(0, params->spi_din_mode, params->spi_din_num);
void mspi_timing_config_psram_tune_dummy(uint8_t extra_dummy)
{
#if CONFIG_SPIRAM_MODE_OCT
//On 728, for SPI1, flash and psram share the extra dummy register
mspi_timing_config_flash_set_extra_dummy(1, extra_dummy);
mspi_timing_config_flash_set_extra_dummy(1, params->extra_dummy_len);
#elif CONFIG_SPIRAM_MODE_QUAD
//Update this `s_psram_extra_dummy`, the `s_psram_read_data` will set dummy according to this `s_psram_extra_dummy`
s_psram_extra_dummy = extra_dummy;
mspi_timing_ll_set_quad_flash_dummy(1, extra_dummy - 1);
s_psram_extra_dummy = params->extra_dummy_len;
mspi_timing_ll_set_quad_flash_dummy(1, s_psram_extra_dummy - 1);
#endif
}

View File

@ -128,6 +128,11 @@
#endif
#endif //PSRAM 120M STR
//PSRAM 120M STR
#if MSPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_120M
#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240
#endif //PSRAM 120M DTR
//------------------------------------------Determine the Core Clock-----------------------------------------------//
/**
@ -233,3 +238,20 @@ ESP_STATIC_ASSERT(CHECK_POWER_OF_2(MSPI_TIMING_CORE_CLOCK_MHZ / MSPI_TIMING_PSRA
#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {1, 0, 1}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {1, 0, 2}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {1, 0, 3}}
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12
#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2
//PSRAM: core clock 240M, module clock 120M, DTR mode
#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE {{0, 0, 0}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 1, 4}, {1, 0, 3}, {4, 0, 4}, {0, 0, 3}, {4, 1, 5}}
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 14
#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 1
//------------------------------------------Frequency Scanning Related-----------------------------------------------//
/**
* On ESP32S3, only module clock 120M, DDR mode needs frequency scan. Frequency scanning is to get the max workable PLL
* frequency under each successfull timing tuning configuration. PLL frequency may fluctuate under high temperature,
* this method is to get the tuning configuration that can work under higher PLL frequency.
*/
#define MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MIN 440
#define MSPI_TIMING_PLL_FREQ_SCAN_RANGE_MHZ_MAX 600
#define MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_LOW 448
#define MSPI_TIMING_PLL_FREQ_SCAN_THRESH_MHZ_HIGH 520
#define MSPI_TIMING_PLL_FREQ_SCAN_STEP_MHZ_MODULE_CLK_120M 8

View File

@ -0,0 +1,6 @@
# F8R8, Flash 120M DDR, PSRAM disable
CONFIG_ESPTOOLPY_OCT_FLASH=y
CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

View File

@ -0,0 +1,10 @@
# F8R8, Flash 120M DDR, PSRAM 120M DDR
CONFIG_ESPTOOLPY_OCT_FLASH=y
CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_120M=y

View File

@ -1,5 +1,6 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_EN=n
CONFIG_SPIRAM_RODATA=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@ -82,8 +82,20 @@ menu "SPI RAM config"
Select the speed for the SPI RAM chip.
config SPIRAM_SPEED_120M
depends on SPIRAM_MODE_QUAD
depends on SPIRAM_MODE_QUAD || IDF_EXPERIMENTAL_FEATURES
bool "120MHz clock speed"
help
- Quad PSRAM 120 MHz is stable.
- Octal PSRAM 120 MHz is an experimental feature, it works when
the temperature is stable.
Risks:
If your chip powers on at a certain temperature, then after the temperature
increases or decreases by approximately 20 Celsius degrees (depending on the
chip), the accesses to / from PSRAM will crash randomly.
config SPIRAM_SPEED_80M
bool "80MHz clock speed"
config SPIRAM_SPEED_40M
@ -97,5 +109,4 @@ menu "SPI RAM config"
default 40 if SPIRAM_SPEED_40M
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
endmenu

View File

@ -95,7 +95,18 @@ menu "Serial flasher config"
config ESPTOOLPY_FLASHFREQ_120M
bool "120 MHz"
select SPI_FLASH_HPM_ENABLE
depends on SOC_MEMSPI_SRC_FREQ_120M && ESPTOOLPY_FLASH_SAMPLE_MODE_STR
depends on SOC_MEMSPI_SRC_FREQ_120M && \
(ESPTOOLPY_FLASH_SAMPLE_MODE_STR || IDF_EXPERIMENTAL_FEATURES)
help
- Flash 120 MHz SDR mode is stable.
- Flash 120 MHz DDR mode is an experimental feature, it works when
the temperature is stable.
Risks:
If your chip powers on at a certain temperature, then after the temperature
increases or decreases by approximately 20 Celsius degrees (depending on the
chip), the program will crash randomly.
config ESPTOOLPY_FLASHFREQ_80M
bool "80 MHz"
depends on SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED

View File

@ -12,6 +12,7 @@
#include "soc/rtc.h"
#include "soc/system_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/regi2c_defs.h"
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_bbpll.h"
#include "hal/assert.h"
@ -682,6 +683,45 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_rtc_slow_load_cal(v
return REG_READ(RTC_SLOW_CLK_CAL_REG);
}
/**
* @brief Configure PLL frequency for MSPI timing tuning
* @note Only used by the MSPI Timing tuning driver
*
* @param xtal_freq Xtal frequency
* @param pll_freq PLL frequency
* @param oc_div OC divider
* @param oc_ref_div OC ref divider
*/
static inline __attribute__((always_inline))
void clk_ll_bbpll_set_frequency_for_mspi_tuning(rtc_xtal_freq_t xtal_freq, int pll_freq, uint8_t oc_div, uint8_t oc_ref_div)
{
HAL_ASSERT(xtal_freq == RTC_XTAL_FREQ_40M);
uint32_t pll_reg = GET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
HAL_ASSERT(pll_reg == 0);
/* Set this register to let the digital part know 480M PLL is used */
SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL);
uint8_t dr1 = 0;
uint8_t dr3 = 0;
uint8_t dchgp = 5;
uint8_t dcur = 3;
uint8_t dbias = 2;
uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (oc_ref_div);
uint8_t i2c_bbpll_div_7_0 = oc_div;
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B);
uint8_t i2c_bbpll_dcur = (1 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3);
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -575,6 +575,9 @@ static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void)
case 2:
clock_val = 160;
break;
case 3:
clock_val = 240;
break;
default:
abort();
}

View File

@ -310,5 +310,4 @@ menu "SPI Flash driver"
help
This option is invisible, and will be selected automatically
when ``ESPTOOLPY_FLASHFREQ_120M`` is selected.
endmenu

View File

@ -160,17 +160,22 @@ Restrictions
External RAM use has the following restrictions:
* When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible; any reads from or writes to it will lead to an illegal cache access exception. This is also the reason why ESP-IDF does not by default allocate any task stacks in external RAM (see below).
* When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible. Any read operations from or write operations to it will lead to an illegal cache access exception. This is also the reason why ESP-IDF does not by default allocate any task stacks in external RAM (see below).
* External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Therefore when External RAM is enabled, any buffer that will be used in combination with DMA must be allocated using ``heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL)`` and can be freed using a standard ``free()`` call.
.. only:: SOC_PSRAM_DMA_CAPABLE and not esp32s3
.. only:: SOC_PSRAM_DMA_CAPABLE
* External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Therefore when External RAM is enabled, any buffer that will be used in combination with DMA must be allocated using ``heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL)`` and can be freed using a standard ``free()`` call. Note, although {IDF_TARGET_NAME} has hardware support for DMA to / from external RAM, this is not yet supported in ESP-IDF.
Note, although {IDF_TARGET_NAME} has hardware support for DMA to/from external RAM, this is not yet supported in ESP-IDF.
.. only:: esp32s3
* External RAM uses the same cache region as the external flash. This means that frequently accessed variables in external RAM can be read and modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32 KB), the cache can be insufficient, and speeds will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can "push out" cached flash, possibly making the execution of code slower afterwards.
* Although {IDF_TARGET_NAME} has hardware support for DMA to / from external RAM, there are still limitations:
* In general, external RAM will not be used as task stack memory. :cpp:func:`xTaskCreate` and similar functions will always allocate internal memory for stack and task TCBs.
- The bandwidth that DMA accesses external RAM is very limited, especially when CPU is trying to access the external RAM at the same time.
- You can configure :ref:`CONFIG_SPIRAM_SPEED` as 120 MHz for an Octal PSRAM. The bandwidth will be improved. However there are still restrictions for this option, see :ref:`All Supported PSRAM Modes and Speeds <flash-psram-combination>` for more details.
* External RAM uses the same cache region as the external flash. This means that frequently accessed variables in external RAM can be read and modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32 KB), the cache can be insufficient, and speeds will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can "push out" cached flash, possibly making the execution of code slower afterwards.
* In general, external RAM will not be used as task stack memory. :cpp:func:`xTaskCreate` and similar functions will always allocate internal memory for stack and task TCBs.
The option :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` can be used to allow placing task stacks into external memory. In these cases :cpp:func:`xTaskCreateStatic` must be used to specify a task stack buffer allocated from external memory, otherwise task stacks will still be allocated from internal memory.

View File

@ -74,20 +74,34 @@ All Supported Modes and Speeds
For MSPI DDR mode, the data are sampled on both the positive edge and the negative edge. e.g.: if a Flash is set to 80 MHz and DDR mode, then the final speed of the Flash is 160 MHz. This is faster than the Flash setting to 120 Mhz and STR mode.
.. important::
120 MHz DDR mode is an experimental feature. You will only see it when:
- :ref:`CONFIG_IDF_EXPERIMENTAL_FEATURES` is enabled
With above step, you will find 120 MHz option is visible.
Risks:
If your chip powers on at a certain temperature, then after the temperature increases or decreases over 20 celsius degree, the accesses to / from PSRAM / Flash will crash randomly. Flash access crash will lead to program crash.
Note 20 celsius degree is not a totally correct number. This value may changes among chips.
F8R8 Hardware
^^^^^^^^^^^^^
======= =============== ======= ============
======= =============== ======= =============
Group Flash mode Group PSRAM mode
======= =============== ======= ============
A 120 MHz SDR A N.A.
======= =============== ======= =============
A 120 MHz DDR A 120 MHz DDR
A 120 MHz SDR A
B 80 MHz DDR B 80 MHz DDR
C 80 MHz SDR C 40 MHz DDR
C 40 MHz DDR C
C < 40 MHz C
D D disable
======= =============== ======= ============
======= =============== ======= =============
1. Flash mode in group A works with PSRAM mode in group A/D
2. Flash mode in group B/C works with PSRAM mode in group B/C/D
@ -99,7 +113,7 @@ F4R8 Hardware
======= =============== ======= ============
Group Flash mode Group PSRAM mode
======= =============== ======= ============
A 120 MHz SDR A N.A.
A 120 MHz SDR A 120MHz DDR
B 80 MHz SDR B 80MHz DDR
C 40 MHz SDR C 40MHz DDR
C 20 MHz SDR C