spi_master: add feature spi periph clk source selectable

This commit is contained in:
wanlei 2023-01-18 10:56:25 +08:00
parent b20c156ae6
commit 184145817c
45 changed files with 542 additions and 138 deletions

View File

@ -111,6 +111,15 @@ menu "Driver Configurations"
Also you can forbid the ISR being disabled during flash writing Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver. access, by add ESP_INTR_FLAG_IRAM when initializing the driver.
config SPI_SUPPRESS_FREQ_MACRO_DEPRECATE_WARN
bool "Suppress SPI_MASTER_FREQ_nM deprecation warning"
default n
help
Select this option to suppress the deprecation warning when using
`SPI_MASTER_FREQ_nM` macros.
SPI clock source can be set into different clock sources. These
macros are no longer guaranteed to be accurate.
endmenu # SPI Configuration endmenu # SPI Configuration
menu "TWAI Configuration" menu "TWAI Configuration"

View File

@ -8,12 +8,25 @@
#include "esp_err.h" #include "esp_err.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "hal/spi_types.h"
//for spi_bus_initialization funcions. to be back-compatible //for spi_bus_initialization funcions. to be back-compatible
#include "driver/spi_common.h" #include "driver/spi_common.h"
/** SPI master clock is divided by 80MHz apb clock. Below defines are example frequencies, and are accurate. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz). /** SPI master clock is divided by clock source. Below defines are example frequencies. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz).
* 8MHz
*/ */
#if !CONFIG_SPI_SUPPRESS_FREQ_MACRO_DEPRECATE_WARN
#define SPI_MASTER_FREQ_8M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/10)
#define SPI_MASTER_FREQ_9M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/9) ///< 8.89MHz
#define SPI_MASTER_FREQ_10M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/8) ///< 10MHz
#define SPI_MASTER_FREQ_11M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/7) ///< 11.43MHz
#define SPI_MASTER_FREQ_13M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/6) ///< 13.33MHz
#define SPI_MASTER_FREQ_16M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/5) ///< 16MHz
#define SPI_MASTER_FREQ_20M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/4) ///< 20MHz
#define SPI_MASTER_FREQ_26M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/3) ///< 26.67MHz
#define SPI_MASTER_FREQ_40M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/2) ///< 40MHz
#define SPI_MASTER_FREQ_80M _Pragma("GCC warning \"'SPI_MASTER_FREQ_xxM' macro is deprecated\"") (APB_CLK_FREQ/1) ///< 80MHz
#else
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10) #define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10)
#define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz #define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz
#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz #define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz
@ -24,6 +37,8 @@
#define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz #define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz
#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz #define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz
#define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz #define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz
#endif //!CONFIG_SPI_SUPPRESS_FREQ_MACRO_DEPRECATE_WARN
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -63,6 +78,7 @@ typedef struct {
- 2: (1, 0) - 2: (1, 0)
- 3: (1, 1) - 3: (1, 1)
*/ */
spi_clock_source_t clock_source;///< Select SPI clock source, `SPI_CLK_SRC_DEFAULT` by default.
uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128. uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions. uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16) uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
@ -356,7 +372,7 @@ esp_err_t spi_device_get_actual_freq(spi_device_handle_t handle, int* freq_khz);
* *
* @return Actual working frequency that most fit. * @return Actual working frequency that most fit.
*/ */
int spi_get_actual_clock(int fapb, int hz, int duty_cycle); int spi_get_actual_clock(int fapb, int hz, int duty_cycle) __attribute__((deprecated("Please use spi_device_get_actual_freq instead")));
/** /**
* @brief Calculate the timing settings of specified frequency and settings. * @brief Calculate the timing settings of specified frequency and settings.

View File

@ -113,7 +113,7 @@ We have two bits to control the interrupt:
#include <string.h> #include <string.h>
#include "esp_private/spi_common_internal.h" #include "esp_private/spi_common_internal.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "clk_tree.h"
#include "esp_log.h" #include "esp_log.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
@ -121,8 +121,6 @@ We have two bits to control the interrupt:
#include "driver/gpio.h" #include "driver/gpio.h"
#include "hal/spi_hal.h" #include "hal/spi_hal.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
//Temporarily include esp_clk.h, will be replaced by clock tree API
#include "esp_private/esp_clk.h"
typedef struct spi_device_t spi_device_t; typedef struct spi_device_t spi_device_t;
@ -156,6 +154,7 @@ typedef struct {
struct spi_device_t { struct spi_device_t {
int id; int id;
int real_clk_freq_hz;
QueueHandle_t trans_queue; QueueHandle_t trans_queue;
QueueHandle_t ret_queue; QueueHandle_t ret_queue;
spi_device_interface_config_t cfg; spi_device_interface_config_t cfg;
@ -286,17 +285,28 @@ static esp_err_t spi_master_deinit_driver(void* arg)
void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dummy_o, int* cycles_remain_o) void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dummy_o, int* cycles_remain_o)
{ {
#ifdef CONFIG_IDF_TARGET_ESP32
int timing_dummy; int timing_dummy;
int timing_miso_delay; int timing_miso_delay;
spi_hal_cal_timing(eff_clk, gpio_is_used, input_delay_ns, &timing_dummy, &timing_miso_delay); spi_hal_cal_timing(APB_CLK_FREQ, eff_clk, gpio_is_used, input_delay_ns, &timing_dummy, &timing_miso_delay);
if (dummy_o) *dummy_o = timing_dummy; if (dummy_o) *dummy_o = timing_dummy;
if (cycles_remain_o) *cycles_remain_o = timing_miso_delay; if (cycles_remain_o) *cycles_remain_o = timing_miso_delay;
#else
//TODO: IDF-6578
ESP_LOGW(SPI_TAG, "This func temporary not supported for current target!");
#endif
} }
int spi_get_freq_limit(bool gpio_is_used, int input_delay_ns) int spi_get_freq_limit(bool gpio_is_used, int input_delay_ns)
{ {
#ifdef CONFIG_IDF_TARGET_ESP32
return spi_hal_get_freq_limit(gpio_is_used, input_delay_ns); return spi_hal_get_freq_limit(gpio_is_used, input_delay_ns);
#else
//TODO: IDF-6578
ESP_LOGW(SPI_TAG, "This func temporary not supported for current target!");
return 0;
#endif
} }
/* /*
@ -320,9 +330,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
spi_host_t *host = bus_driver_ctx[host_id]; spi_host_t *host = bus_driver_ctx[host_id];
const spi_bus_attr_t* bus_attr = host->bus_attr; const spi_bus_attr_t* bus_attr = host->bus_attr;
SPI_CHECK(dev_config->spics_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(dev_config->spics_io_num), "spics pin invalid", ESP_ERR_INVALID_ARG); SPI_CHECK(dev_config->spics_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(dev_config->spics_io_num), "spics pin invalid", ESP_ERR_INVALID_ARG);
uint32_t apb_clk_freq_hz = esp_clk_apb_freq(); uint32_t clock_source_hz;
assert((apb_clk_freq_hz == 80 * 1000 * 1000) || (apb_clk_freq_hz == 40 * 1000 * 1000) || (apb_clk_freq_hz == 48 * 1000 * 1000)); clk_tree_src_get_freq_hz((dev_config->clock_source == 0)?SPI_CLK_SRC_DEFAULT:dev_config->clock_source, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
SPI_CHECK((dev_config->clock_speed_hz > 0) && (dev_config->clock_speed_hz <= apb_clk_freq_hz) , "invalid sclk speed", ESP_ERR_INVALID_ARG); SPI_CHECK((dev_config->clock_speed_hz > 0) && (dev_config->clock_speed_hz <= clock_source_hz), "invalid sclk speed", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
//The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full //The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full
//duplex mode does absolutely nothing on the ESP32. //duplex mode does absolutely nothing on the ESP32.
@ -355,10 +365,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
int duty_cycle = (dev_config->duty_cycle_pos==0) ? 128 : dev_config->duty_cycle_pos; int duty_cycle = (dev_config->duty_cycle_pos==0) ? 128 : dev_config->duty_cycle_pos;
int use_gpio = !(bus_attr->flags & SPICOMMON_BUSFLAG_IOMUX_PINS); int use_gpio = !(bus_attr->flags & SPICOMMON_BUSFLAG_IOMUX_PINS);
spi_hal_timing_param_t timing_param = { spi_hal_timing_param_t timing_param = {
.clk_src_hz = esp_clk_apb_freq(),
.clk_sel = SPI_CLK_APB, //Currently, SPI driver only set SPI to APB clock. SPI is not supposed to be used during sleep modes.
.half_duplex = half_duplex, .half_duplex = half_duplex,
.no_compensate = no_compensate, .no_compensate = no_compensate,
.clk_src_hz = clock_source_hz,
.expected_freq = dev_config->clock_speed_hz, .expected_freq = dev_config->clock_speed_hz,
.duty_cycle = duty_cycle, .duty_cycle = duty_cycle,
.input_delay_ns = dev_config->input_delay_ns, .input_delay_ns = dev_config->input_delay_ns,
@ -369,6 +378,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
spi_hal_timing_conf_t temp_timing_conf; spi_hal_timing_conf_t temp_timing_conf;
int freq; int freq;
esp_err_t ret = spi_hal_cal_clock_conf(&timing_param, &freq, &temp_timing_conf); esp_err_t ret = spi_hal_cal_clock_conf(&timing_param, &freq, &temp_timing_conf);
temp_timing_conf.clock_source = dev_config->clock_source;
SPI_CHECK(ret==ESP_OK, "assigned clock speed not supported", ret); SPI_CHECK(ret==ESP_OK, "assigned clock speed not supported", ret);
//Allocate memory for device //Allocate memory for device
@ -395,6 +405,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
//We want to save a copy of the dev config in the dev struct. //We want to save a copy of the dev config in the dev struct.
memcpy(&dev->cfg, dev_config, sizeof(spi_device_interface_config_t)); memcpy(&dev->cfg, dev_config, sizeof(spi_device_interface_config_t));
dev->cfg.duty_cycle_pos = duty_cycle; dev->cfg.duty_cycle_pos = duty_cycle;
dev->real_clk_freq_hz = freq;
// TODO: if we have to change the apb clock among transactions, re-calculate this each time the apb clock lock is locked. // TODO: if we have to change the apb clock among transactions, re-calculate this each time the apb clock lock is locked.
//Set CS pin, CS options //Set CS pin, CS options
@ -476,10 +487,7 @@ esp_err_t spi_device_get_actual_freq(spi_device_handle_t handle, int* freq_khz)
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
int dev_required_freq = ((spi_device_t*)handle)->cfg.clock_speed_hz; *freq_khz = handle->real_clk_freq_hz / 1000;
int dev_duty_cycle = ((spi_device_t*)handle)->cfg.duty_cycle_pos;
*freq_khz = spi_get_actual_clock(esp_clk_apb_freq(), dev_required_freq, dev_duty_cycle);
return ESP_OK; return ESP_OK;
} }
@ -846,6 +854,8 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
if (ret != ESP_OK) return ret; if (ret != ESP_OK) return ret;
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
// though clock source is selectable, read/write reg and mem of spi peripherial still use APB
// and dma still use APB, so pm_lock is still needed
esp_pm_lock_acquire(host->bus_attr->pm_lock); esp_pm_lock_acquire(host->bus_attr->pm_lock);
#endif #endif
//Send to queue and invoke the ISR. //Send to queue and invoke the ISR.

View File

@ -145,8 +145,8 @@
#define TV_WITH_ESP_SLAVE (TV_INT_CONNECT+WIRE_DELAY) #define TV_WITH_ESP_SLAVE (TV_INT_CONNECT+WIRE_DELAY)
//currently ESP32 slave only supports up to 20MHz, but 40MHz on the same board //currently ESP32 slave only supports up to 20MHz, but 40MHz on the same board
#define ESP_SPI_SLAVE_MAX_FREQ SPI_MASTER_FREQ_20M #define ESP_SPI_SLAVE_MAX_FREQ 20 * 1000 * 1000
#define ESP_SPI_SLAVE_MAX_FREQ_SYNC SPI_MASTER_FREQ_40M #define ESP_SPI_SLAVE_MAX_FREQ_SYNC 40 * 1000 * 1000
#define MAX_TEST_SIZE 16 ///< in this test we run several transactions, this is the maximum trans that can be run #define MAX_TEST_SIZE 16 ///< in this test we run several transactions, this is the maximum trans that can be run
#define PSET_NAME_LEN 30 ///< length of each param set name #define PSET_NAME_LEN 30 ///< length of each param set name
@ -154,16 +154,16 @@
//test low frequency, high frequency until freq limit for worst case (both GPIO) //test low frequency, high frequency until freq limit for worst case (both GPIO)
#define TEST_FREQ_DEFAULT(){ \ #define TEST_FREQ_DEFAULT(){ \
1 * 1000 * 1000, \ 1 * 1000 * 1000, \
SPI_MASTER_FREQ_8M , \ 8 * 1000 * 1000, \
SPI_MASTER_FREQ_9M , \ 9 * 1000 * 1000, \
SPI_MASTER_FREQ_10M, \ 10 * 1000 * 1000, \
SPI_MASTER_FREQ_11M, \ 11 * 1000 * 1000, \
SPI_MASTER_FREQ_13M, \ 13 * 1000 * 1000, \
SPI_MASTER_FREQ_16M, \ 16 * 1000 * 1000, \
SPI_MASTER_FREQ_20M, \ 20 * 1000 * 1000, \
SPI_MASTER_FREQ_26M, \ 26 * 1000 * 1000, \
SPI_MASTER_FREQ_40M, \ 40 * 1000 * 1000, \
SPI_MASTER_FREQ_80M, \ 80 * 1000 * 1000, \
0,\ 0,\
} }

View File

@ -19,6 +19,7 @@
#include "esp_private/spi_common_internal.h" #include "esp_private/spi_common_internal.h"
#include "esp_private/esp_clk.h" #include "esp_private/esp_clk.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "clk_tree.h"
#include "esp_log.h" #include "esp_log.h"
#include "test_utils.h" #include "test_utils.h"
#include "test_spi_utils.h" #include "test_spi_utils.h"
@ -29,7 +30,7 @@ const static char TAG[] = "test_spi";
// There is no input-only pin except on esp32 and esp32s2 // There is no input-only pin except on esp32 and esp32s2
#define TEST_SOC_HAS_INPUT_ONLY_PINS (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2) #define TEST_SOC_HAS_INPUT_ONLY_PINS (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2)
static void check_spi_pre_n_for(int clk, int pre, int n) static void check_spi_pre_n_for(spi_clock_source_t clock_source, int clk, int pre, int n)
{ {
spi_device_handle_t handle; spi_device_handle_t handle;
@ -37,6 +38,7 @@ static void check_spi_pre_n_for(int clk, int pre, int n)
.command_bits = 0, .command_bits = 0,
.address_bits = 0, .address_bits = 0,
.dummy_bits = 0, .dummy_bits = 0,
.clock_source = clock_source,
.clock_speed_hz = clk, .clock_speed_hz = clk,
.duty_cycle_pos = 128, .duty_cycle_pos = 128,
.mode = 0, .mode = 0,
@ -63,7 +65,6 @@ static void check_spi_pre_n_for(int clk, int pre, int n)
TEST_ESP_OK(spi_bus_remove_device(handle)); TEST_ESP_OK(spi_bus_remove_device(handle));
} }
#define TEST_CLK_TIMES 8
/** /**
* In this test, SPI Clock Calculation: * In this test, SPI Clock Calculation:
* Fspi = Fclk_spi_mst / (pre + n) * Fspi = Fclk_spi_mst / (pre + n)
@ -71,33 +72,71 @@ static void check_spi_pre_n_for(int clk, int pre, int n)
* For each item: * For each item:
* {freq, pre, n} * {freq, pre, n}
*/ */
#define TEST_CLK_PARAM_APB_80 {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 16, 50}, {333333, 4, 60}, {800000, 2, 50}, {900000, 2, 44}, {8000000, 1, 10}, {20000000, 1, 4}, {26000000, 1, 3} } #define TEST_CLK_TIMES 8
#define TEST_CLK_PARAM_APB_40 {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 50}, {333333, 2, 60}, {800000, 1, 50}, {900000, 1, 44}, {8000000, 1, 5}, {10000000, 1, 4}, {20000000, 1, 2} } struct test_clk_param_group_t
{
uint32_t clk_param_80m[TEST_CLK_TIMES][3];
uint32_t clk_param_40m[TEST_CLK_TIMES][3];
uint32_t clk_param_17m[TEST_CLK_TIMES][3];
} test_clk_param = {
{{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 16, 50}, {333333, 4, 60}, {800000, 2, 50}, {900000, 2, 44}, {8000000, 1, 10}, {20000000, 1, 4}, {26000000, 1, 3} },
{{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 50}, {333333, 2, 60}, {800000, 1, 50}, {900000, 1, 44}, {8000000, 1, 5}, {10000000, 1, 4}, {20000000, 1, 2} },
{{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 5, 35}, {333333, 1, 53}, {800000, 1, 22}, {900000, 1, 19}, {8000000, 1, 2}, {10000000, 1, 2}, {15000000, 1, 1} },
};
TEST_CASE("SPI Master clockdiv calculation routines", "[spi]") TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
{ {
spi_bus_config_t buscfg = { spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1
};
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
uint32_t clock_source_hz;
// Test main clock source
#if SOC_SPI_SUPPORT_CLK_PLL_F80M
clk_tree_src_get_freq_hz(SPI_CLK_SRC_PLL_F80M, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source PLL_80M = %ld\n", clock_source_hz);
TEST_ASSERT((80 * 1000 * 1000) == clock_source_hz);
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_PLL_F80M, test_clk_param.clk_param_80m[i][0], test_clk_param.clk_param_80m[i][1], test_clk_param.clk_param_80m[i][2]);
}
#endif
uint32_t apb_freq_hz = esp_clk_apb_freq(); #if SOC_SPI_SUPPORT_CLK_PLL_F40M
if (apb_freq_hz == (80 * 1000 * 1000)) { clk_tree_src_get_freq_hz(SPI_CLK_SRC_PLL_F40M, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_80; printf("\nTest clock source PLL_40M = %ld\n", clock_source_hz);
TEST_ASSERT((40 * 1000 * 1000) == clock_source_hz);
for (int i = 0; i < TEST_CLK_TIMES; i++) { for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(clk_param[i][0], clk_param[i][1], clk_param[i][2]); check_spi_pre_n_for(SPI_CLK_SRC_PLL_F40M, test_clk_param.clk_param_40m[i][0], test_clk_param.clk_param_40m[i][1], test_clk_param.clk_param_40m[i][2]);
} }
} else { #endif
TEST_ASSERT(apb_freq_hz == (40 * 1000 * 1000));
uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_40; #if SOC_SPI_SUPPORT_CLK_APB
clk_tree_src_get_freq_hz(SPI_CLK_SRC_APB, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source APB = %ld\n", clock_source_hz);
TEST_ASSERT((80 * 1000 * 1000) == clock_source_hz);
for (int i = 0; i < TEST_CLK_TIMES; i++) { for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(clk_param[i][0], clk_param[i][1], clk_param[i][2]); check_spi_pre_n_for(SPI_CLK_SRC_APB, test_clk_param.clk_param_80m[i][0], test_clk_param.clk_param_80m[i][1], test_clk_param.clk_param_80m[i][2]);
} }
#endif
// Test XTAL clock source
#if SOC_SPI_SUPPORT_CLK_XTAL
clk_tree_src_get_freq_hz(SPI_CLK_SRC_XTAL, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source XTAL = %ld\n", clock_source_hz);
TEST_ASSERT((40 * 1000 * 1000) == clock_source_hz);
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_XTAL, test_clk_param.clk_param_40m[i][0], test_clk_param.clk_param_40m[i][1], test_clk_param.clk_param_40m[i][2]);
} }
#endif
// Test RC fast osc clock source
#if SOC_SPI_SUPPORT_CLK_RC_FAST
clk_tree_src_get_freq_hz(SPI_CLK_SRC_RC_FAST, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source RC_FAST = %ld\n", clock_source_hz);
TEST_ASSERT((17500000) == clock_source_hz);
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_RC_FAST, test_clk_param.clk_param_17m[i][0], test_clk_param.clk_param_17m[i][1], test_clk_param.clk_param_17m[i][2]);
}
#endif
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
} }

