From b20c156ae6fe78e1943dfd3e83a8002aedefa8cd Mon Sep 17 00:00:00 2001 From: wanlei Date: Wed, 4 Jan 2023 11:20:19 +0800 Subject: [PATCH 1/2] spi_master: update spi performance test resulte for C6 --- .../idf_test/include/esp32c6/idf_performance_target.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/idf_test/include/esp32c6/idf_performance_target.h b/components/idf_test/include/esp32c6/idf_performance_target.h index 809f2827b1b..ee85593cde3 100644 --- a/components/idf_test/include/esp32c6/idf_performance_target.h +++ b/components/idf_test/include/esp32c6/idf_performance_target.h @@ -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 */ @@ -15,7 +15,7 @@ #define IDF_PERFORMANCE_MAX_ECDSA_P192_VERIFY_OP 18000 #define IDF_PERFORMANCE_MAX_ECDSA_P256_VERIFY_OP 27000 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 45 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 40 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 115 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 110 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 34 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 17 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 32 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 From 184145817c13d28eb1fbe5f7345cd155a6d79ac6 Mon Sep 17 00:00:00 2001 From: wanlei Date: Wed, 18 Jan 2023 10:56:25 +0800 Subject: [PATCH 2/2] spi_master: add feature spi periph clk source selectable --- components/driver/Kconfig | 9 ++ components/driver/include/driver/spi_master.h | 26 ++++-- components/driver/spi_master.c | 36 +++++--- .../include/test_spi_utils.h | 26 +++--- .../spi/master/main/test_spi_master.c | 85 ++++++++++++++----- .../test_apps/spi/param/main/test_spi_param.c | 82 +++++++++--------- .../spi/slave_hd/main/test_spi_slave_hd.c | 6 +- components/hal/esp32/include/hal/spi_ll.h | 14 ++- components/hal/esp32c2/include/hal/spi_ll.h | 21 ++++- components/hal/esp32c3/include/hal/spi_ll.h | 21 ++++- components/hal/esp32c6/include/hal/spi_ll.h | 27 +++++- components/hal/esp32h4/include/hal/spi_ll.h | 14 ++- components/hal/esp32s2/include/hal/spi_ll.h | 14 ++- components/hal/esp32s3/include/hal/spi_ll.h | 21 ++++- components/hal/include/hal/spi_hal.h | 5 +- components/hal/include/hal/spi_types.h | 9 +- components/hal/spi_hal.c | 17 ++-- components/hal/spi_hal_iram.c | 1 + .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32/include/soc/clk_tree_defs.h | 15 ++++ components/soc/esp32/include/soc/soc_caps.h | 2 + .../esp32c2/include/soc/Kconfig.soc_caps.in | 8 ++ .../soc/esp32c2/include/soc/clk_tree_defs.h | 17 ++++ components/soc/esp32c2/include/soc/soc_caps.h | 2 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 8 ++ .../soc/esp32c3/include/soc/clk_tree_defs.h | 18 +++- components/soc/esp32c3/include/soc/soc_caps.h | 2 + .../esp32c6/include/soc/Kconfig.soc_caps.in | 12 +++ .../soc/esp32c6/include/soc/clk_tree_defs.h | 20 ++++- components/soc/esp32c6/include/soc/soc_caps.h | 3 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h2/include/soc/clk_tree_defs.h | 19 ++++- components/soc/esp32h2/include/soc/soc_caps.h | 1 + .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h4/include/soc/clk_tree_defs.h | 17 +++- components/soc/esp32h4/include/soc/soc_caps.h | 1 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s2/include/soc/clk_tree_defs.h | 17 +++- components/soc/esp32s2/include/soc/soc_caps.h | 1 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 ++ .../soc/esp32s3/include/soc/clk_tree_defs.h | 18 +++- components/soc/esp32s3/include/soc/soc_caps.h | 2 + .../api-reference/peripherals/spi_master.rst | 14 +-- .../release-5.x/5.1/peripherals.rst | 11 +++ tools/mocks/hal/include/hal/spi_types.h | 12 +++ 45 files changed, 541 insertions(+), 137 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 8e40c8b5db8..42927355e01 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -111,6 +111,15 @@ menu "Driver Configurations" Also you can forbid the ISR being disabled during flash writing 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 menu "TWAI Configuration" diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index d6f42629ac8..ea8f40de83e 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -8,12 +8,25 @@ #include "esp_err.h" #include "freertos/FreeRTOS.h" +#include "hal/spi_types.h" //for spi_bus_initialization funcions. to be back-compatible #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). - * 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). */ +#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_9M (APB_CLK_FREQ/9) ///< 8.89MHz #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_40M (APB_CLK_FREQ/2) ///< 40MHz #define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz +#endif //!CONFIG_SPI_SUPPRESS_FREQ_MACRO_DEPRECATE_WARN + #ifdef __cplusplus extern "C" { @@ -63,8 +78,9 @@ typedef struct { - 2: (1, 0) - 3: (1, 1) */ - 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. + 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 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) int clock_speed_hz; ///< Clock speed, divisors of 80MHz, in Hz. See ``SPI_MASTER_FREQ_*``. int input_delay_ns; /**< Maximum data valid time of slave. The time required between SCLK and MISO @@ -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. */ -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. diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 74cbaff8712..377a0294c3a 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -113,7 +113,7 @@ We have two bits to control the interrupt: #include #include "esp_private/spi_common_internal.h" #include "driver/spi_master.h" - +#include "clk_tree.h" #include "esp_log.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -121,8 +121,6 @@ We have two bits to control the interrupt: #include "driver/gpio.h" #include "hal/spi_hal.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; @@ -156,6 +154,7 @@ typedef struct { struct spi_device_t { int id; + int real_clk_freq_hz; QueueHandle_t trans_queue; QueueHandle_t ret_queue; 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) { +#ifdef CONFIG_IDF_TARGET_ESP32 int timing_dummy; 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 (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) { +#ifdef CONFIG_IDF_TARGET_ESP32 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]; 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); - uint32_t apb_clk_freq_hz = esp_clk_apb_freq(); - assert((apb_clk_freq_hz == 80 * 1000 * 1000) || (apb_clk_freq_hz == 40 * 1000 * 1000) || (apb_clk_freq_hz == 48 * 1000 * 1000)); - SPI_CHECK((dev_config->clock_speed_hz > 0) && (dev_config->clock_speed_hz <= apb_clk_freq_hz) , "invalid sclk speed", ESP_ERR_INVALID_ARG); + uint32_t clock_source_hz; + 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 <= clock_source_hz), "invalid sclk speed", ESP_ERR_INVALID_ARG); #ifdef CONFIG_IDF_TARGET_ESP32 //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. @@ -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 use_gpio = !(bus_attr->flags & SPICOMMON_BUSFLAG_IOMUX_PINS); 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, .no_compensate = no_compensate, + .clk_src_hz = clock_source_hz, .expected_freq = dev_config->clock_speed_hz, .duty_cycle = duty_cycle, .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; int freq; 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); //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. memcpy(&dev->cfg, dev_config, sizeof(spi_device_interface_config_t)); 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. //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; } - int dev_required_freq = ((spi_device_t*)handle)->cfg.clock_speed_hz; - 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); - + *freq_khz = handle->real_clk_freq_hz / 1000; 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; #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); #endif //Send to queue and invoke the ISR. diff --git a/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h b/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h index 1daf149e27f..538c4638fce 100644 --- a/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h +++ b/components/driver/test_apps/components/test_driver_utils/include/test_spi_utils.h @@ -145,25 +145,25 @@ #define TV_WITH_ESP_SLAVE (TV_INT_CONNECT+WIRE_DELAY) //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_SYNC SPI_MASTER_FREQ_40M +#define ESP_SPI_SLAVE_MAX_FREQ 20 * 1000 * 1000 +#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 PSET_NAME_LEN 30 ///< length of each param set name //test low frequency, high frequency until freq limit for worst case (both GPIO) #define TEST_FREQ_DEFAULT(){ \ - 1*1000*1000, \ - SPI_MASTER_FREQ_8M , \ - SPI_MASTER_FREQ_9M , \ - SPI_MASTER_FREQ_10M, \ - SPI_MASTER_FREQ_11M, \ - SPI_MASTER_FREQ_13M, \ - SPI_MASTER_FREQ_16M, \ - SPI_MASTER_FREQ_20M, \ - SPI_MASTER_FREQ_26M, \ - SPI_MASTER_FREQ_40M, \ - SPI_MASTER_FREQ_80M, \ + 1 * 1000 * 1000, \ + 8 * 1000 * 1000, \ + 9 * 1000 * 1000, \ + 10 * 1000 * 1000, \ + 11 * 1000 * 1000, \ + 13 * 1000 * 1000, \ + 16 * 1000 * 1000, \ + 20 * 1000 * 1000, \ + 26 * 1000 * 1000, \ + 40 * 1000 * 1000, \ + 80 * 1000 * 1000, \ 0,\ } diff --git a/components/driver/test_apps/spi/master/main/test_spi_master.c b/components/driver/test_apps/spi/master/main/test_spi_master.c index afcdec4a4e3..e1b1db6c7f0 100644 --- a/components/driver/test_apps/spi/master/main/test_spi_master.c +++ b/components/driver/test_apps/spi/master/main/test_spi_master.c @@ -19,6 +19,7 @@ #include "esp_private/spi_common_internal.h" #include "esp_private/esp_clk.h" #include "esp_heap_caps.h" +#include "clk_tree.h" #include "esp_log.h" #include "test_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 #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; @@ -37,6 +38,7 @@ static void check_spi_pre_n_for(int clk, int pre, int n) .command_bits = 0, .address_bits = 0, .dummy_bits = 0, + .clock_source = clock_source, .clock_speed_hz = clk, .duty_cycle_pos = 128, .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)); } -#define TEST_CLK_TIMES 8 /** * In this test, SPI Clock Calculation: * 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: * {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_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} } +#define TEST_CLK_TIMES 8 +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]") { - spi_bus_config_t buscfg = { - .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 - }; + spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG(); 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 (apb_freq_hz == (80 * 1000 * 1000)) { - uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_80; - 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]); - } - } else { - TEST_ASSERT(apb_freq_hz == (40 * 1000 * 1000)); - uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_40; - 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]); - } +#if SOC_SPI_SUPPORT_CLK_PLL_F40M + clk_tree_src_get_freq_hz(SPI_CLK_SRC_PLL_F40M, CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz); + 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++) { + 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]); + } +#endif + +#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++) { + 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)); } diff --git a/components/driver/test_apps/spi/param/main/test_spi_param.c b/components/driver/test_apps/spi/param/main/test_spi_param.c index 5be8c2cd42a..cdd201f498b 100644 --- a/components/driver/test_apps/spi/param/main/test_spi_param.c +++ b/components/driver/test_apps/spi/param/main/test_spi_param.c @@ -235,7 +235,7 @@ static spitest_param_set_t timing_pgroup[] = { #if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) { .pset_name = "FULL_DUP, MASTER IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = true, .slave_iomux = false, @@ -243,7 +243,7 @@ static spitest_param_set_t timing_pgroup[] = { }, { .pset_name = "FULL_DUP, SLAVE IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = false, .slave_iomux = true, @@ -252,7 +252,7 @@ static spitest_param_set_t timing_pgroup[] = { #endif { .pset_name = "FULL_DUP, BOTH GPIO", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, - .master_limit = SPI_MASTER_FREQ_10M, + .master_limit = 10 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = false, .slave_iomux = false, @@ -316,16 +316,16 @@ static spitest_param_set_t timing_pgroup[] = { TEST_SPI_LOCAL(TIMING, timing_pgroup) /************ Mode Test ***********************************************/ -#define FREQ_LIMIT_MODE SPI_MASTER_FREQ_16M +#define FREQ_LIMIT_MODE 16 * 1000 * 1000 static int test_freq_mode_local[]={ - 1*1000*1000, - SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge - SPI_MASTER_FREQ_13M, - SPI_MASTER_FREQ_16M, - SPI_MASTER_FREQ_20M, - SPI_MASTER_FREQ_26M, - SPI_MASTER_FREQ_40M, - 0, + 1 * 1000 * 1000, + 9 * 1000 * 1000, //maximum freq MISO stable before next latch edge + 13 * 1000 * 1000, + 16 * 1000 * 1000, + 20 * 1000 * 1000, + 26 * 1000 * 1000, + 40 * 1000 * 1000, + 0, }; //signals are not fed to peripherals through iomux if the functions are not selected to iomux @@ -358,7 +358,7 @@ static int test_freq_mode_local[]={ static spitest_param_set_t mode_pgroup[] = { { .pset_name = "Mode 0", .freq_list = test_freq_mode_local, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 0, .master_iomux = false, @@ -367,8 +367,8 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 1", .freq_list = test_freq_mode_local, - .freq_limit = SPI_MASTER_FREQ_26M, - .master_limit = SPI_MASTER_FREQ_13M, + .freq_limit = 26 * 1000 * 1000, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 1, .master_iomux = false, @@ -377,7 +377,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 2", .freq_list = test_freq_mode_local, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 2, .master_iomux = false, @@ -386,8 +386,8 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 3", .freq_list = test_freq_mode_local, - .freq_limit = SPI_MASTER_FREQ_26M, - .master_limit = SPI_MASTER_FREQ_13M, + .freq_limit = 26 * 1000 * 1000, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 3, .master_iomux = false, @@ -396,7 +396,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 0, DMA", .freq_list = test_freq_mode_local, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 0, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -407,8 +407,8 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 1, DMA", .freq_list = test_freq_mode_local, - .freq_limit = SPI_MASTER_FREQ_26M, - .master_limit = SPI_MASTER_FREQ_13M, + .freq_limit = 26 * 1000 * 1000, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 1, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -419,7 +419,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 2, DMA", .freq_list = test_freq_mode_local, - .master_limit = SPI_MASTER_FREQ_13M, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 2, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -430,8 +430,8 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 3, DMA", .freq_list = test_freq_mode_local, - .freq_limit = SPI_MASTER_FREQ_26M, - .master_limit = SPI_MASTER_FREQ_13M, + .freq_limit = 26 * 1000 * 1000, + .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 3, .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[] = { { .pset_name = "FULL_DUP, BOTH IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ, - .master_limit = SPI_MASTER_FREQ_16M, + .master_limit = 16 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux= true, .slave_iomux = true, @@ -915,7 +915,7 @@ static spitest_param_set_t timing_conf[] = { }, { .pset_name = "FULL_DUP, MASTER IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ, - .master_limit = SPI_MASTER_FREQ_11M, + .master_limit = 11 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = true, .slave_iomux = false, @@ -923,7 +923,7 @@ static spitest_param_set_t timing_conf[] = { }, { .pset_name = "FULL_DUP, SLAVE IOMUX", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ, - .master_limit = SPI_MASTER_FREQ_11M, + .master_limit = 11 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = false, .slave_iomux = true, @@ -931,7 +931,7 @@ static spitest_param_set_t timing_conf[] = { }, { .pset_name = "FULL_DUP, BOTH GPIO", .freq_limit = ESP_SPI_SLAVE_MAX_FREQ, - .master_limit = SPI_MASTER_FREQ_9M, + .master_limit = 9 * 1000 * 1000, .dup = FULL_DUPLEX, .master_iomux = false, .slave_iomux = false, @@ -997,25 +997,25 @@ static spitest_param_set_t timing_conf[] = { TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "") /************ 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 #define DELAY_HCLK_UNTIL_7M 12.5*3 static int test_freq_mode_ms[]={ - 100*1000, - 6*1000*1000, - 7*1000*1000, - SPI_MASTER_FREQ_8M, //maximum freq MISO stable before next latch edge - SPI_MASTER_FREQ_9M, //maximum freq MISO stable before next latch edge - SPI_MASTER_FREQ_10M, - SPI_MASTER_FREQ_11M, - SPI_MASTER_FREQ_13M, - SPI_MASTER_FREQ_16M, - SPI_MASTER_FREQ_20M, - 0, + 100 * 1000, + 6 * 1000 * 1000, + 7 * 1000 * 1000, + 8 * 1000 * 1000, //maximum freq MISO stable before next latch edge + 9 * 1000 * 1000, //maximum freq MISO stable before next latch edge + 10 * 1000 * 1000, + 11 * 1000 * 1000, + 13 * 1000 * 1000, + 16 * 1000 * 1000, + 20 * 1000 * 1000, + 0, }; static int test_freq_20M_only[]={ - SPI_MASTER_FREQ_20M, + 20 * 1000 * 1000, 0, }; diff --git a/components/driver/test_apps/spi/slave_hd/main/test_spi_slave_hd.c b/components/driver/test_apps/spi/slave_hd/main/test_spi_slave_hd.c index 971f794b4c9..10b6a084239 100644 --- a/components/driver/test_apps/spi/slave_hd/main/test_spi_slave_hd.c +++ b/components/driver/test_apps/spi/slave_hd/main/test_spi_slave_hd.c @@ -444,9 +444,9 @@ static const ptest_func_t hd_test_func = { static int test_freq_hd[] = { // 100*1000, - // SPI_MASTER_FREQ_10M, //maximum freq MISO stable before next latch edge - // SPI_MASTER_FREQ_20M, //maximum freq MISO stable before next latch edge - SPI_MASTER_FREQ_40M, //maximum freq MISO stable before next latch edge + // 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge + // 20 * 1000 * 1000, //maximum freq MISO stable before next latch edge + 40 * 1000 * 1000, //maximum freq MISO stable before next latch edge 0, }; diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index cf09b6e94f4..8b65624bf00 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -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) /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 24) @@ -56,6 +54,18 @@ typedef spi_dev_t spi_dma_dev_t; /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32c2/include/hal/spi_ll.h b/components/hal/esp32c2/include/hal/spi_ll.h index ca67e3960a1..377da887587 100644 --- a/components/hal/esp32c2/include/hal/spi_ll.h +++ b/components/hal/esp32c2/include/hal/spi_ll.h @@ -36,8 +36,6 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 18) @@ -92,6 +90,25 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index 78b58de6c4f..9cdc2c344a9 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -36,8 +36,6 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 18) @@ -92,6 +90,25 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32c6/include/hal/spi_ll.h b/components/hal/esp32c6/include/hal/spi_ll.h index d8115a0b29e..3a97b192ca9 100644 --- a/components/hal/esp32c6/include/hal/spi_ll.h +++ b/components/hal/esp32c6/include/hal/spi_ll.h @@ -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 */ @@ -37,8 +37,6 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 18) @@ -93,6 +91,29 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32h4/include/hal/spi_ll.h b/components/hal/esp32h4/include/hal/spi_ll.h index 22e5eb5562b..4ab56b97a4c 100644 --- a/components/hal/esp32h4/include/hal/spi_ll.h +++ b/components/hal/esp32h4/include/hal/spi_ll.h @@ -36,8 +36,6 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 18) @@ -92,6 +90,18 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index eb50b6f5be5..ab83769b00a 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -39,8 +39,6 @@ extern "C" { #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 #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_DATA_MAX_BIT_LEN (1 << 23) @@ -102,6 +100,18 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index e210a76f8ef..2477847af28 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -38,8 +38,6 @@ extern "C" { /// 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)) -/// 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_DATA_MAX_BIT_LEN (1 << 18) @@ -94,6 +92,25 @@ typedef enum { /*------------------------------------------------------------------------------ * 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). * diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index 8950e26dac5..81477b100cb 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -36,7 +36,6 @@ * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration */ 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 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 @@ -56,6 +55,7 @@ typedef struct { */ typedef struct { 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_miso_delay; ///< Extra miso delay clocks to compensate the timing } 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. * + * @param source_freq_hz Clock freq of selected clock source for SPI in Hz. * @param eff_clk Actual SPI clock frequency * @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 @@ -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 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. diff --git a/components/hal/include/hal/spi_types.h b/components/hal/include/hal/spi_types.h index 05566d7aedc..e9db6e0ffdc 100644 --- a/components/hal/include/hal/spi_types.h +++ b/components/hal/include/hal/spi_types.h @@ -9,6 +9,7 @@ #include #include "esp_attr.h" #include "esp_bit_defs.h" +#include "soc/clk_tree_defs.h" #include "soc/soc_caps.h" #include "sdkconfig.h" @@ -25,10 +26,10 @@ typedef enum { SPI_HOST_MAX, ///< invalid host value } spi_host_device_t; -typedef enum { - SPI_CLK_APB, ///< Select APB as the source clock - SPI_CLK_XTAL ///< Select XTAL as the source clock -} spi_clock_source_t; +/** + * @brief Type of SPI clock source. + */ +typedef soc_periph_spi_clk_src_t spi_clock_source_t; /// SPI Events typedef enum { diff --git a/components/hal/spi_hal.c b/components/hal/spi_hal.c index 0ec85d8fdbc..75df2df56cf 100644 --- a/components/hal/spi_hal.c +++ b/components/hal/spi_hal.c @@ -10,6 +10,7 @@ #include "hal/log.h" #include "hal/assert.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. #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; - int clk_src_freq_hz = timing_param->clk_src_hz; - 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); + 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); //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. - 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 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); } -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 - 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; //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); } +#ifdef CONFIG_IDF_TARGET_ESP32 +//TODO: IDF-6578 int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns) { 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); } +#endif diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index a8432402264..8a9e38f122c 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -37,6 +37,7 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de #endif 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_set_clk_source(hw, dev->timing_conf.clock_source); //Configure bit order spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst); spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst); diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index d4884ec25da..fdba1a66e4b 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -559,6 +559,10 @@ config SOC_SPI_MAX_CS_NUM int default 3 +config SOC_SPI_SUPPORT_CLK_APB + bool + default y + config SOC_SPI_MAXIMUM_BUFFER_SIZE int default 64 diff --git a/components/soc/esp32/include/soc/clk_tree_defs.h b/components/soc/esp32/include/soc/clk_tree_defs.h index 63506e28d74..e238ea9660e 100644 --- a/components/soc/esp32/include/soc/clk_tree_defs.h +++ b/components/soc/esp32/include/soc/clk_tree_defs.h @@ -272,6 +272,21 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, } 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////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index c9da452ffef..f0c8ceed685 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -275,6 +275,8 @@ #define SOC_SPI_PERIPH_CS_NUM(i) 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_MAX_PRE_DIVIDER 8192 diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index e35ad85ced2..e85589a013e 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -391,6 +391,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool 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 bool default y diff --git a/components/soc/esp32c2/include/soc/clk_tree_defs.h b/components/soc/esp32c2/include/soc/clk_tree_defs.h index 6954fea0cba..1c18af9d9fc 100644 --- a/components/soc/esp32c2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c2/include/soc/clk_tree_defs.h @@ -187,6 +187,23 @@ typedef enum { /////////////////////////////////////////////////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 */ diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index a2f8eb473ba..b711e031951 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -200,6 +200,8 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 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 // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index b829bd5ab00..c338a4d2c38 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -603,6 +603,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool 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 bool default y diff --git a/components/soc/esp32c3/include/soc/clk_tree_defs.h b/components/soc/esp32c3/include/soc/clk_tree_defs.h index 3c906fce580..c93661bf15c 100644 --- a/components/soc/esp32c3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c3/include/soc/clk_tree_defs.h @@ -243,7 +243,23 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, } 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 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 725174e1869..50852958e50 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -280,6 +280,8 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 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 // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index c8d25e64e51..ece9e9af8e8 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -735,6 +735,18 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool 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 bool default y diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index 16243140eba..2af236c669c 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -286,7 +286,25 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, } 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 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index b8ce95ff0e9..143eae26371 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -333,6 +333,9 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 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 // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 4b54431c593..7bd81d9d5b4 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -555,6 +555,10 @@ config SOC_SPI_SUPPORT_CONTINUOUS_TRANS bool default y +config SOC_SPI_SUPPORT_CLK_PLL_F48M + bool + default y + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index d584e562788..05124dfe9a4 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -320,7 +320,24 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, } 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 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index a21f3ff5438..88eae0eb071 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -312,6 +312,7 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 //#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 // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index d44f60029b1..b31de41430b 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -579,6 +579,10 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y +config SOC_SPI_SUPPORT_CLK_AHB + bool + default y + config SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT bool default y diff --git a/components/soc/esp32h4/include/soc/clk_tree_defs.h b/components/soc/esp32h4/include/soc/clk_tree_defs.h index 9c775913950..dbf97ea45d7 100644 --- a/components/soc/esp32h4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h4/include/soc/clk_tree_defs.h @@ -249,7 +249,22 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, } 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 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index e4924be5e45..aa0f1105413 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -287,6 +287,7 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_CLK_AHB 1 // Peripheral supports DIO, DOUT, QIO, or QOUT // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 7c616f85253..bb4a9a113d5 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -607,6 +607,10 @@ config SOC_SPI_SUPPORT_CONTINUOUS_TRANS bool default y +config SOC_SPI_SUPPORT_CLK_APB + bool + default y + config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool default y diff --git a/components/soc/esp32s2/include/soc/clk_tree_defs.h b/components/soc/esp32s2/include/soc/clk_tree_defs.h index 3af8939736b..94affc84f55 100644 --- a/components/soc/esp32s2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s2/include/soc/clk_tree_defs.h @@ -260,7 +260,22 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, } 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 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index f345f67f090..5c8456a5516 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -264,6 +264,7 @@ #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 #define SOC_SPI_SUPPORT_CD_SIG 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 #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index a6425879fda..ab5ccebdb8a 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -719,6 +719,14 @@ config SOC_SPI_SUPPORT_SLAVE_HD_VER2 bool 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 bool default y diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index 58d5c891a6c..13186e28d30 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -289,7 +289,23 @@ typedef enum { I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, } 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 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 28deb82da3d..75d3182dbaa 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -291,6 +291,8 @@ #define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 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 #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;}) diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index be2ad9f9019..6fdeef9b6e1 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -512,10 +512,10 @@ The main parameter that determines the transfer speed for large transactions is Transaction Duration ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42"} -{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17"} -{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40"} -{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15"} +{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", esp32c6="17"} +{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", 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. @@ -534,7 +534,11 @@ Typical transaction duration for one byte of data are given below. 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: diff --git a/docs/en/migration-guides/release-5.x/5.1/peripherals.rst b/docs/en/migration-guides/release-5.x/5.1/peripherals.rst index e0d12f4e43a..e6a37b12961 100644 --- a/docs/en/migration-guides/release-5.x/5.1/peripherals.rst +++ b/docs/en/migration-guides/release-5.x/5.1/peripherals.rst @@ -47,3 +47,14 @@ Peripherals - ``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_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`. diff --git a/tools/mocks/hal/include/hal/spi_types.h b/tools/mocks/hal/include/hal/spi_types.h index e446de899fd..42b59406f7d 100644 --- a/tools/mocks/hal/include/hal/spi_types.h +++ b/tools/mocks/hal/include/hal/spi_types.h @@ -20,3 +20,15 @@ typedef enum { SPI3_HOST=2, ///< SPI3 SPI_HOST_MAX=3, ///< invalid host value } 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;