View File

@ -235,7 +235,7 @@ static spitest_param_set_t timing_pgroup[] = {
#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) #if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
{ .pset_name = "FULL_DUP, MASTER IOMUX", { .pset_name = "FULL_DUP, MASTER IOMUX",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = true, .master_iomux = true,
.slave_iomux = false, .slave_iomux = false,
@ -243,7 +243,7 @@ static spitest_param_set_t timing_pgroup[] = {
}, },
{ .pset_name = "FULL_DUP, SLAVE IOMUX", { .pset_name = "FULL_DUP, SLAVE IOMUX",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = false, .master_iomux = false,
.slave_iomux = true, .slave_iomux = true,
@ -252,7 +252,7 @@ static spitest_param_set_t timing_pgroup[] = {
#endif #endif
{ .pset_name = "FULL_DUP, BOTH GPIO", { .pset_name = "FULL_DUP, BOTH GPIO",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC,
.master_limit = SPI_MASTER_FREQ_10M, .master_limit = 10 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = false, .master_iomux = false,
.slave_iomux = false, .slave_iomux = false,
@ -316,15 +316,15 @@ static spitest_param_set_t timing_pgroup[] = {
TEST_SPI_LOCAL(TIMING, timing_pgroup) TEST_SPI_LOCAL(TIMING, timing_pgroup)
/************ Mode Test ***********************************************/ /************ Mode Test ***********************************************/
#define FREQ_LIMIT_MODE SPI_MASTER_FREQ_16M #define FREQ_LIMIT_MODE 16 * 1000 * 1000
static int test_freq_mode_local[]={ static int test_freq_mode_local[]={
1 * 1000 * 1000, 1 * 1000 * 1000,
SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge 9 * 1000 * 1000, //maximum freq MISO stable before next latch edge
SPI_MASTER_FREQ_13M, 13 * 1000 * 1000,
SPI_MASTER_FREQ_16M, 16 * 1000 * 1000,
SPI_MASTER_FREQ_20M, 20 * 1000 * 1000,
SPI_MASTER_FREQ_26M, 26 * 1000 * 1000,
SPI_MASTER_FREQ_40M, 40 * 1000 * 1000,
0, 0,
}; };
@ -358,7 +358,7 @@ static int test_freq_mode_local[]={
static spitest_param_set_t mode_pgroup[] = { static spitest_param_set_t mode_pgroup[] = {
{ .pset_name = "Mode 0", { .pset_name = "Mode 0",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 0, .mode = 0,
.master_iomux = false, .master_iomux = false,
@ -367,8 +367,8 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 1", { .pset_name = "Mode 1",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.freq_limit = SPI_MASTER_FREQ_26M, .freq_limit = 26 * 1000 * 1000,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 1, .mode = 1,
.master_iomux = false, .master_iomux = false,
@ -377,7 +377,7 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 2", { .pset_name = "Mode 2",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 2, .mode = 2,
.master_iomux = false, .master_iomux = false,
@ -386,8 +386,8 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 3", { .pset_name = "Mode 3",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.freq_limit = SPI_MASTER_FREQ_26M, .freq_limit = 26 * 1000 * 1000,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 3, .mode = 3,
.master_iomux = false, .master_iomux = false,
@ -396,7 +396,7 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 0, DMA", { .pset_name = "Mode 0, DMA",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 0, .mode = 0,
.slave_dma_chan = SPI_DMA_CH_AUTO, .slave_dma_chan = SPI_DMA_CH_AUTO,
@ -407,8 +407,8 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 1, DMA", { .pset_name = "Mode 1, DMA",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.freq_limit = SPI_MASTER_FREQ_26M, .freq_limit = 26 * 1000 * 1000,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 1, .mode = 1,
.slave_dma_chan = SPI_DMA_CH_AUTO, .slave_dma_chan = SPI_DMA_CH_AUTO,
@ -419,7 +419,7 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 2, DMA", { .pset_name = "Mode 2, DMA",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 2, .mode = 2,
.slave_dma_chan = SPI_DMA_CH_AUTO, .slave_dma_chan = SPI_DMA_CH_AUTO,
@ -430,8 +430,8 @@ static spitest_param_set_t mode_pgroup[] = {
}, },
{ .pset_name = "Mode 3, DMA", { .pset_name = "Mode 3, DMA",
.freq_list = test_freq_mode_local, .freq_list = test_freq_mode_local,
.freq_limit = SPI_MASTER_FREQ_26M, .freq_limit = 26 * 1000 * 1000,
.master_limit = SPI_MASTER_FREQ_13M, .master_limit = 13 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.mode = 3, .mode = 3,
.slave_dma_chan = SPI_DMA_CH_AUTO, .slave_dma_chan = SPI_DMA_CH_AUTO,
@ -907,7 +907,7 @@ static void test_slave_loop(const void *arg1, void* arg2)
static spitest_param_set_t timing_conf[] = { static spitest_param_set_t timing_conf[] = {
{ .pset_name = "FULL_DUP, BOTH IOMUX", { .pset_name = "FULL_DUP, BOTH IOMUX",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
.master_limit = SPI_MASTER_FREQ_16M, .master_limit = 16 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux= true, .master_iomux= true,
.slave_iomux = true, .slave_iomux = true,
@ -915,7 +915,7 @@ static spitest_param_set_t timing_conf[] = {
}, },
{ .pset_name = "FULL_DUP, MASTER IOMUX", { .pset_name = "FULL_DUP, MASTER IOMUX",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
.master_limit = SPI_MASTER_FREQ_11M, .master_limit = 11 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = true, .master_iomux = true,
.slave_iomux = false, .slave_iomux = false,
@ -923,7 +923,7 @@ static spitest_param_set_t timing_conf[] = {
}, },
{ .pset_name = "FULL_DUP, SLAVE IOMUX", { .pset_name = "FULL_DUP, SLAVE IOMUX",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
.master_limit = SPI_MASTER_FREQ_11M, .master_limit = 11 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = false, .master_iomux = false,
.slave_iomux = true, .slave_iomux = true,
@ -931,7 +931,7 @@ static spitest_param_set_t timing_conf[] = {
}, },
{ .pset_name = "FULL_DUP, BOTH GPIO", { .pset_name = "FULL_DUP, BOTH GPIO",
.freq_limit = ESP_SPI_SLAVE_MAX_FREQ, .freq_limit = ESP_SPI_SLAVE_MAX_FREQ,
.master_limit = SPI_MASTER_FREQ_9M, .master_limit = 9 * 1000 * 1000,
.dup = FULL_DUPLEX, .dup = FULL_DUPLEX,
.master_iomux = false, .master_iomux = false,
.slave_iomux = false, .slave_iomux = false,
@ -997,7 +997,7 @@ static spitest_param_set_t timing_conf[] = {
TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "") TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "")
/************ Mode Test ***********************************************/ /************ Mode Test ***********************************************/
#define FREQ_LIMIT_MODE SPI_MASTER_FREQ_16M #define FREQ_LIMIT_MODE 16 * 1000 * 1000
//Set to this input delay so that the master will read with delay until 7M //Set to this input delay so that the master will read with delay until 7M
#define DELAY_HCLK_UNTIL_7M 12.5*3 #define DELAY_HCLK_UNTIL_7M 12.5*3
@ -1005,17 +1005,17 @@ static int test_freq_mode_ms[]={
100 * 1000, 100 * 1000,
6 * 1000 * 1000, 6 * 1000 * 1000,
7 * 1000 * 1000, 7 * 1000 * 1000,
SPI_MASTER_FREQ_8M, //maximum freq MISO stable before next latch edge 8 * 1000 * 1000, //maximum freq MISO stable before next latch edge
SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge 9 * 1000 * 1000, //maximum freq MISO stable before next latch edge
SPI_MASTER_FREQ_10M, 10 * 1000 * 1000,
SPI_MASTER_FREQ_11M, 11 * 1000 * 1000,
SPI_MASTER_FREQ_13M, 13 * 1000 * 1000,
SPI_MASTER_FREQ_16M, 16 * 1000 * 1000,
SPI_MASTER_FREQ_20M, 20 * 1000 * 1000,
0, 0,
}; };
static int test_freq_20M_only[]={ static int test_freq_20M_only[]={
SPI_MASTER_FREQ_20M, 20 * 1000 * 1000,
0, 0,
}; };

View File

@ -444,9 +444,9 @@ static const ptest_func_t hd_test_func = {
static int test_freq_hd[] = { static int test_freq_hd[] = {
// 100*1000, // 100*1000,
// SPI_MASTER_FREQ_10M, //maximum freq MISO stable before next latch edge // 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge
// SPI_MASTER_FREQ_20M, //maximum freq MISO stable before next latch edge // 20 * 1000 * 1000, //maximum freq MISO stable before next latch edge
SPI_MASTER_FREQ_40M, //maximum freq MISO stable before next latch edge 40 * 1000 * 1000, //maximum freq MISO stable before next latch edge
0, 0,
}; };

View File

@ -37,8 +37,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_DUAL | SPI_FWRITE_QUAD | SPI_FWRITE_DIO | SPI_FWRITE_QIO) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_DUAL | SPI_FWRITE_QUAD | SPI_FWRITE_DIO | SPI_FWRITE_QIO)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? &SPI1:((ID)==1? &SPI2 : &SPI3)) #define SPI_LL_GET_HW(ID) ((ID)==0? &SPI1:((ID)==1? &SPI2 : &SPI3))
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 24) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 24)
@ -56,6 +54,18 @@ typedef spi_dev_t spi_dma_dev_t;
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{
//empty, keep this for compatibility
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -36,8 +36,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2)
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 18) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 18)
@ -92,6 +90,25 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source)
{
case SPI_CLK_SRC_XTAL:
hw->clk_gate.mst_clk_sel = 0;
break;
default:
hw->clk_gate.mst_clk_sel = 1;
break;
}
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -36,8 +36,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2)
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 18) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 18)
@ -92,6 +90,25 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source)
{
case SPI_CLK_SRC_XTAL:
hw->clk_gate.mst_clk_sel = 0;
break;
default:
hw->clk_gate.mst_clk_sel = 1;
break;
}
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -37,8 +37,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2)
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 18) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 18)
@ -93,6 +91,29 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{
switch (clk_source)
{
case SPI_CLK_SRC_RC_FAST:
PCR.spi2_clkm_conf.spi2_clkm_sel = 2;
break;
case SPI_CLK_SRC_XTAL:
PCR.spi2_clkm_conf.spi2_clkm_sel = 0;
break;
default:
PCR.spi2_clkm_conf.spi2_clkm_sel = 1;
break;
}
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -36,8 +36,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2)
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 18) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 18)
@ -92,6 +90,18 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{
//empty, keep this for compatibility
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -39,8 +39,6 @@ extern "C" {
#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 23) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 23)
@ -102,6 +100,18 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{
//empty, keep this for compatibility
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -38,8 +38,6 @@ extern "C" {
/// Swap the bit order to its correct place to send /// Swap the bit order to its correct place to send
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
/// This is the expected clock frequency
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
#define SPI_LL_DATA_MAX_BIT_LEN (1 << 18) #define SPI_LL_DATA_MAX_BIT_LEN (1 << 18)
@ -94,6 +92,25 @@ typedef enum {
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Control * Control
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/**
* Select SPI peripheral clock source (master).
*
* @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source)
{
case SPI_CLK_SRC_XTAL:
hw->clk_gate.mst_clk_sel = 0;
break;
default:
hw->clk_gate.mst_clk_sel = 1;
break;
}
}
/** /**
* Initialize SPI peripheral (master). * Initialize SPI peripheral (master).
* *

View File

@ -36,7 +36,6 @@
* Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
*/ */
typedef struct { typedef struct {
spi_clock_source_t clk_sel; ///< Select SPI clock source
uint32_t clk_src_hz; ///< Selected SPI clock source speed in Hz uint32_t clk_src_hz; ///< Selected SPI clock source speed in Hz
uint32_t half_duplex; ///< Whether half duplex mode is used, device specific uint32_t half_duplex; ///< Whether half duplex mode is used, device specific
uint32_t no_compensate; ///< No need to add dummy to compensate the timing, device specific uint32_t no_compensate; ///< No need to add dummy to compensate the timing, device specific
@ -56,6 +55,7 @@ typedef struct {
*/ */
typedef struct { typedef struct {
spi_ll_clock_val_t clock_reg; ///< Register value used by the LL layer spi_ll_clock_val_t clock_reg; ///< Register value used by the LL layer
spi_clock_source_t clock_source; ///< Clock source of each device used by LL layer
int timing_dummy; ///< Extra dummy needed to compensate the timing int timing_dummy; ///< Extra dummy needed to compensate the timing
int timing_miso_delay; ///< Extra miso delay clocks to compensate the timing int timing_miso_delay; ///< Extra miso delay clocks to compensate the timing
} spi_hal_timing_conf_t; } spi_hal_timing_conf_t;
@ -244,6 +244,7 @@ int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle);
/** /**
* Get the timing configuration for given parameters. * Get the timing configuration for given parameters.
* *
* @param source_freq_hz Clock freq of selected clock source for SPI in Hz.
* @param eff_clk Actual SPI clock frequency * @param eff_clk Actual SPI clock frequency
* @param gpio_is_used true if the GPIO matrix is used, otherwise false. * @param gpio_is_used true if the GPIO matrix is used, otherwise false.
* @param input_delay_ns Maximum delay between SPI launch clock and the data to * @param input_delay_ns Maximum delay between SPI launch clock and the data to
@ -252,7 +253,7 @@ int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle);
* @param dummy_n Dummy cycles required to correctly read the data. * @param dummy_n Dummy cycles required to correctly read the data.
* @param miso_delay_n suggested delay on the MISO line, in APB clocks. * @param miso_delay_n suggested delay on the MISO line, in APB clocks.
*/ */
void spi_hal_cal_timing(int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n); void spi_hal_cal_timing(int source_freq_hz, int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n);
/** /**
* Get the maximum frequency allowed to read if no compensation is used. * Get the maximum frequency allowed to read if no compensation is used.

View File

@ -9,6 +9,7 @@
#include <stdint.h> #include <stdint.h>
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_bit_defs.h" #include "esp_bit_defs.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "sdkconfig.h" #include "sdkconfig.h"
@ -25,10 +26,10 @@ typedef enum {
SPI_HOST_MAX, ///< invalid host value SPI_HOST_MAX, ///< invalid host value
} spi_host_device_t; } spi_host_device_t;
typedef enum { /**
SPI_CLK_APB, ///< Select APB as the source clock * @brief Type of SPI clock source.
SPI_CLK_XTAL ///< Select XTAL as the source clock */
} spi_clock_source_t; typedef soc_periph_spi_clk_src_t spi_clock_source_t;
/// SPI Events /// SPI Events
typedef enum { typedef enum {

View File

@ -10,6 +10,7 @@
#include "hal/log.h" #include "hal/log.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_GDMA_SUPPORTED #if SOC_GDMA_SUPPORTED
@ -80,13 +81,11 @@ esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int
{ {
spi_hal_timing_conf_t temp_conf; spi_hal_timing_conf_t temp_conf;
int clk_src_freq_hz = timing_param->clk_src_hz; int eff_clk_n = spi_ll_master_cal_clock(timing_param->clk_src_hz, timing_param->expected_freq, timing_param->duty_cycle, &temp_conf.clock_reg);
HAL_ASSERT((clk_src_freq_hz == 80 * 1000 * 1000) || (clk_src_freq_hz == 40 * 1000 * 1000) || (clk_src_freq_hz == 48 * 1000 * 1000));
int eff_clk_n = spi_ll_master_cal_clock(clk_src_freq_hz, timing_param->expected_freq, timing_param->duty_cycle, &temp_conf.clock_reg);
//When the speed is too fast, we may need to use dummy cycles to compensate the reading. //When the speed is too fast, we may need to use dummy cycles to compensate the reading.
//But these don't work for full-duplex connections. //But these don't work for full-duplex connections.
spi_hal_cal_timing(eff_clk_n, timing_param->use_gpio, timing_param->input_delay_ns, &temp_conf.timing_dummy, &temp_conf.timing_miso_delay); spi_hal_cal_timing(timing_param->clk_src_hz, eff_clk_n, timing_param->use_gpio, timing_param->input_delay_ns, &temp_conf.timing_dummy, &temp_conf.timing_miso_delay);
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
const int freq_limit = spi_hal_get_freq_limit(timing_param->use_gpio, timing_param->input_delay_ns); const int freq_limit = spi_hal_get_freq_limit(timing_param->use_gpio, timing_param->input_delay_ns);
@ -113,11 +112,12 @@ int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle)
return spi_ll_master_cal_clock(fapb, hz, duty_cycle, NULL); return spi_ll_master_cal_clock(fapb, hz, duty_cycle, NULL);
} }
void spi_hal_cal_timing(int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n)
void spi_hal_cal_timing(int source_freq_hz, int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n)
{ {
const int apbclk_kHz = APB_CLK_FREQ / 1000; const int apbclk_kHz = source_freq_hz / 1000;
//how many apb clocks a period has //how many apb clocks a period has
const int spiclk_apb_n = APB_CLK_FREQ / eff_clk; const int spiclk_apb_n = source_freq_hz / eff_clk;
const int gpio_delay_ns = gpio_is_used ? GPIO_MATRIX_DELAY_NS : 0; const int gpio_delay_ns = gpio_is_used ? GPIO_MATRIX_DELAY_NS : 0;
//how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off. //how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
@ -144,6 +144,8 @@ void spi_hal_cal_timing(int eff_clk, bool gpio_is_used, int input_delay_ns, int
HAL_LOGD(SPI_HAL_TAG, "eff: %d, limit: %dk(/%d), %d dummy, %d delay", eff_clk / 1000, apbclk_kHz / (delay_apb_n + 1), delay_apb_n, dummy_required, miso_delay); HAL_LOGD(SPI_HAL_TAG, "eff: %d, limit: %dk(/%d), %d dummy, %d delay", eff_clk / 1000, apbclk_kHz / (delay_apb_n + 1), delay_apb_n, dummy_required, miso_delay);
} }
#ifdef CONFIG_IDF_TARGET_ESP32
//TODO: IDF-6578
int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns) int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns)
{ {
const int apbclk_kHz = APB_CLK_FREQ / 1000; const int apbclk_kHz = APB_CLK_FREQ / 1000;
@ -157,3 +159,4 @@ int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns)
return APB_CLK_FREQ / (delay_apb_n + 1); return APB_CLK_FREQ / (delay_apb_n + 1);
} }
#endif

View File

@ -37,6 +37,7 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
#endif #endif
spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs); spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs);
spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg); spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg);
spi_ll_set_clk_source(hw, dev->timing_conf.clock_source);
//Configure bit order //Configure bit order
spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst); spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst);
spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst); spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst);

View File

@ -559,6 +559,10 @@ config SOC_SPI_MAX_CS_NUM
int int
default 3 default 3
config SOC_SPI_SUPPORT_CLK_APB
bool
default y
config SOC_SPI_MAXIMUM_BUFFER_SIZE config SOC_SPI_MAXIMUM_BUFFER_SIZE
int int
default 64 default 64

View File

@ -272,6 +272,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
/////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM////////////////////////////////////////////////////////////// //////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**

View File

@ -275,6 +275,8 @@
#define SOC_SPI_PERIPH_CS_NUM(i) 3 #define SOC_SPI_PERIPH_CS_NUM(i) 3
#define SOC_SPI_MAX_CS_NUM 3 #define SOC_SPI_MAX_CS_NUM 3
#define SOC_SPI_SUPPORT_CLK_APB 1
#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64
#define SOC_SPI_MAX_PRE_DIVIDER 8192 #define SOC_SPI_MAX_PRE_DIVIDER 8192

View File

@ -391,6 +391,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_XTAL
bool
default y
config SOC_SPI_SUPPORT_CLK_PLL_F40M
bool
default y
config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT
bool bool
default y default y

View File

@ -187,6 +187,23 @@ typedef enum {
/////////////////////////////////////////////////I2C//////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_PLL_F40M, SOC_MOD_CLK_XTAL}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F40M, /*!< Select PLL_40M as SPI source clock */
SPI_CLK_SRC_PLL_F40M = SOC_MOD_CLK_PLL_F40M, /*!< Select PLL_40M as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
} soc_periph_spi_clk_src_t;
/** /**
* @brief Array initializer for all supported clock sources of I2C * @brief Array initializer for all supported clock sources of I2C
*/ */

View File

@ -200,6 +200,8 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1
#define SOC_SPI_SUPPORT_CLK_XTAL 1
#define SOC_SPI_SUPPORT_CLK_PLL_F40M 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,

View File

@ -603,6 +603,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_APB
bool
default y
config SOC_SPI_SUPPORT_CLK_XTAL
bool
default y
config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT
bool bool
default y default y

View File

@ -243,7 +243,23 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APB}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -280,6 +280,8 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1
#define SOC_SPI_SUPPORT_CLK_APB 1
#define SOC_SPI_SUPPORT_CLK_XTAL 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,

View File

@ -735,6 +735,18 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_XTAL
bool
default y
config SOC_SPI_SUPPORT_CLK_PLL_F80M
bool
default y
config SOC_SPI_SUPPORT_CLK_RC_FAST
bool
default y
config SOC_MEMSPI_IS_INDEPENDENT config SOC_MEMSPI_IS_INDEPENDENT
bool bool
default y default y

View File

@ -286,7 +286,25 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM///////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_80M as SPI source clock */
SPI_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_80M as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -333,6 +333,9 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1
#define SOC_SPI_SUPPORT_CLK_XTAL 1
#define SOC_SPI_SUPPORT_CLK_PLL_F80M 1
#define SOC_SPI_SUPPORT_CLK_RC_FAST 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,

View File

@ -555,6 +555,10 @@ config SOC_SPI_SUPPORT_CONTINUOUS_TRANS
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_PLL_F48M
bool
default y
config SOC_MEMSPI_IS_INDEPENDENT config SOC_MEMSPI_IS_INDEPENDENT
bool bool
default y default y

View File

@ -320,7 +320,24 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_PLL_F48M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F48M, /*!< Select PLL_48M as SPI source clock */
SPI_CLK_SRC_PLL_F48M = SOC_MOD_CLK_PLL_F48M, /*!< Select PLL_48M as SPI source clock */
SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -312,6 +312,7 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
//#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 //TODO: IDF-6247 //#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 //TODO: IDF-6247
#define SOC_SPI_SUPPORT_CLK_PLL_F48M 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,

View File

@ -579,6 +579,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_AHB
bool
default y
config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT
bool bool
default y default y

View File

@ -249,7 +249,22 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_AHB}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_AHB, /*!< Select AHB as SPI source clock */
SPI_CLK_SRC_AHB = SOC_MOD_CLK_AHB, /*!< Select AHB as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -287,6 +287,7 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1
#define SOC_SPI_SUPPORT_CLK_AHB 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,

View File

@ -607,6 +607,10 @@ config SOC_SPI_SUPPORT_CONTINUOUS_TRANS
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_APB
bool
default y
config SOC_SPI_SUPPORT_SLAVE_HD_VER2 config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y

View File

@ -260,7 +260,22 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select XTAL as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -264,6 +264,7 @@
#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_CLK_APB 1
/// The SPI Slave half duplex mode has been updated greatly in ESP32-S2 /// The SPI Slave half duplex mode has been updated greatly in ESP32-S2
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1

View File

@ -719,6 +719,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_APB
bool
default y
config SOC_SPI_SUPPORT_CLK_XTAL
bool
default y
config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT
bool bool
default y default y

View File

@ -289,7 +289,23 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t; } soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////SPI////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SPI
*/
#define SOC_SPI_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL}
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
} soc_periph_spi_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/** /**
* @brief Array initializer for all supported clock sources of SDM * @brief Array initializer for all supported clock sources of SDM

View File

@ -291,6 +291,8 @@
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1
#define SOC_SPI_SUPPORT_CLK_APB 1
#define SOC_SPI_SUPPORT_CLK_XTAL 1
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;}) #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;})

View File

@ -512,10 +512,10 @@ The main parameter that determines the transfer speed for large transactions is
Transaction Duration Transaction Duration
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42"} {IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42", esp32c6="34"}
{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17"} {IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17", esp32c6="17"}
{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40"} {IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32"}
{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15"} {IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15"}
Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction. Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction.
@ -534,7 +534,11 @@ Typical transaction duration for one byte of data are given below.
SPI Clock Frequency SPI Clock Frequency
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
The driver support setting an SPI peripheral to different clock frequencies. Actual clock frequency may not be exactly equal to the number you set, it will be re-calculated by the driver to the nearest hardware compatible number, you can call :cpp:func:`spi_device_get_actual_freq` to get the actual frequency computed by driver.
Clock source of the GPSPI peripherals can be selected by setting :cpp:member:`spi_device_handle_t::cfg::clock_source`. You can refer to :cpp:type:`spi_clock_source_t` to know the supported clock sources.
By default driver will set :cpp:member:`spi_device_handle_t::cfg::clock_source` to `SPI_CLK_SRC_DEFAULT`. This usually stands for the highest frequency among GPSPI clock sources. Its value will be different among chips.
Actual clock frequency of a device may not be exactly equal to the number you set, it will be re-calculated by the driver to the nearest hardware compatible number, and not larger than the clock frequency of the clock source. You can call :cpp:func:`spi_device_get_actual_freq` or use :cpp:member:`spi_device_handle_t::real_clk_freq_hz` directly to know the actual frequency computed by the driver.
Theoretical maximum transfer speed of Write or Read phase can be calculated according to the table below: Theoretical maximum transfer speed of Write or Read phase can be calculated according to the table below:

View File

@ -47,3 +47,14 @@ Peripherals
- ``dac_digi_deinit`` is replaced by :cpp:func:`dac_continuous_del_channels`. - ``dac_digi_deinit`` is replaced by :cpp:func:`dac_continuous_del_channels`.
- ``dac_digi_start``, ``dac_digi_fifo_reset`` and ``dac_digi_reset`` are merged into :cpp:func:`dac_continuous_enable`. - ``dac_digi_start``, ``dac_digi_fifo_reset`` and ``dac_digi_reset`` are merged into :cpp:func:`dac_continuous_enable`.
- ``dac_digi_stop`` is replaced by :cpp:func:`dac_continuous_disable`. - ``dac_digi_stop`` is replaced by :cpp:func:`dac_continuous_disable`.
.. only:: SOC_GPSPI_SUPPORTED
GPSPI
-----
Following items are deprecated. Since IDF v5.1, GPSPI clock source is configurable.
- ``spi_get_actual_clock`` is deprecated, you should use :cpp:func:`spi_device_get_actual_freq` instead.
- ``SPI_MASTER_FREQ_nM`` macros are deprecated, these macros are no longer guaranteed to be accurate, as clock source may not be APB. By default, using these macros will generate deprecation warnings. You can suppress the warnings by enabling the Kconfig option :ref:`CONFIG_SPI_SUPPRESS_FREQ_MACRO_DEPRECATE_WARN`.

View File

@ -20,3 +20,15 @@ typedef enum {
SPI3_HOST=2, ///< SPI3 SPI3_HOST=2, ///< SPI3
SPI_HOST_MAX=3, ///< invalid host value SPI_HOST_MAX=3, ///< invalid host value
} spi_host_device_t; } spi_host_device_t;
/**
* @brief Type of SPI clock source.
*/
typedef enum {
SPI_CLK_SRC_DEFAULT, /*!< Select PLL as SPI source clock */
SPI_CLK_SRC_PLL_F40M, /*!< Select PLL as SPI source clock */
SPI_CLK_SRC_PLL_F80M, /*!< Select PLL as SPI source clock */
SPI_CLK_SRC_APB, /*!< Select APB as SPI source clock */
SPI_CLK_SRC_XTAL, /*!< Select XTAL as SPI source clock */
SPI_CLK_SRC_RC_FAST, /*!< Select RC_FAST as SPI source clock */
} spi_clock_source_t;