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 cf77f9254a..08bc9835bd 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -74,7 +74,7 @@ #define ESP_SPI_SLAVE_TV (12.5*3.5) #define WIRE_DELAY 12.5 -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32H4 #define SLAVE_IOMUX_PIN_MISO -1 #define SLAVE_IOMUX_PIN_MOSI -1 #define SLAVE_IOMUX_PIN_SCLK -1 @@ -82,7 +82,11 @@ #define SLAVE_IOMUX_PIN_WP -1 #define SLAVE_IOMUX_PIN_HD -1 +#if CONFIG_IDF_TARGET_ESP32H4 +#define UNCONNECTED_PIN 27 +#else #define UNCONNECTED_PIN 41 +#endif #define INPUT_ONLY_PIN 46 #define GPIO_DELAY 0 #define ESP_SPI_SLAVE_TV 0 @@ -113,22 +117,6 @@ #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, \ - 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,\ - } - //default bus config for tests #define SPI_BUS_TEST_DEFAULT_CONFIG() {\ .miso_io_num=PIN_NUM_MISO, \ @@ -234,9 +222,6 @@ typedef struct { slave_txdata_t slave_trans[MAX_TEST_SIZE]; } spitest_context_t; -// fill default value of spitest_param_set_t -void spitest_def_param(void* arg); - // functions for slave task esp_err_t init_slave_context(spi_slave_task_context_t *context, spi_host_device_t host); void deinit_slave_context(spi_slave_task_context_t *context); diff --git a/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c b/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c index a5d6c04e83..3329865de8 100644 --- a/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c +++ b/components/driver/test_apps/components/test_driver_utils/test_spi_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,8 +12,6 @@ #include "hal/spi_ll.h" #include "esp_rom_gpio.h" -int test_freq_default[] = TEST_FREQ_DEFAULT(); - const char MASTER_TAG[] = "test_master"; const char SLAVE_TAG[] = "test_slave"; @@ -34,15 +32,6 @@ DRAM_ATTR uint8_t spitest_slave_send[] = { 0xda, }; -void spitest_def_param(void* arg) -{ - spitest_param_set_t *param_set = (spitest_param_set_t*)arg; - param_set->test_size = 8; - if (param_set->freq_list == NULL) { - param_set->freq_list = test_freq_default; - } -} - /********************************************************************************** * functions for slave task *********************************************************************************/ diff --git a/components/esp_driver_sdspi/test_apps/sdspi/README.md b/components/esp_driver_sdspi/test_apps/sdspi/README.md index 15bfc62bf3..44f3780f1d 100644 --- a/components/esp_driver_sdspi/test_apps/sdspi/README.md +++ b/components/esp_driver_sdspi/test_apps/sdspi/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_spi/include/esp_private/spi_common_internal.h b/components/esp_driver_spi/include/esp_private/spi_common_internal.h index 4383e5d5c0..66b393b26c 100644 --- a/components/esp_driver_spi/include/esp_private/spi_common_internal.h +++ b/components/esp_driver_spi/include/esp_private/spi_common_internal.h @@ -80,6 +80,23 @@ typedef struct { /// Destructor called when a bus is deinitialized. typedef esp_err_t (*spi_destroy_func_t)(void*); +/** + * @brief Allocate a SPI bus + * + * @param host_id SPI host ID + * @param name Name of the bus + * @return ESP_OK on success, ESP_ERR_NO_MEM if no memory is available + */ +esp_err_t spicommon_bus_alloc(spi_host_device_t host_id, const char *name); + +/** + * @brief Free a SPI bus + * + * @param host_id SPI host ID + * @return ESP_OK on success, ESP_ERR_INVALID_STATE if the bus is not allocated + */ +esp_err_t spicommon_bus_free(spi_host_device_t host_id); + /** * @brief Alloc DMA channel for SPI * diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 488b52d100..be7152fa9a 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -29,6 +29,12 @@ #include "soc/dport_reg.h" #endif +#if SOC_PERIPH_CLK_CTRL_SHARED +#define SPI_COMMON_PERI_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define SPI_COMMON_PERI_CLOCK_ATOMIC() +#endif + #if CONFIG_SPI_MASTER_ISR_IN_IRAM || CONFIG_SPI_SLAVE_ISR_IN_IRAM #define SPI_COMMON_ISR_ATTR IRAM_ATTR #else @@ -87,6 +93,9 @@ esp_err_t spicommon_bus_alloc(spi_host_device_t host_id, const char *name) spicommon_periph_free(host_id); return ESP_ERR_NO_MEM; } + SPI_COMMON_PERI_CLOCK_ATOMIC() { + spi_ll_enable_clock(host_id, true); + } ctx->host_id = host_id; bus_ctx[host_id] = ctx; return ESP_OK; @@ -96,6 +105,9 @@ esp_err_t spicommon_bus_free(spi_host_device_t host_id) { assert(bus_ctx[host_id]); spicommon_periph_free(host_id); + SPI_COMMON_PERI_CLOCK_ATOMIC() { + spi_ll_enable_clock(host_id, false); + } free(bus_ctx[host_id]); bus_ctx[host_id] = NULL; return ESP_OK; diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index 762dc1418f..10dcbc9344 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -318,9 +318,6 @@ static esp_err_t spi_master_init_driver(spi_host_device_t host_id) } } - SPI_MASTER_PERI_CLOCK_ATOMIC() { - spi_ll_enable_clock(host_id, true); - } spi_hal_init(&host->hal, host_id); spi_hal_config_io_default_level(&host->hal, bus_attr->bus_cfg.data_io_default_level); @@ -406,7 +403,7 @@ static uint32_t s_spi_find_clock_src_pre_div(uint32_t src_freq, uint32_t target_ uint32_t total_div = src_freq / target_freq; // Loop the `div` to find a divisible value of `total_div` - for (uint32_t pre_div = min_div; pre_div <= total_div; pre_div += 2) { + for (uint32_t pre_div = min_div; pre_div <= MIN(total_div, SPI_LL_SRC_PRE_DIV_MAX); pre_div += 2) { if ((total_div % pre_div) || (total_div / pre_div) > SPI_LL_PERIPH_CLK_DIV_MAX) { continue; } @@ -1529,8 +1526,8 @@ static SPI_MASTER_ISR_ATTR spi_dma_desc_t *s_sct_setup_desc_anywhere(spi_dma_des { while (len) { int dmachunklen = len; - if (dmachunklen > LLDESC_MAX_NUM_PER_DESC) { - dmachunklen = LLDESC_MAX_NUM_PER_DESC; + if (dmachunklen > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { + dmachunklen = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; } if (is_rx) { //Receive needs DMA length rounded to next 32-bit boundary @@ -1557,7 +1554,7 @@ static SPI_MASTER_ISR_ATTR spi_dma_desc_t *s_sct_setup_desc_anywhere(spi_dma_des static SPI_MASTER_ISR_ATTR int s_sct_desc_get_required_num(uint32_t bytes_len) { - return (bytes_len + LLDESC_MAX_NUM_PER_DESC - 1) / LLDESC_MAX_NUM_PER_DESC; + return (bytes_len + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; } /*------------------------- * TX diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 3a83efd6a5..8ac42193bc 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -167,7 +167,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b SPI_CHECK(slave_config->post_trans_cb != NULL, "use feature flag 'SPI_SLAVE_NO_RETURN_RESULT' but no post_trans_cb function sets", ESP_ERR_INVALID_ARG); } - SPI_CHECK(spicommon_periph_claim(host, "spi slave"), "host already in use", ESP_ERR_INVALID_STATE); + SPI_CHECK(ESP_OK == spicommon_bus_alloc(host, "spi slave"), "host already in use", ESP_ERR_INVALID_STATE); // spi_slave_t contains atomic variable, memory must be allocated from internal memory spihost[host] = heap_caps_calloc(1, sizeof(spi_slave_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (spihost[host] == NULL) { @@ -355,7 +355,7 @@ esp_err_t spi_slave_free(spi_host_device_t host) #endif //CONFIG_PM_ENABLE free(spihost[host]); spihost[host] = NULL; - spicommon_periph_free(host); + spicommon_bus_free(host); return ESP_OK; } diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index 9877715cac..a07124b456 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -117,7 +117,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b SPIHD_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM) == 0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG); #endif - SPIHD_CHECK(spicommon_periph_claim(host_id, "slave_hd"), "host already in use", ESP_ERR_INVALID_STATE); + SPIHD_CHECK(ESP_OK == spicommon_bus_alloc(host_id, "slave_hd"), "host already in use", ESP_ERR_INVALID_STATE); // spi_slave_hd_slot_t contains atomic variable, memory must be allocated from internal memory spi_slave_hd_slot_t *host = heap_caps_calloc(1, sizeof(spi_slave_hd_slot_t), MALLOC_CAP_INTERNAL); if (host == NULL) { @@ -351,7 +351,7 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id) spicommon_bus_free_io_cfg(&host->bus_config, &host->gpio_reserve); spicommon_cs_free_io(host->cs_io_num, &host->gpio_reserve); - spicommon_periph_free(host_id); + spicommon_bus_free(host_id); free(host->dma_ctx->dmadesc_tx); free(host->dma_ctx->dmadesc_rx); free(host->hal.dmadesc_tx); @@ -756,7 +756,7 @@ esp_err_t s_spi_slave_hd_append_txdma(spi_slave_hd_slot_t *host, uint8_t *data, spi_slave_hd_hal_context_t *hal = &host->hal; //Check if there are enough available DMA descriptors for software to use - int num_required = (len + LLDESC_MAX_NUM_PER_DESC - 1) / LLDESC_MAX_NUM_PER_DESC; + int num_required = (len + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; int available_desc_num = hal->dma_desc_num - hal->tx_used_desc_cnt; if (num_required > available_desc_num) { return ESP_ERR_INVALID_STATE; @@ -797,7 +797,7 @@ esp_err_t s_spi_slave_hd_append_rxdma(spi_slave_hd_slot_t *host, uint8_t *data, spi_slave_hd_hal_context_t *hal = &host->hal; //Check if there are enough available dma descriptors for software to use - int num_required = (len + LLDESC_MAX_NUM_PER_DESC - 1) / LLDESC_MAX_NUM_PER_DESC; + int num_required = (len + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; int available_desc_num = hal->dma_desc_num - hal->rx_used_desc_cnt; if (num_required > available_desc_num) { return ESP_ERR_INVALID_STATE; diff --git a/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h b/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h index f8b6d67c47..5b5a0ba4d5 100644 --- a/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h +++ b/components/esp_driver_spi/test_apps/components/spi_bench_mark/include/spi_performance.h @@ -89,21 +89,17 @@ #define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 14 #elif CONFIG_IDF_TARGET_ESP32H21 -#if SOC_CLK_TREE_SUPPORTED -//TODO: [ESP32H21] IDF-11521 update perform data according to `TEST_CASE("spi_speed", "[spi]")` -//Also update this value in doc spi_master.rst:535 #define IDF_TARGET_MAX_SPI_CLK_FREQ 32*1000*1000 -#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 0 // need update to real_val + 3 -#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 0 // need update to real_val + 3 -#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 0 // need update to real_val + 3 -#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 0 // need update to real_val + 3 -#else -// Remove after SOC_CLK_TREE_SUPPORTED -#define IDF_TARGET_MAX_SPI_CLK_FREQ 32*1000*1000 -#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 1000 -#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 1000 -#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 1000 -#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 1000 -#endif +#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 60 +#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 32 +#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 55 +#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 26 + +#elif CONFIG_IDF_TARGET_ESP32H4 +#define IDF_TARGET_MAX_SPI_CLK_FREQ 24*1000*1000 +#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 70 +#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 35 +#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 60 +#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 25 #endif diff --git a/components/esp_driver_spi/test_apps/master/README.md b/components/esp_driver_spi/test_apps/master/README.md index 15bfc62bf3..44f3780f1d 100644 --- a/components/esp_driver_spi/test_apps/master/README.md +++ b/components/esp_driver_spi/test_apps/master/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c index d0b6f692b9..67f094bd62 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_master.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_master.c @@ -82,12 +82,13 @@ static void check_spi_pre_n_for(int clk, int pre, int n) */ #define TEST_CLK_TIMES 8 uint32_t clk_param_80m[TEST_CLK_TIMES][3] = {{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} }; -uint32_t clk_param_48m[TEST_CLK_TIMES][3] = {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 60}, {333333, 3, 48}, {800000, 1, 60}, {5000000, 1, 10}, {12000000, 1, 4}, {18000000, 1, 3}, {26000000, 1, 2} }; uint32_t clk_param_160m[TEST_CLK_TIMES][3] = {{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} }; #if SPI_LL_SUPPORT_CLK_SRC_PRE_DIV uint32_t clk_param_40m[TEST_CLK_TIMES][3] = {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 4, 50}, {333333, 1, 60}, {800000, 1, 25}, {2000000, 1, 10}, {5000000, 1, 4}, {12000000, 1, 2}, {18000000, 1, 1} }; +uint32_t clk_param_48m[TEST_CLK_TIMES][3] = {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 4, 60}, {333333, 2, 36}, {800000, 1, 30}, {5000000, 1, 5}, {12000000, 1, 2}, {18000000, 1, 2}, {24000000, 1, 1} }; #else uint32_t clk_param_40m[TEST_CLK_TIMES][3] = {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 50}, {333333, 2, 60}, {800000, 1, 50}, {2000000, 1, 20}, {5000000, 1, 8}, {12000000, 1, 3}, {18000000, 1, 2} }; +uint32_t clk_param_48m[TEST_CLK_TIMES][3] = {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 60}, {333333, 3, 48}, {800000, 1, 60}, {5000000, 1, 10}, {12000000, 1, 4}, {18000000, 1, 3}, {26000000, 1, 2} }; #endif TEST_CASE("SPI Master clockdiv calculation routines", "[spi]") @@ -173,7 +174,7 @@ TEST_CASE("SPI Master clk_source and divider accuracy", "[spi]") int real_freq_khz; spi_device_get_actual_freq(handle, &real_freq_khz); // (byte_len * 8 / real_freq_hz) * 1000 000, (unit)us - int trans_cost_us_predict = (float)TEST_CLK_BYTE_LEN * 8 * 1000 / real_freq_khz + IDF_TARGET_MAX_TRANS_TIME_POLL_DMA; + int trans_cost_us_predict = (float)TEST_CLK_BYTE_LEN * 8 * 1000 / real_freq_khz; // transaction and measure time start = esp_timer_get_time(); @@ -355,8 +356,8 @@ TEST_CASE("SPI Master test", "[spi]") master_free_device_bus(handle); TEST_ASSERT(success); - printf("Testing bus at 20MHz\n"); - handle = setup_spi_bus_loopback(20000000, true); + printf("Testing bus at %dMHz\n", IDF_TARGET_MAX_SPI_CLK_FREQ / 1000000); + handle = setup_spi_bus_loopback(IDF_TARGET_MAX_SPI_CLK_FREQ, true); success &= spi_test(handle, 128); //DMA, aligned success &= spi_test(handle, 4096 * 3); //DMA, multiple descs master_free_device_bus(handle); @@ -1470,7 +1471,7 @@ TEST_CASE("spi_speed", "[spi]") ESP_LOGI(TAG, "%.2lf", GET_US_BY_CCOUNT(t_flight_sorted[i])); } #ifndef CONFIG_SPIRAM - printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_NO_POLLING", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); + printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_INTR_DMA", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); TEST_ASSERT_LESS_THAN_INT(IDF_TARGET_MAX_TRANS_TIME_INTR_DMA, (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); #endif @@ -1488,7 +1489,7 @@ TEST_CASE("spi_speed", "[spi]") ESP_LOGI(TAG, "%.2lf", GET_US_BY_CCOUNT(t_flight_sorted[i])); } #ifndef CONFIG_SPIRAM - printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_POLLING", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); + printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_POLL_DMA", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); TEST_ASSERT_LESS_THAN_INT(IDF_TARGET_MAX_TRANS_TIME_POLL_DMA, (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); #endif @@ -1508,7 +1509,7 @@ TEST_CASE("spi_speed", "[spi]") ESP_LOGI(TAG, "%.2lf", GET_US_BY_CCOUNT(t_flight_sorted[i])); } #ifndef CONFIG_SPIRAM - printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_NO_POLLING_NO_DMA", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); + printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_INTR_CPU", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); TEST_ASSERT_LESS_THAN_INT(IDF_TARGET_MAX_TRANS_TIME_INTR_CPU, (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); #endif @@ -1526,7 +1527,7 @@ TEST_CASE("spi_speed", "[spi]") ESP_LOGI(TAG, "%.2lf", GET_US_BY_CCOUNT(t_flight_sorted[i])); } #ifndef CONFIG_SPIRAM - printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_POLLING_NO_DMA", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); + printf("[Performance][%s]: %d us\n", "SPI_PER_TRANS_POLL_CPU", (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); TEST_ASSERT_LESS_THAN_INT(IDF_TARGET_MAX_TRANS_TIME_POLL_CPU, (int)GET_US_BY_CCOUNT(t_flight_sorted[(TEST_TIMES + 1) / 2])); #endif diff --git a/components/esp_driver_spi/test_apps/param/README.md b/components/esp_driver_spi/test_apps/param/README.md index 15bfc62bf3..44f3780f1d 100644 --- a/components/esp_driver_spi/test_apps/param/README.md +++ b/components/esp_driver_spi/test_apps/param/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c index 8651b517cb..020df8e860 100644 --- a/components/esp_driver_spi/test_apps/param/main/test_spi_param.c +++ b/components/esp_driver_spi/test_apps/param/main/test_spi_param.c @@ -19,6 +19,27 @@ #include "driver/spi_slave_hd.h" #endif +//test low frequency, high frequency until freq limit for worst case (both GPIO) +static int test_freq_default[] = { + IDF_TARGET_MAX_SPI_CLK_FREQ / 100, + IDF_TARGET_MAX_SPI_CLK_FREQ / 50, + IDF_TARGET_MAX_SPI_CLK_FREQ / 16, + IDF_TARGET_MAX_SPI_CLK_FREQ / 7, + IDF_TARGET_MAX_SPI_CLK_FREQ / 3, + IDF_TARGET_MAX_SPI_CLK_FREQ / 2, + IDF_TARGET_MAX_SPI_CLK_FREQ, + 0, +}; + +static void spitest_def_param(void* arg) +{ + spitest_param_set_t *param_set = (spitest_param_set_t*)arg; + param_set->test_size = 8; + if (param_set->freq_list == NULL) { + param_set->freq_list = test_freq_default; + } +} + #if (TEST_SPI_PERIPH_NUM >= 2) //These will only be enabled on chips with 2 or more SPI peripherals @@ -337,16 +358,6 @@ TEST_SPI_LOCAL(TIMING, timing_pgroup) /************ Mode Test ***********************************************/ #define FREQ_LIMIT_MODE 16 * 1000 * 1000 -static int test_freq_mode_local[] = { - 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 #ifdef CONFIG_IDF_TARGET_ESP32 @@ -377,7 +388,7 @@ static int test_freq_mode_local[] = { static spitest_param_set_t mode_pgroup[] = { { .pset_name = "Mode 0", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 0, @@ -387,7 +398,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 1", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .freq_limit = 26 * 1000 * 1000, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, @@ -398,7 +409,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 2", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 2, @@ -408,7 +419,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 3", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .freq_limit = 26 * 1000 * 1000, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, @@ -419,7 +430,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 0, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 0, @@ -431,7 +442,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 1, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .freq_limit = 26 * 1000 * 1000, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, @@ -444,7 +455,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 2, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, .mode = 2, @@ -456,7 +467,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "Mode 3, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .freq_limit = 26 * 1000 * 1000, .master_limit = 13 * 1000 * 1000, .dup = FULL_DUPLEX, @@ -470,7 +481,7 @@ static spitest_param_set_t mode_pgroup[] = { /////////////////////////// MISO //////////////////////////////////// { .pset_name = "MISO, Mode 0", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 0, .master_iomux = false, @@ -479,7 +490,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 1", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 1, .master_iomux = false, @@ -488,7 +499,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 2", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 2, .master_iomux = false, @@ -497,7 +508,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 3", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 3, .master_iomux = false, @@ -506,7 +517,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 0, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 0, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -517,7 +528,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 1, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 1, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -528,7 +539,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 2, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 2, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -539,7 +550,7 @@ static spitest_param_set_t mode_pgroup[] = { }, { .pset_name = "MISO, Mode 3, DMA", - .freq_list = test_freq_mode_local, + .freq_list = test_freq_default, .dup = HALF_DUPLEX_MISO, .mode = 3, .slave_dma_chan = SPI_DMA_CH_AUTO, @@ -1047,19 +1058,6 @@ TEST_SPI_MASTER_SLAVE(TIMING, timing_conf, "") //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, - 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[] = { 20 * 1000 * 1000, 0, @@ -1069,7 +1067,7 @@ spitest_param_set_t mode_conf[] = { //non-DMA tests { .pset_name = "mode 0, no DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1079,7 +1077,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 1, no DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1089,7 +1087,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 2, no DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1099,7 +1097,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 3, no DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1147,7 +1145,7 @@ spitest_param_set_t mode_conf[] = { //DMA tests { .pset_name = "mode 0, DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1160,7 +1158,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 1, DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1173,7 +1171,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 2, DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, @@ -1186,7 +1184,7 @@ spitest_param_set_t mode_conf[] = { }, { .pset_name = "mode 3, DMA", - .freq_list = test_freq_mode_ms, + .freq_list = test_freq_default, .master_limit = FREQ_LIMIT_MODE, .dup = FULL_DUPLEX, .master_iomux = true, diff --git a/components/esp_driver_spi/test_apps/slave/README.md b/components/esp_driver_spi/test_apps/slave/README.md index 15bfc62bf3..44f3780f1d 100644 --- a/components/esp_driver_spi/test_apps/slave/README.md +++ b/components/esp_driver_spi/test_apps/slave/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c index 34c9e0a09a..21266edd09 100644 --- a/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c +++ b/components/esp_driver_spi/test_apps/slave/main/test_spi_slave.c @@ -231,7 +231,7 @@ TEST_CASE("test fullduplex slave with only TX direction", "[spi]") t.tx_buffer = NULL; t.rx_buffer = master_rxbuf; } - spi_device_transmit(spi, (spi_transaction_t *)&t); + spi_device_transmit(spi, &t); //wait for end TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY)); diff --git a/components/esp_driver_spi/test_apps/slave_hd/README.md b/components/esp_driver_spi/test_apps/slave_hd/README.md index ffceaeb158..b91fc54735 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/README.md +++ b/components/esp_driver_spi/test_apps/slave_hd/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_driver_spi/test_apps/slave_hd/main/idf_component.yml b/components/esp_driver_spi/test_apps/slave_hd/main/idf_component.yml index c4fea9f147..f066b284d1 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/main/idf_component.yml +++ b/components/esp_driver_spi/test_apps/slave_hd/main/idf_component.yml @@ -1,6 +1,8 @@ dependencies: + espressif/esp_serial_slave_link: "^1.1.0" test_utils: path: ${IDF_PATH}/tools/test_apps/components/test_utils test_driver_utils: path: ${IDF_PATH}/components/driver/test_apps/components/test_driver_utils - espressif/esp_serial_slave_link: "^1.1.0" + spi_bench_mark: + path: ${IDF_PATH}/components/esp_driver_spi/test_apps/components/spi_bench_mark diff --git a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c index 293b1e24ec..635b4ab984 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c +++ b/components/esp_driver_spi/test_apps/slave_hd/main/test_spi_slave_hd.c @@ -19,6 +19,7 @@ #include "esp_private/sleep_cpu.h" #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_pmu.h" +#include "spi_performance.h" #include "esp_rom_gpio.h" #define TEST_BUFFER_SIZE 256 ///< buffer size of each wrdma buffer in fifo mode @@ -433,6 +434,27 @@ static void test_hd_loop(const void* arg1, void* arg2) } } +//test low frequency, high frequency until freq limit for worst case (both GPIO) +static int test_freq_default[] = { + IDF_TARGET_MAX_SPI_CLK_FREQ / 100, + IDF_TARGET_MAX_SPI_CLK_FREQ / 50, + IDF_TARGET_MAX_SPI_CLK_FREQ / 10, + IDF_TARGET_MAX_SPI_CLK_FREQ / 7, + IDF_TARGET_MAX_SPI_CLK_FREQ / 4, + IDF_TARGET_MAX_SPI_CLK_FREQ / 2, + IDF_TARGET_MAX_SPI_CLK_FREQ, + 0, +}; + +static void spitest_def_param(void* arg) +{ + spitest_param_set_t *param_set = (spitest_param_set_t*)arg; + param_set->test_size = 8; + if (param_set->freq_list == NULL) { + param_set->freq_list = test_freq_default; + } +} + static const ptest_func_t hd_test_func = { .pre_test = test_hd_init, .post_test = test_hd_deinit, @@ -446,9 +468,8 @@ static const ptest_func_t hd_test_func = { static int test_freq_hd[] = { 500 * 1000, - 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 + 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge + IDF_TARGET_MAX_SPI_CLK_FREQ, //maximum freq MISO stable before next latch edge 0, }; diff --git a/components/esp_lcd/test_apps/spi_lcd/README.md b/components/esp_lcd/test_apps/spi_lcd/README.md index 3bc8f1af35..78b6ac489f 100644 --- a/components/esp_lcd/test_apps/spi_lcd/README.md +++ b/components/esp_lcd/test_apps/spi_lcd/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | This test app is used to test LCDs with SPI interface. diff --git a/components/hal/esp32c2/include/hal/spi_ll.h b/components/hal/esp32c2/include/hal/spi_ll.h index cff322be05..fef1ff04fc 100644 --- a/components/hal/esp32c2/include/hal/spi_ll.h +++ b/components/hal/esp32c2/include/hal/spi_ll.h @@ -21,7 +21,6 @@ #include "soc/spi_periph.h" #include "soc/spi_struct.h" #include "soc/system_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index a7fe606151..258cc41675 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -21,7 +21,6 @@ #include "soc/spi_periph.h" #include "soc/spi_struct.h" #include "soc/system_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" diff --git a/components/hal/esp32c5/include/hal/spi_ll.h b/components/hal/esp32c5/include/hal/spi_ll.h index 538ea77ac0..42006016b7 100644 --- a/components/hal/esp32c5/include/hal/spi_ll.h +++ b/components/hal/esp32c5/include/hal/spi_ll.h @@ -17,12 +17,12 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" -#include "soc/lldesc.h" #include "soc/clk_tree_defs.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" #include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" #ifdef __cplusplus extern "C" { @@ -41,6 +41,7 @@ extern "C" { #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized #define SPI_LL_SUPPORT_CLK_SRC_PRE_DIV 1 //clock source have divider before peripheral +#define SPI_LL_SRC_PRE_DIV_MAX (PCR_SPI2_CLKM_DIV_NUM + 1) //source pre divider max #define SPI_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider /** diff --git a/components/hal/esp32c6/include/hal/spi_ll.h b/components/hal/esp32c6/include/hal/spi_ll.h index c52ec2f26c..83d516236f 100644 --- a/components/hal/esp32c6/include/hal/spi_ll.h +++ b/components/hal/esp32c6/include/hal/spi_ll.h @@ -20,7 +20,6 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" @@ -183,8 +182,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_sel = 1; - hw->dma_conf.val = 0; hw->dma_conf.slv_tx_seg_trans_clr_en = 1; hw->dma_conf.slv_rx_seg_trans_clr_en = 1; diff --git a/components/hal/esp32c61/include/hal/spi_ll.h b/components/hal/esp32c61/include/hal/spi_ll.h index 4c8bf5edb2..b2304f1b90 100644 --- a/components/hal/esp32c61/include/hal/spi_ll.h +++ b/components/hal/esp32c61/include/hal/spi_ll.h @@ -18,11 +18,11 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" #include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" #ifdef __cplusplus extern "C" { @@ -41,6 +41,7 @@ extern "C" { #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized #define SPI_LL_SUPPORT_CLK_SRC_PRE_DIV 1 //clock source have divider before peripheral +#define SPI_LL_SRC_PRE_DIV_MAX (PCR_SPI2_CLKM_DIV_NUM + 1) //source pre divider max #define SPI_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider /** @@ -205,8 +206,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_sel = 1; - hw->dma_conf.val = 0; hw->dma_conf.slv_tx_seg_trans_clr_en = 1; hw->dma_conf.slv_rx_seg_trans_clr_en = 1; diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index fade1a565e..43690e9106 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -22,7 +22,6 @@ #include "soc/spi_struct.h" #include "soc/chip_revision.h" #include "soc/pcr_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/efuse_hal.h" @@ -184,8 +183,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_sel = 0; - hw->dma_conf.val = 0; hw->dma_conf.slv_tx_seg_trans_clr_en = 1; hw->dma_conf.slv_rx_seg_trans_clr_en = 1; diff --git a/components/hal/esp32h21/include/hal/spi_ll.h b/components/hal/esp32h21/include/hal/spi_ll.h index c4e7caba82..d2ae13d544 100644 --- a/components/hal/esp32h21/include/hal/spi_ll.h +++ b/components/hal/esp32h21/include/hal/spi_ll.h @@ -20,7 +20,6 @@ #include "soc/spi_struct.h" #include "soc/chip_revision.h" #include "soc/pcr_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/efuse_hal.h" @@ -170,8 +169,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_sel = 0; - hw->dma_conf.val = 0; hw->dma_conf.slv_tx_seg_trans_clr_en = 1; hw->dma_conf.slv_rx_seg_trans_clr_en = 1; diff --git a/components/hal/esp32h4/include/hal/gpspi_flash_ll.h b/components/hal/esp32h4/include/hal/gpspi_flash_ll.h index 82f3597f48..d46fcdeea3 100644 --- a/components/hal/esp32h4/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h4/include/hal/gpspi_flash_ll.h @@ -386,6 +386,21 @@ static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) abort(); } +/** + * Set D/Q output level during dummy phase + * + * @param dev Beginning address of the peripheral registers. + * @param out_en whether to enable IO output for dummy phase + * @param out_level dummy output level + */ +static inline void gpspi_flash_ll_set_dummy_out(spi_dev_t *dev, uint32_t out_en, uint32_t out_lev) +{ + // dev->ctrl.dummy_out = out_en; + // dev->ctrl.q_pol = out_lev; + // dev->ctrl.d_pol = out_lev; + abort(); +} + /** * Set extra hold time of CS after the clocks. * diff --git a/components/hal/esp32h4/include/hal/spi_ll.h b/components/hal/esp32h4/include/hal/spi_ll.h new file mode 100644 index 0000000000..a198b6342b --- /dev/null +++ b/components/hal/esp32h4/include/hal/spi_ll.h @@ -0,0 +1,1326 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The LL layer for ESP32H4 SPI register operations + * It is NOT public api, don't use in application code. + ******************************************************************************/ + +#pragma once + +#include //for abs() +#include +#include "esp_attr.h" +#include "esp_types.h" +#include "soc/spi_periph.h" +#include "soc/spi_struct.h" +#include "hal/assert.h" +#include "hal/misc.h" +#include "hal/spi_types.h" +#include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL)) +/// Interrupt not used. Don't use in app. +#define SPI_LL_UNUSED_INT_MASK (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_QUAD | SPI_FADDR_DUAL) +#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)) + +#define SPI_LL_DMA_MAX_BIT_LEN SPI_MS_DATA_BITLEN +#define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words +#define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized +#define SPI_LL_SUPPORT_CLK_SRC_PRE_DIV 1 //clock source have divider before peripheral +#define SPI_LL_SRC_PRE_DIV_MAX (PCR_SPI2_CLKM_DIV_NUM + 1) //source pre divider max +#define SPI_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider + +/** + * The data structure holding calculated clock configuration. Since the + * calculation needs long time, it should be calculated during initialization and + * stored somewhere to be quickly used. + */ +typedef uint32_t spi_ll_clock_val_t; +typedef spi_dev_t spi_dma_dev_t; + +// Type definition of all supported interrupts +typedef enum { + SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done + SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD. + SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD. + SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD. + SPI_LL_INTR_WRDMA = BIT(9), ///< Has received WRDMA command. Only available in slave HD. + SPI_LL_INTR_CMD7 = BIT(10), ///< Has received CMD7 command. Only available in slave HD. + SPI_LL_INTR_CMD8 = BIT(11), ///< Has received CMD8 command. Only available in slave HD. + SPI_LL_INTR_CMD9 = BIT(12), ///< Has received CMD9 command. Only available in slave HD. + SPI_LL_INTR_CMDA = BIT(13), ///< Has received CMDA command. Only available in slave HD. + SPI_LL_INTR_SEG_DONE = BIT(14), +} spi_ll_intr_t; + +// Flags for conditions under which the transaction length should be recorded +typedef enum { + SPI_LL_TRANS_LEN_COND_WRBUF = BIT(0), ///< WRBUF length will be recorded + SPI_LL_TRANS_LEN_COND_RDBUF = BIT(1), ///< RDBUF length will be recorded + SPI_LL_TRANS_LEN_COND_WRDMA = BIT(2), ///< WRDMA length will be recorded + SPI_LL_TRANS_LEN_COND_RDDMA = BIT(3), ///< RDDMA length will be recorded +} spi_ll_trans_len_cond_t; + +// SPI base command +typedef enum { + /* Slave HD Only */ + SPI_LL_BASE_CMD_HD_WRBUF = 0x01, + SPI_LL_BASE_CMD_HD_RDBUF = 0x02, + SPI_LL_BASE_CMD_HD_WRDMA = 0x03, + SPI_LL_BASE_CMD_HD_RDDMA = 0x04, + SPI_LL_BASE_CMD_HD_SEG_END = 0x05, + SPI_LL_BASE_CMD_HD_EN_QPI = 0x06, + SPI_LL_BASE_CMD_HD_WR_END = 0x07, + SPI_LL_BASE_CMD_HD_INT0 = 0x08, + SPI_LL_BASE_CMD_HD_INT1 = 0x09, + SPI_LL_BASE_CMD_HD_INT2 = 0x0A, +} spi_ll_base_command_t; + +/*------------------------------------------------------------------------------ + * Control + *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) +{ + switch (host_id) { + case SPI2_HOST: + PCR.spi2_conf.spi2_clk_en = enable; + break; + case SPI3_HOST: + PCR.spi3_conf.spi3_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) +{ + switch (host_id) { + case SPI2_HOST: + PCR.spi2_conf.spi2_rst_en = 1; + PCR.spi2_conf.spi2_rst_en = 0; + break; + case SPI3_HOST: + PCR.spi3_conf.spi3_rst_en = 1; + PCR.spi3_conf.spi3_rst_en = 0; + break; + default: HAL_ASSERT(false); + } +} + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + switch (host_id) { + case SPI2_HOST: + PCR.spi2_clkm_conf.spi2_clkm_en = enable; + break; + case SPI3_HOST: + PCR.spi3_clkm_conf.spi3_clkm_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/** + * 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` + */ +__attribute__((always_inline)) +static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + int clock_id = 0; + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + clock_id = 2; + break; + case SPI_CLK_SRC_XTAL: + clock_id = 0; + break; + default: + clock_id = 1; + break; + } + + if (hw == &GPSPI2) { + PCR.spi2_clkm_conf.spi2_clkm_sel = clock_id; + } else if (hw == &GPSPI3) { + PCR.spi3_clkm_conf.spi3_clkm_sel = clock_id; + } else { + HAL_ASSERT(false); + } +} + +/** + * Config clock source integrate pre_div before it enter GPSPI peripheral + * + * @note 1. For timing turning(e.g. input_delay) feature available, should be (mst_div >= 2) + * 2. From peripheral limitation: (sour_freq/hs_div <= 160M) and (sour_freq/hs_div/mst_div <= 80M) + * + * @param hw Beginning address of the peripheral registers. + * @param hs_div Timing turning clock divider: (hs_clk_o = sour_freq/hs_div) + * @param mst_div Functional output clock divider: (mst_clk_o = sour_freq/hs_div/mst_div) + */ +__attribute__((always_inline)) +static inline void spi_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint8_t mst_div) +{ + // In IDF master driver 'mst_div' will be const 2 and 'hs_div' is actually pre_div temporally + (void) hs_div; + if (hw == &GPSPI2) { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi2_clkm_conf, spi2_clkm_div_num, mst_div - 1); + } else if (hw == &GPSPI3) { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi3_clkm_conf, spi3_clkm_div_num, mst_div - 1); + } else { + HAL_ASSERT(false); + } +} + +/** + * Initialize SPI peripheral (master). + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_master_init(spi_dev_t *hw) +{ + //Reset timing + hw->user1.cs_setup_time = 0; + hw->user1.cs_hold_time = 0; + + //use all 64 bytes of the buffer + hw->user.usr_miso_highpart = 0; + hw->user.usr_mosi_highpart = 0; + + //Disable unused error_end condition + hw->user1.mst_wfull_err_end_en = 0; + hw->user2.mst_rempty_err_end_en = 0; + + //Disable unneeded ints + hw->slave.val = 0; + hw->user.val = 0; + + hw->dma_conf.val = 0; + hw->dma_conf.slv_tx_seg_trans_clr_en = 1; + hw->dma_conf.slv_rx_seg_trans_clr_en = 1; + hw->dma_conf.dma_slv_seg_trans_en = 0; +} + +/** + * Initialize SPI peripheral (slave). + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_slave_init(spi_dev_t *hw) +{ + //Configure slave + hw->clock.val = 0; + hw->user.val = 0; + hw->ctrl.val = 0; + hw->user.doutdin = 1; //we only support full duplex + hw->user.sio = 0; + hw->slave.slave_mode = 1; + hw->slave.soft_reset = 1; + hw->slave.soft_reset = 0; + //use all 64 bytes of the buffer + hw->user.usr_miso_highpart = 0; + hw->user.usr_mosi_highpart = 0; + + // Configure DMA In-Link to not be terminated when transaction bit counter exceeds + hw->dma_conf.rx_eof_en = 0; + hw->dma_conf.dma_slv_seg_trans_en = 0; + + //Disable unneeded ints + hw->dma_int_ena.val &= ~SPI_LL_UNUSED_INT_MASK; +} + +/** + * Initialize SPI peripheral (slave half duplex mode) + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_slave_hd_init(spi_dev_t *hw) +{ + hw->clock.val = 0; + hw->user.val = 0; + hw->ctrl.val = 0; + hw->user.doutdin = 0; + hw->user.sio = 0; + + hw->slave.soft_reset = 1; + hw->slave.soft_reset = 0; + hw->slave.slave_mode = 1; +} + +/** + * Determine and unify the default level of mosi line when bus free + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_set_mosi_free_level(spi_dev_t *hw, bool level) +{ + hw->ctrl.d_pol = level; //set default level for MOSI only on IDLE state +} + +/** + * Apply the register configurations and wait until it's done + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_apply_config(spi_dev_t *hw) +{ + hw->cmd.update = 1; + while (hw->cmd.update); //waiting config applied +} + +/** + * Check whether user-defined transaction is done. + * + * @param hw Beginning address of the peripheral registers. + * + * @return True if transaction is done, otherwise false. + */ +static inline bool spi_ll_usr_is_done(spi_dev_t *hw) +{ + return hw->dma_int_raw.trans_done_int_raw; +} + +/** + * Trigger start of user-defined transaction. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_user_start(spi_dev_t *hw) +{ + hw->cmd.usr = 1; +} + +/** + * Get current running command bit-mask. (Preview) + * + * @param hw Beginning address of the peripheral registers. + * + * @return Bitmask of running command, see ``SPI_CMD_REG``. 0 if no in-flight command. + */ +static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) +{ + return hw->cmd.val; +} + +/** + * Reset the slave peripheral before next transaction. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_slave_reset(spi_dev_t *hw) +{ + hw->slave.soft_reset = 1; + hw->slave.soft_reset = 0; +} + +/** + * Reset SPI CPU TX FIFO + * + * On ESP32H4, this function is not separated + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw) +{ + hw->dma_conf.buf_afifo_rst = 1; + hw->dma_conf.buf_afifo_rst = 0; +} + +/** + * Reset SPI CPU RX FIFO + * + * On ESP32H4, this function is not separated + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw) +{ + hw->dma_conf.rx_afifo_rst = 1; + hw->dma_conf.rx_afifo_rst = 0; +} + +/** + * Reset SPI DMA TX FIFO + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw) +{ + hw->dma_conf.dma_afifo_rst = 1; + hw->dma_conf.dma_afifo_rst = 0; +} + +/** + * Reset SPI DMA RX FIFO + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw) +{ + hw->dma_conf.rx_afifo_rst = 1; + hw->dma_conf.rx_afifo_rst = 0; +} + +/** + * Clear in fifo full error + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_infifo_full_clr(spi_dev_t *hw) +{ + hw->dma_int_clr.dma_infifo_full_err_int_clr = 1; +} + +/** + * Clear out fifo empty error + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw) +{ + hw->dma_int_clr.dma_outfifo_empty_err_int_clr = 1; +} + +/*------------------------------------------------------------------------------ + * DMA + *----------------------------------------------------------------------------*/ +/** + * Enable/Disable RX DMA (Peripherals->DMA->RAM) + * + * @param hw Beginning address of the peripheral registers. + * @param enable 1: enable; 2: disable + */ +static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable) +{ + hw->dma_conf.dma_rx_ena = enable; +} + +/** + * Enable/Disable TX DMA (RAM->DMA->Peripherals) + * + * @param hw Beginning address of the peripheral registers. + * @param enable 1: enable; 2: disable + */ +static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable) +{ + hw->dma_conf.dma_tx_ena = enable; +} + +/** + * Configuration of RX DMA EOF interrupt generation way + * + * @param hw Beginning address of the peripheral registers. + * @param enable 1: spi_dma_inlink_eof is set when the number of dma pushed data bytes is equal to the value of spi_slv/mst_dma_rd_bytelen[19:0] in spi dma transition. 0: spi_dma_inlink_eof is set by spi_trans_done in non-seg-trans or spi_dma_seg_trans_done in seg-trans. + */ +static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable) +{ + hw->dma_conf.rx_eof_en = enable; +} + +/*------------------------------------------------------------------------------ + * Buffer + *----------------------------------------------------------------------------*/ +/** + * Write to SPI hardware data buffer. + * + * @param hw Beginning address of the peripheral registers. + * @param buffer_to_send Address of the data to be written to the hardware data buffer. + * @param bitlen Length to write, in bits. + */ +static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_send, size_t bitlen) +{ + for (int x = 0; x < bitlen; x += 32) { + //Use memcpy to get around alignment issues for txdata + uint32_t word; + memcpy(&word, &buffer_to_send[x / 8], 4); + hw->data_buf[(x / 32)].buf = word; + } +} + +/** + * Write to SPI hardware data buffer by buffer ID (address) + * + * @param hw Beginning address of the peripheral registers + * @param byte_id Start ID (address) of the hardware buffer to be written + * @param data Address of the data to be written to the hardware data buffer. + * @param len Length to write, in bytes. + */ +static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len) +{ + HAL_ASSERT(byte_id + len <= 64); + HAL_ASSERT(len > 0); + HAL_ASSERT(byte_id >= 0); + + while (len > 0) { + uint32_t word; + int offset = byte_id % 4; + int copy_len = 4 - offset; + if (copy_len > len) { + copy_len = len; + } + + //read-modify-write + if (copy_len != 4) { + word = hw->data_buf[byte_id / 4].buf; //read + } + memcpy(((uint8_t *)&word) + offset, data, copy_len); //modify + hw->data_buf[byte_id / 4].buf = word; //write + + data += copy_len; + byte_id += copy_len; + len -= copy_len; + } +} + +/** + * Read from SPI hardware data buffer. + * + * @param hw Beginning address of the peripheral registers. + * @param buffer_to_rcv Address of a buffer to read data from hardware data buffer + * @param bitlen Length to read, in bits. + */ +static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, size_t bitlen) +{ + for (int x = 0; x < bitlen; x += 32) { + //Do a memcpy to get around possible alignment issues in rx_buffer + uint32_t word = hw->data_buf[x / 32].buf; + int len = bitlen - x; + if (len > 32) { + len = 32; + } + memcpy(&buffer_to_rcv[x / 8], &word, (len + 7) / 8); + } +} + +/** + * Read from SPI hardware data buffer by buffer ID (address) + * + * @param hw Beginning address of the peripheral registers + * @param byte_id Start ID (address) of the hardware buffer to be read + * @param data Address of a buffer to read data from hardware data buffer + * @param len Length to read, in bytes. + */ +static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *out_data, int len) +{ + while (len > 0) { + uint32_t word = hw->data_buf[byte_id / 4].buf; + int offset = byte_id % 4; + int copy_len = 4 - offset; + if (copy_len > len) { + copy_len = len; + } + + memcpy(out_data, ((uint8_t *)&word) + offset, copy_len); + byte_id += copy_len; + out_data += copy_len; + len -= copy_len; + } +} + +/*------------------------------------------------------------------------------ + * Configs: mode + *----------------------------------------------------------------------------*/ +/** + * Enable/disable the postive-cs feature. + * + * @param hw Beginning address of the peripheral registers. + * @param cs One of the CS (0-2) to enable/disable the feature. + * @param pos_cs True to enable the feature, otherwise disable (default). + */ +static inline void spi_ll_master_set_pos_cs(spi_dev_t *hw, int cs, uint32_t pos_cs) +{ + if (pos_cs) { + hw->misc.master_cs_pol |= (1 << cs); + } else { + hw->misc.master_cs_pol &= ~(1 << cs); + } +} + +/** + * Enable/disable the LSBFIRST feature for TX data. + * + * @param hw Beginning address of the peripheral registers. + * @param lsbfirst True if LSB of TX data to be sent first, otherwise MSB is sent first (default). + */ +static inline void spi_ll_set_tx_lsbfirst(spi_dev_t *hw, bool lsbfirst) +{ + hw->ctrl.wr_bit_order = lsbfirst; +} + +/** + * Enable/disable the LSBFIRST feature for RX data. + * + * @param hw Beginning address of the peripheral registers. + * @param lsbfirst True if first bit received as LSB, otherwise as MSB (default). + */ +static inline void spi_ll_set_rx_lsbfirst(spi_dev_t *hw, bool lsbfirst) +{ + hw->ctrl.rd_bit_order = lsbfirst; +} + +/** + * Set SPI mode for the peripheral as master. + * + * @param hw Beginning address of the peripheral registers. + * @param mode SPI mode to work at, 0-3. + */ +static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode) +{ + //Configure polarity + if (mode == 0) { + hw->misc.ck_idle_edge = 0; + hw->user.ck_out_edge = 0; + } else if (mode == 1) { + hw->misc.ck_idle_edge = 0; + hw->user.ck_out_edge = 1; + } else if (mode == 2) { + hw->misc.ck_idle_edge = 1; + hw->user.ck_out_edge = 1; + } else if (mode == 3) { + hw->misc.ck_idle_edge = 1; + hw->user.ck_out_edge = 0; + } +} + +/** + * Set SPI mode for the peripheral as slave. + * + * @param hw Beginning address of the peripheral registers. + * @param mode SPI mode to work at, 0-3. + */ +static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma_used) +{ + if (mode == 0) { + hw->misc.ck_idle_edge = 0; + hw->user.rsck_i_edge = 0; + hw->user.tsck_i_edge = 0; + hw->slave.clk_mode_13 = 0; + } else if (mode == 1) { + hw->misc.ck_idle_edge = 0; + hw->user.rsck_i_edge = 1; + hw->user.tsck_i_edge = 1; + hw->slave.clk_mode_13 = 1; + } else if (mode == 2) { + hw->misc.ck_idle_edge = 1; + hw->user.rsck_i_edge = 1; + hw->user.tsck_i_edge = 1; + hw->slave.clk_mode_13 = 0; + } else if (mode == 3) { + hw->misc.ck_idle_edge = 1; + hw->user.rsck_i_edge = 0; + hw->user.tsck_i_edge = 0; + hw->slave.clk_mode_13 = 1; + } + hw->slave.rsck_data_out = 0; +} + +/** + * Set SPI to work in full duplex or half duplex mode. + * + * @param hw Beginning address of the peripheral registers. + * @param half_duplex True to work in half duplex mode, otherwise in full duplex mode. + */ +static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex) +{ + hw->user.doutdin = !half_duplex; +} + +/** + * Set SPI to work in SIO mode or not. + * + * SIO is a mode which MOSI and MISO share a line. The device MUST work in half-duplexmode. + * + * @param hw Beginning address of the peripheral registers. + * @param sio_mode True to work in SIO mode, otherwise false. + */ +static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) +{ + hw->user.sio = sio_mode; +} + +/** + * Configure the SPI transaction line mode for the master to use. + * + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. + */ +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) +{ + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2); + hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4); + hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); + hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); + hw->ctrl.fread_dual = (line_mode.data_lines == 2); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_quad = (line_mode.data_lines == 4); +} + +/** + * Set the SPI slave to work in segment transaction mode + * + * @param hw Beginning address of the peripheral registers. + * @param seg_trans True to work in seg mode, otherwise false. + */ +static inline void spi_ll_slave_set_seg_mode(spi_dev_t *hw, bool seg_trans) +{ + hw->dma_conf.dma_slv_seg_trans_en = seg_trans; +} + +/** + * Select one of the CS to use in current transaction. + * + * @param hw Beginning address of the peripheral registers. + * @param cs_id The cs to use, 0-2, otherwise none of them is used. + */ +static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) +{ + hw->misc.cs0_dis = (cs_id == 0) ? 0 : 1; + hw->misc.cs1_dis = (cs_id == 1) ? 0 : 1; + hw->misc.cs2_dis = (cs_id == 2) ? 0 : 1; + hw->misc.cs3_dis = (cs_id == 3) ? 0 : 1; + hw->misc.cs4_dis = (cs_id == 4) ? 0 : 1; + hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1; +} + +/** + * Keep Chip Select activated after the current transaction. + * + * @param hw Beginning address of the peripheral registers. + * @param keep_active if 0 don't keep CS activated, else keep CS activated + */ +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ + hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0; +} + +/*------------------------------------------------------------------------------ + * Configs: parameters + *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + hw->clock.clk_edge_sel = (sample_point == SPI_SAMPLING_POINT_PHASE_1); +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return true; +} + +/** + * Set the clock for master by stored value. + * + * @param hw Beginning address of the peripheral registers. + * @param val Stored clock configuration calculated before (by ``spi_ll_cal_clock``). + */ +static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_clock_val_t *val) +{ + hw->clock.val = *(uint32_t *)val; +} + +/** + * Get the frequency of given dividers. Don't use in app. + * + * @param fapb APB clock of the system. + * @param pre Pre divider. + * @param n Main divider. + * + * @return Frequency of given dividers. + */ +__attribute__((always_inline)) +static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) +{ + return (fapb / (pre * n)); +} + +/** + * Calculate the nearest frequency available for master. + * + * @param fapb APB clock of the system. + * @param hz Frequency desired. + * @param duty_cycle Duty cycle desired. + * @param out_reg Output address to store the calculated clock configurations for the return frequency. + * + * @return Actual (nearest) frequency. + */ +__attribute__((always_inline)) +static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) +{ + typeof(GPSPI2.clock) reg = {.val = 0}; + int eff_clk; + + //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. + if (hz > ((fapb / 4) * 3)) { + //Using Fapb directly will give us the best result here. + reg.clkcnt_l = 0; + reg.clkcnt_h = 0; + reg.clkcnt_n = 0; + reg.clkdiv_pre = 0; + reg.clk_equ_sysclk = 1; + eff_clk = fapb; + } else { + //For best duty cycle resolution, we want n to be as close to 32 as possible, but + //we also need a pre/n combo that gets us as close as possible to the intended freq. + //To do this, we bruteforce n and calculate the best pre to go along with that. + //If there's a choice between pre/n combos that give the same result, use the one + //with the higher n. + int pre, n, h, l; + int bestn = -1; + int bestpre = -1; + int besterr = 0; + int errval; + for (n = 2; n <= 64; n++) { //Start at 2: we need to be able to set h/l so we have at least one high and one low pulse. + //Effectively, this does pre=round((fapb/n)/hz). + pre = ((fapb / n) + (hz / 2)) / hz; + if (pre <= 0) { + pre = 1; + } + if (pre > 16) { + pre = 16; + } + errval = abs(spi_ll_freq_for_pre_n(fapb, pre, n) - hz); + if (bestn == -1 || errval <= besterr) { + besterr = errval; + bestn = n; + bestpre = pre; + } + } + + n = bestn; + pre = bestpre; + l = n; + //This effectively does round((duty_cycle*n)/256) + h = (duty_cycle * n + 127) / 256; + if (h <= 0) { + h = 1; + } + + reg.clk_equ_sysclk = 0; + reg.clkcnt_n = n - 1; + reg.clkdiv_pre = pre - 1; + reg.clkcnt_h = h - 1; + reg.clkcnt_l = l - 1; + eff_clk = spi_ll_freq_for_pre_n(fapb, pre, n); + } + if (out_reg != NULL) { + *(uint32_t *)out_reg = reg.val; + } + return eff_clk; +} + +/** + * Calculate and set clock for SPI master according to desired parameters. + * + * This takes long, suggest to calculate the configuration during + * initialization by ``spi_ll_master_cal_clock`` and store the result, then + * configure the clock by stored value when used by + * ``spi_ll_msater_set_clock_by_reg``. + * + * @param hw Beginning address of the peripheral registers. + * @param fapb APB clock of the system. + * @param hz Frequency desired. + * @param duty_cycle Duty cycle desired. + * + * @return Actual frequency that is used. + */ +static inline int spi_ll_master_set_clock(spi_dev_t *hw, int fapb, int hz, int duty_cycle) +{ + spi_ll_clock_val_t reg_val; + int freq = spi_ll_master_cal_clock(fapb, hz, duty_cycle, ®_val); + spi_ll_master_set_clock_by_reg(hw, ®_val); + return freq; +} + +/** + * Set the mosi delay after the output edge to the signal. (Preview) + * + * The delay mode/num is a Espressif conception, may change in the new chips. + * + * @param hw Beginning address of the peripheral registers. + * @param delay_mode Delay mode, see TRM. + * @param delay_num APB clocks to delay. + */ +static inline void spi_ll_set_mosi_delay(spi_dev_t *hw, int delay_mode, int delay_num) +{ +} + +/** + * Set the miso delay applied to the input signal before the internal peripheral. (Preview) + * + * The delay mode/num is a Espressif conception, may change in the new chips. + * + * @param hw Beginning address of the peripheral registers. + * @param delay_mode Delay mode, see TRM. + * @param delay_num APB clocks to delay. + */ +static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int delay_num) +{ +} + +/** + * Set the delay of SPI clocks before the CS inactive edge after the last SPI clock. + * + * @param hw Beginning address of the peripheral registers. + * @param hold Delay of SPI clocks after the last clock, 0 to disable the hold phase. + */ +static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold) +{ + hw->user1.cs_hold_time = hold; + hw->user.cs_hold = hold ? 1 : 0; +} + +/** + * Set the delay of SPI clocks before the first SPI clock after the CS active edge. + * + * Note ESP32H4 doesn't support to use this feature when command/address phases + * are used in full duplex mode. + * + * @param hw Beginning address of the peripheral registers. + * @param setup Delay of SPI clocks after the CS active edge, 0 to disable the setup phase. + */ +static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup) +{ + hw->user1.cs_setup_time = setup - 1; + hw->user.cs_setup = setup ? 1 : 0; +} + +/*------------------------------------------------------------------------------ + * Configs: data + *----------------------------------------------------------------------------*/ +/** + * Set the output length (master). + * This should be called before master setting MISO(input) length + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen output length, in bits. + */ +static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen) +{ + if (bitlen > 0) { + hw->ms_dlen.ms_data_bitlen = bitlen - 1; + } +} + +/** + * Set the input length (master). + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen input length, in bits. + */ +static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen) +{ + if (bitlen > 0) { + hw->ms_dlen.ms_data_bitlen = bitlen - 1; + } +} + +/** + * Set the maximum input length (slave). + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen Input length, in bits. + */ +static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen) +{ + //This is not used in esp32H4 +} + +/** + * Set the maximum output length (slave). + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen Output length, in bits. + */ +static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen) +{ + //This is not used in esp32H4 +} + +/** + * Set the length of command phase. + * + * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit + * command phases takes 4 cycles in 4-bit mode. + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen Length of command phase, in bits. 0 to disable the command phase. + */ +static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen) +{ + hw->user2.usr_command_bitlen = bitlen - 1; + hw->user.usr_command = bitlen ? 1 : 0; +} + +/** + * Set the length of address phase. + * + * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit + * address phases takes 4 cycles in 4-bit mode. + * + * @param hw Beginning address of the peripheral registers. + * @param bitlen Length of address phase, in bits. 0 to disable the address phase. + */ +static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen) +{ + hw->user1.usr_addr_bitlen = bitlen - 1; + hw->user.usr_addr = bitlen ? 1 : 0; +} + +/** + * Set the address value in an intuitive way. + * + * The length and lsbfirst is required to shift and swap the address to the right place. + * + * @param hw Beginning address of the peripheral registers. + * @param address Address to set + * @param addrlen Length of the address phase + * @param lsbfirst Whether the LSB first feature is enabled. + */ +static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, uint32_t lsbfirst) +{ + if (lsbfirst) { + /* The output address start from the LSB of the highest byte, i.e. + * addr[24] -> addr[31] + * ... + * addr[0] -> addr[7] + * So swap the byte order to let the LSB sent first. + */ + addr = HAL_SWAP32(addr); + //otherwise only addr register is sent + hw->addr.val = addr; + } else { + // shift the address to MSB of addr register. + // output address will be sent from MSB to LSB of addr register + hw->addr.val = addr << (32 - addrlen); + } +} + +/** + * Set the command value in an intuitive way. + * + * The length and lsbfirst is required to shift and swap the command to the right place. + * + * @param hw Beginning command of the peripheral registers. + * @param command Command to set + * @param addrlen Length of the command phase + * @param lsbfirst Whether the LSB first feature is enabled. + */ +static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst) +{ + if (lsbfirst) { + // The output command start from bit0 to bit 15, kept as is. + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); + } else { + /* Output command will be sent from bit 7 to 0 of command_value, and + * then bit 15 to 8 of the same register field. Shift and swap to send + * more straightly. + */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); + } +} + +/** + * Set dummy clocks to output before RX phase (master), or clocks to skip + * before the data phase and after the address phase (slave). + * + * Note this phase is also used to compensate RX timing in half duplex mode. + * + * @param hw Beginning address of the peripheral registers. + * @param dummy_n Dummy cycles used. 0 to disable the dummy phase. + */ +static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) +{ + hw->user.usr_dummy = dummy_n ? 1 : 0; + if (dummy_n > 0) { + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); + } +} + +/** + * Enable/disable the RX data phase. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True if RX phase exist, otherwise false. + */ +static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable) +{ + hw->user.usr_miso = enable; +} + +/** + * Enable/disable the TX data phase. + * + * @param hw Beginning address of the peripheral registers. + * @param enable True if TX phase exist, otherwise false. + */ +static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable) +{ + hw->user.usr_mosi = enable; +} + +/** + * Get the received bit length of the slave. + * + * @param hw Beginning address of the peripheral registers. + * + * @return Received bits of the slave. + */ +static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) +{ + return hw->slave1.slv_data_bitlen; +} + +/*------------------------------------------------------------------------------ + * Interrupts + *----------------------------------------------------------------------------*/ +//helper macros to generate code for each interrupts +#define FOR_EACH_ITEM(op, list) do { list(op) } while(0) +#define INTR_LIST(item) \ + item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done_int_ena, dma_int_raw.trans_done_int_raw, dma_int_clr.trans_done_int_clr, dma_int_set.trans_done_int_set) \ + item(SPI_LL_INTR_RDBUF, dma_int_ena.slv_rd_buf_done_int_ena, dma_int_raw.slv_rd_buf_done_int_raw, dma_int_clr.slv_rd_buf_done_int_clr, dma_int_set.slv_rd_buf_done_int_set) \ + item(SPI_LL_INTR_WRBUF, dma_int_ena.slv_wr_buf_done_int_ena, dma_int_raw.slv_wr_buf_done_int_raw, dma_int_clr.slv_wr_buf_done_int_clr, dma_int_set.slv_wr_buf_done_int_set) \ + item(SPI_LL_INTR_RDDMA, dma_int_ena.slv_rd_dma_done_int_ena, dma_int_raw.slv_rd_dma_done_int_raw, dma_int_clr.slv_rd_dma_done_int_clr, dma_int_set.slv_rd_dma_done_int_set) \ + item(SPI_LL_INTR_WRDMA, dma_int_ena.slv_wr_dma_done_int_ena, dma_int_raw.slv_wr_dma_done_int_raw, dma_int_clr.slv_wr_dma_done_int_clr, dma_int_set.slv_wr_dma_done_int_set) \ + item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done_int_ena, dma_int_raw.dma_seg_trans_done_int_raw, dma_int_clr.dma_seg_trans_done_int_clr, dma_int_set.dma_seg_trans_done_int_set) \ + item(SPI_LL_INTR_CMD7, dma_int_ena.slv_cmd7_int_ena, dma_int_raw.slv_cmd7_int_raw, dma_int_clr.slv_cmd7_int_clr, dma_int_set.slv_cmd7_int_set) \ + item(SPI_LL_INTR_CMD8, dma_int_ena.slv_cmd8_int_ena, dma_int_raw.slv_cmd8_int_raw, dma_int_clr.slv_cmd8_int_clr, dma_int_set.slv_cmd8_int_set) \ + item(SPI_LL_INTR_CMD9, dma_int_ena.slv_cmd9_int_ena, dma_int_raw.slv_cmd9_int_raw, dma_int_clr.slv_cmd9_int_clr, dma_int_set.slv_cmd9_int_set) \ + item(SPI_LL_INTR_CMDA, dma_int_ena.slv_cmda_int_ena, dma_int_raw.slv_cmda_int_raw, dma_int_clr.slv_cmda_int_clr, dma_int_set.slv_cmda_int_set) + + +static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) +{ +#define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1; + FOR_EACH_ITEM(ENA_INTR, INTR_LIST); +#undef ENA_INTR +} + +static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) +{ +#define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0; + FOR_EACH_ITEM(DIS_INTR, INTR_LIST); +#undef DIS_INTR +} + +static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) +{ +#define SET_INTR(intr_bit, _, __, ___, set_reg) if (intr_mask & (intr_bit)) hw->set_reg = 1; + FOR_EACH_ITEM(SET_INTR, INTR_LIST); +#undef SET_INTR +} + +static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) +{ +#define CLR_INTR(intr_bit, _, __, clr_reg, ...) if (intr_mask & (intr_bit)) hw->clr_reg = 1; + FOR_EACH_ITEM(CLR_INTR, INTR_LIST); +#undef CLR_INTR +} + +static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) +{ +#define GET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit) && hw->st_reg) return true; + FOR_EACH_ITEM(GET_INTR, INTR_LIST); + return false; +#undef GET_INTR +} + +#undef FOR_EACH_ITEM +#undef INTR_LIST + +/** + * Disable the trans_done interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_disable_int(spi_dev_t *hw) +{ + hw->dma_int_ena.trans_done_int_ena = 0; +} + +/** + * Clear the trans_done interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_clear_int_stat(spi_dev_t *hw) +{ + hw->dma_int_clr.trans_done_int_clr = 1; +} + +/** + * Set the trans_done interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_set_int_stat(spi_dev_t *hw) +{ + hw->dma_int_set.trans_done_int_set = 1; +} + +/** + * Enable the trans_done interrupt. + * + * @param hw Beginning address of the peripheral registers. + */ +static inline void spi_ll_enable_int(spi_dev_t *hw) +{ + hw->dma_int_ena.trans_done_int_ena = 1; +} + +/*------------------------------------------------------------------------------ + * Slave HD + *----------------------------------------------------------------------------*/ +static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) +{ + hw->slave.slv_rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; + hw->slave.slv_wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; + hw->slave.slv_rddma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDDMA) ? 1 : 0; + hw->slave.slv_wrdma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0; +} + +static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) +{ + return hw->slave1.slv_data_bitlen / 8; +} + +static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) +{ + return hw->slave1.slv_last_addr; +} + +#undef SPI_LL_RST_MASK +#undef SPI_LL_UNUSED_INT_MASK + +/** + * Get the base spi command + * + * @param cmd_t Command value + */ +static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t) +{ + uint8_t cmd_base = 0x00; + switch (cmd_t) { + case SPI_CMD_HD_WRBUF: + cmd_base = SPI_LL_BASE_CMD_HD_WRBUF; + break; + case SPI_CMD_HD_RDBUF: + cmd_base = SPI_LL_BASE_CMD_HD_RDBUF; + break; + case SPI_CMD_HD_WRDMA: + cmd_base = SPI_LL_BASE_CMD_HD_WRDMA; + break; + case SPI_CMD_HD_RDDMA: + cmd_base = SPI_LL_BASE_CMD_HD_RDDMA; + break; + case SPI_CMD_HD_SEG_END: + cmd_base = SPI_LL_BASE_CMD_HD_SEG_END; + break; + case SPI_CMD_HD_EN_QPI: + cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI; + break; + case SPI_CMD_HD_WR_END: + cmd_base = SPI_LL_BASE_CMD_HD_WR_END; + break; + case SPI_CMD_HD_INT0: + cmd_base = SPI_LL_BASE_CMD_HD_INT0; + break; + case SPI_CMD_HD_INT1: + cmd_base = SPI_LL_BASE_CMD_HD_INT1; + break; + case SPI_CMD_HD_INT2: + cmd_base = SPI_LL_BASE_CMD_HD_INT2; + break; + default: + HAL_ASSERT(cmd_base); + } + return cmd_base; +} + +/** + * Get the spi communication command + * + * @param cmd_t Base command value + * @param line_mode Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN. + */ +static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode) +{ + uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t); + uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit + + if (line_mode.data_lines == 2) { + if (line_mode.addr_lines == 2) { + cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit + } else { + cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit + } + } else if (line_mode.data_lines == 4) { + if (line_mode.addr_lines == 4) { + cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit + } else { + cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit + } + } + if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) { + cmd_mod = 0x00; + } + + return cmd_base | cmd_mod; +} + +/** + * Get the dummy bits + * + * @param line_mode Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN. + */ +static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode) +{ + return 8; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32p4/include/hal/spi_ll.h b/components/hal/esp32p4/include/hal/spi_ll.h index 599ecf6843..a1da625f9a 100644 --- a/components/hal/esp32p4/include/hal/spi_ll.h +++ b/components/hal/esp32p4/include/hal/spi_ll.h @@ -19,11 +19,11 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/hp_sys_clkrst_reg.h" #ifdef __cplusplus extern "C" { @@ -41,6 +41,7 @@ extern "C" { #define SPI_LL_DMA_MAX_BIT_LEN SPI_MS_DATA_BITLEN #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words #define SPI_LL_SUPPORT_CLK_SRC_PRE_DIV 1 //clock source have divider before peripheral +#define SPI_LL_SRC_PRE_DIV_MAX (HP_SYS_CLKRST_REG_GPSPI2_MST_CLK_DIV_NUM + 1) //source pre divider max #define SPI_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index b23c74eae6..acc71ba64b 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -21,7 +21,6 @@ #include "soc/spi_periph.h" #include "soc/spi_struct.h" #include "soc/system_struct.h" -#include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" #include "hal/spi_types.h" diff --git a/components/soc/esp32h21/include/soc/clk_tree_defs.h b/components/soc/esp32h21/include/soc/clk_tree_defs.h index 0e29e70840..8718583e19 100644 --- a/components/soc/esp32h21/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h21/include/soc/clk_tree_defs.h @@ -280,11 +280,7 @@ typedef enum { * @brief Type of SPI clock source. */ typedef enum { -#if SOC_CLK_TREE_SUPPORTED SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F48M, /*!< Select PLL_48M as SPI source clock */ -#else - SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */ -#endif SPI_CLK_SRC_PLL_F48M = SOC_MOD_CLK_PLL_F48M, /*!< Select PLL_48M 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 */ diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 54c17a526f..dae76e5395 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -47,6 +47,10 @@ config SOC_RMT_SUPPORTED bool default y +config SOC_GPSPI_SUPPORTED + bool + default y + config SOC_I2C_SUPPORTED bool default y @@ -551,6 +555,38 @@ config SOC_SPI_MAX_CS_NUM int default 6 +config SOC_SPI_MAXIMUM_BUFFER_SIZE + int + default 64 + +config SOC_SPI_SUPPORT_DDRCLK + bool + default y + +config SOC_SPI_SLAVE_SUPPORT_SEG_TRANS + bool + default y + +config SOC_SPI_SUPPORT_CD_SIG + bool + default y + +config SOC_SPI_SUPPORT_CONTINUOUS_TRANS + bool + default y + +config SOC_SPI_SUPPORT_SLAVE_HD_VER2 + bool + default y + +config SOC_SPI_SUPPORT_CLK_XTAL + 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/esp32h4/include/soc/clk_tree_defs.h b/components/soc/esp32h4/include/soc/clk_tree_defs.h index 958612e2be..c520614e11 100644 --- a/components/soc/esp32h4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h4/include/soc/clk_tree_defs.h @@ -240,15 +240,15 @@ typedef enum { /** * @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} +#define SOC_SPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F48M,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_DEFAULT = SOC_MOD_CLK_PLL_F48M, /*!< Select XTAL as SPI source clock */ SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL 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 */ } soc_periph_spi_clk_src_t; diff --git a/components/soc/esp32h4/include/soc/retention_periph_defs.h b/components/soc/esp32h4/include/soc/retention_periph_defs.h index dc5e35603f..2f316495d7 100644 --- a/components/soc/esp32h4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h4/include/soc/retention_periph_defs.h @@ -46,14 +46,15 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_TWAI0 = 22, SLEEP_RETENTION_MODULE_PARLIO0 = 23, SLEEP_RETENTION_MODULE_GPSPI2 = 24, - SLEEP_RETENTION_MODULE_LEDC = 25, - SLEEP_RETENTION_MODULE_PCNT0 = 26, - SLEEP_RETENTION_MODULE_MCPWM0 = 27, + SLEEP_RETENTION_MODULE_GPSPI3 = 25, + SLEEP_RETENTION_MODULE_LEDC = 26, + SLEEP_RETENTION_MODULE_PCNT0 = 27, + SLEEP_RETENTION_MODULE_MCPWM0 = 28, /* Modem module, which includes BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_BLE_MAC = 28, - SLEEP_RETENTION_MODULE_BT_BB = 29, - SLEEP_RETENTION_MODULE_802154_MAC = 30, + SLEEP_RETENTION_MODULE_BLE_MAC = 29, + SLEEP_RETENTION_MODULE_BT_BB = 30, + SLEEP_RETENTION_MODULE_802154_MAC = 31, SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; @@ -83,6 +84,7 @@ typedef enum periph_retention_module { : ((m) == SLEEP_RETENTION_MODULE_TWAI0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_PARLIO0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_GPSPI2) ? true \ + : ((m) == SLEEP_RETENTION_MODULE_GPSPI3) ? true \ : ((m) == SLEEP_RETENTION_MODULE_LEDC) ? true \ : ((m) == SLEEP_RETENTION_MODULE_PCNT0) ? true \ : ((m) == SLEEP_RETENTION_MODULE_MCPWM0) ? true \ diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index edb7c9e87b..c8ca8b3808 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -57,7 +57,7 @@ #define SOC_I2S_SUPPORTED 1 #define SOC_RMT_SUPPORTED 1 // #define SOC_SDM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12348 -// #define SOC_GPSPI_SUPPORTED 1 // TODO: [ESP32H4] IDF-12362 IDF-12364 IDF-12366 +#define SOC_GPSPI_SUPPORTED 1 // #define SOC_LEDC_SUPPORTED 1 // TODO: [ESP32H4] IDF-12343 #define SOC_I2C_SUPPORTED 1 #define SOC_SYSTIMER_SUPPORTED 1 // TODO: [ESP32H4] IDF-12375 IDF-12377 @@ -404,18 +404,16 @@ /*-------------------------- SPI CAPS ----------------------------------------*/ #define SOC_SPI_PERIPH_NUM 3 #define SOC_SPI_PERIPH_CS_NUM(i) (((i)==0)? 2: (((i)==1)? 6: 3)) -#define SOC_SPI_MAX_CS_NUM 6 +#define SOC_SPI_MAX_CS_NUM 6 -// #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 - -// #define SOC_SPI_SUPPORT_DDRCLK 1 -// #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_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 +#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define SOC_SPI_SUPPORT_DDRCLK 1 +#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_SLAVE_HD_VER2 1 +#define SOC_SPI_SUPPORT_CLK_XTAL 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/esp32h4/include/soc/spi_pins.h b/components/soc/esp32h4/include/soc/spi_pins.h index 35b7345912..fa9dffa36d 100644 --- a/components/soc/esp32h4/include/soc/spi_pins.h +++ b/components/soc/esp32h4/include/soc/spi_pins.h @@ -6,7 +6,6 @@ #pragma once -// TODO: [ESP32H4] IDF-12388 #define MSPI_FUNC_NUM 0 #define MSPI_IOMUX_PIN_NUM_CS0 7 #define MSPI_IOMUX_PIN_NUM_CS1 6 diff --git a/components/soc/esp32h4/register/soc/pcr_reg.h b/components/soc/esp32h4/register/soc/pcr_reg.h index 8e75c6c525..9d65e0d2fa 100644 --- a/components/soc/esp32h4/register/soc/pcr_reg.h +++ b/components/soc/esp32h4/register/soc/pcr_reg.h @@ -1550,9 +1550,8 @@ extern "C" { /** PCR_SPI2_CLKM_SEL : R/W; bitpos: [21:20]; default: 0; * Configures the clock source of SPI2. * 0 (default): XTAL_CLK - * 1: PLL_F160M_CLK + * 1: PLL_F48M_CLK * 2: RC_FAST_CLK - * 3: PLL_F120M_CLK */ #define PCR_SPI2_CLKM_SEL 0x00000003U #define PCR_SPI2_CLKM_SEL_M (PCR_SPI2_CLKM_SEL_V << PCR_SPI2_CLKM_SEL_S) @@ -2905,9 +2904,8 @@ extern "C" { /** PCR_SPI3_CLKM_SEL : R/W; bitpos: [21:20]; default: 0; * Configures the clock source of SPI3. * 0 (default): XTAL_CLK - * 1: PLL_F160M_CLK + * 1: PLL_F48M_CLK * 2: RC_FAST_CLK - * 3: PLL_F120M_CLK */ #define PCR_SPI3_CLKM_SEL 0x00000003U #define PCR_SPI3_CLKM_SEL_M (PCR_SPI3_CLKM_SEL_V << PCR_SPI3_CLKM_SEL_S) diff --git a/components/soc/esp32h4/register/soc/pcr_struct.h b/components/soc/esp32h4/register/soc/pcr_struct.h index c2b58f5aee..0bc022d385 100644 --- a/components/soc/esp32h4/register/soc/pcr_struct.h +++ b/components/soc/esp32h4/register/soc/pcr_struct.h @@ -1304,9 +1304,8 @@ typedef union { /** spi2_clkm_sel : R/W; bitpos: [21:20]; default: 0; * Configures the clock source of SPI2. * 0 (default): XTAL_CLK - * 1: PLL_F160M_CLK + * 1: PLL_F48M_CLK * 2: RC_FAST_CLK - * 3: PLL_F120M_CLK */ uint32_t spi2_clkm_sel:2; /** spi2_clkm_en : R/W; bitpos: [22]; default: 1; @@ -2452,9 +2451,8 @@ typedef union { /** spi3_clkm_sel : R/W; bitpos: [21:20]; default: 0; * Configures the clock source of SPI3. * 0 (default): XTAL_CLK - * 1: PLL_F160M_CLK + * 1: PLL_F48M_CLK * 2: RC_FAST_CLK - * 3: PLL_F120M_CLK */ uint32_t spi3_clkm_sel:2; /** spi3_clkm_en : R/W; bitpos: [22]; default: 0; diff --git a/components/soc/esp32h4/register/soc/spi_reg.h b/components/soc/esp32h4/register/soc/spi_reg.h index 9bfe747795..36902ec347 100644 --- a/components/soc/esp32h4/register/soc/spi_reg.h +++ b/components/soc/esp32h4/register/soc/spi_reg.h @@ -11,7 +11,7 @@ extern "C" { #endif -#define DR_REG_SPI_BASE(i) (((i)>=2) ? (DR_REG_SPI2_BASE + (i-2) * 0x1000) : (0)) // GPSPI2 and GPSPI3 +#define DR_REG_SPI_BASE(i) (((i)>=2) ? (DR_REG_GPSPI2_BASE + (i-2) * 0x1000) : (0)) // GPSPI2 and GPSPI3 /** SPI_CMD_REG register * Command control register diff --git a/components/soc/esp32h4/spi_periph.c b/components/soc/esp32h4/spi_periph.c new file mode 100644 index 0000000000..a013e32f2b --- /dev/null +++ b/components/soc/esp32h4/spi_periph.c @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/spi_periph.h" + +/* + Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc +*/ +const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { + { + // MSPI has dedicated iomux pins + }, { + .spiclk_out = FSPICLK_OUT_IDX, + .spiclk_in = FSPICLK_IN_IDX, + .spid_out = FSPID_OUT_IDX, + .spiq_out = FSPIQ_OUT_IDX, + .spiwp_out = FSPIWP_OUT_IDX, + .spihd_out = FSPIHD_OUT_IDX, + .spid_in = FSPID_IN_IDX, + .spiq_in = FSPIQ_IN_IDX, + .spiwp_in = FSPIWP_IN_IDX, + .spihd_in = FSPIHD_IN_IDX, + .spics_out = {FSPICS0_OUT_IDX, FSPICS1_OUT_IDX, FSPICS2_OUT_IDX, FSPICS3_OUT_IDX, FSPICS4_OUT_IDX, FSPICS5_OUT_IDX}, + .spics_in = FSPICS0_IN_IDX, + .spiclk_iomux_pin = SPI2_IOMUX_PIN_NUM_CLK, + .spid_iomux_pin = SPI2_IOMUX_PIN_NUM_MOSI, + .spiq_iomux_pin = SPI2_IOMUX_PIN_NUM_MISO, + .spiwp_iomux_pin = SPI2_IOMUX_PIN_NUM_WP, + .spihd_iomux_pin = SPI2_IOMUX_PIN_NUM_HD, + .spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS, + .irq = ETS_GPSPI2_INTR_SOURCE, + .irq_dma = -1, + .hw = &GPSPI2, + .func = SPI2_FUNC_NUM, + }, { + .spiclk_out = FSPI3CLK_OUT_IDX, + .spiclk_in = FSPI3CLK_IN_IDX, + .spid_out = FSPI3D_OUT_IDX, + .spiq_out = FSPI3Q_OUT_IDX, + .spiwp_out = FSPI3WP_OUT_IDX, + .spihd_out = FSPI3HD_OUT_IDX, + .spid_in = FSPI3D_IN_IDX, + .spiq_in = FSPI3Q_IN_IDX, + .spiwp_in = FSPI3WP_IN_IDX, + .spihd_in = FSPI3HD_IN_IDX, + .spics_out = {FSPI3CS0_OUT_IDX, FSPI3CS1_OUT_IDX, FSPI3CS2_OUT_IDX}, + .spics_in = FSPI3CS0_IN_IDX, + //SPI3 doesn't have iomux pins + .spiclk_iomux_pin = -1, + .spid_iomux_pin = -1, + .spiq_iomux_pin = -1, + .spiwp_iomux_pin = -1, + .spihd_iomux_pin = -1, + .spics0_iomux_pin = -1, + .irq = ETS_GPSPI3_INTR_SOURCE, + .irq_dma = -1, + .hw = &GPSPI3, + .func = -1, + } +}; + +/** + * Backup registers in Light sleep: (total cnt 29) + * + * cmd + * addr + * ctrl + * clock + * user + * user1 + * user2 + * ms_dlen + * misc + * dma_conf + * dma_int_ena + * data_buf[0-15] // slave driver only + * slave + * slave1 + */ +#define SPI_RETENTION_REGS_CNT 29 +static const uint32_t spi_regs_map[4] = {0x31ff, 0x33fffc0, 0x0, 0x0}; +#define SPI_REG_RETENTION_ENTRIES(num) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_GPSPI_LINK(0), \ + DR_REG_SPI_BASE(num), DR_REG_SPI_BASE(num), \ + SPI_RETENTION_REGS_CNT, 0, 0, \ + spi_regs_map[0], spi_regs_map[1], \ + spi_regs_map[2], spi_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + /* Additional interrupt setting is required by idf SPI drivers after register recovered */ \ + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_GPSPI_LINK(1), \ + SPI_DMA_INT_SET_REG(num), \ + SPI_TRANS_DONE_INT_SET | SPI_DMA_SEG_TRANS_DONE_INT_SET | SPI_SLV_CMD7_INT_SET | SPI_SLV_CMD8_INT_SET , \ + UINT32_MAX, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t spi2_regs_retention[] = SPI_REG_RETENTION_ENTRIES(2); // '2' for GPSPI2 +static const regdma_entries_config_t spi3_regs_retention[] = SPI_REG_RETENTION_ENTRIES(3); // '3' for GPSPI3 + +const spi_reg_retention_info_t spi_reg_retention_info[SOC_SPI_PERIPH_NUM - 1] = { // '-1' to except mspi + { + .module_id = SLEEP_RETENTION_MODULE_GPSPI2, + .entry_array = spi2_regs_retention, + .array_size = ARRAY_SIZE(spi2_regs_retention), + }, { + .module_id = SLEEP_RETENTION_MODULE_GPSPI3, + .entry_array = spi3_regs_retention, + .array_size = ARRAY_SIZE(spi3_regs_retention), + } +}; diff --git a/docs/docs_not_updated/esp32h4.txt b/docs/docs_not_updated/esp32h4.txt index e701f1697a..e1884f6e04 100644 --- a/docs/docs_not_updated/esp32h4.txt +++ b/docs/docs_not_updated/esp32h4.txt @@ -144,7 +144,6 @@ api-reference/peripherals/jpeg.rst api-reference/peripherals/mcpwm.rst api-reference/peripherals/usb_host.rst api-reference/peripherals/camera_driver.rst -api-reference/peripherals/spi_master.rst api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/twai.rst api-reference/peripherals/etm.rst @@ -154,7 +153,6 @@ api-reference/peripherals/adc_continuous.rst api-reference/peripherals/hmac.rst api-reference/peripherals/uart.rst api-reference/peripherals/sdspi_host.rst -api-reference/peripherals/spi_slave_hd.rst api-reference/peripherals/vad.rst api-reference/peripherals/i2s.rst api-reference/peripherals/isp.rst @@ -173,7 +171,6 @@ api-reference/peripherals/adc_calibration.rst api-reference/peripherals/lp_i2s.rst api-reference/peripherals/ecdsa.rst api-reference/peripherals/dac.rst -api-reference/peripherals/spi_slave.rst api-reference/peripherals/spi_flash/index.rst api-reference/peripherals/spi_flash/spi_flash_concurrency.rst api-reference/peripherals/spi_flash/spi_flash_override_driver.rst @@ -188,7 +185,6 @@ api-reference/peripherals/lcd/spi_lcd.rst api-reference/peripherals/lcd/rgb_lcd.rst api-reference/peripherals/lcd/parl_lcd.rst api-reference/peripherals/pcnt.rst -api-reference/peripherals/spi_features.rst api-reference/peripherals/ppa.rst api-reference/peripherals/ldo_regulator.rst api-reference/peripherals/ledc.rst diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 6c002fa84f..9f7a0dce61 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -481,12 +481,12 @@ GPIO Matrix and IO_MUX .. only:: not esp32 - {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7" , esp32c5="10", esp32c61="8", esp32h21="12"} - {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9" , esp32c5="6", esp32c61="6", esp32h21="2"} - {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8" , esp32c5="7", esp32c61="7", esp32h21="3"} - {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10", esp32c5="2", esp32c61="2", esp32h21="4"} - {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6" , esp32c5="4", esp32c61="3", esp32h21="1"} - {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11", esp32c5="5", esp32c61="4", esp32h21="0"} + {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7" , esp32c5="10", esp32c61="8", esp32h21="12", esp32h4="20"} + {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9" , esp32c5="6", esp32c61="6", esp32h21="2", esp32h4="16"} + {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8" , esp32c5="7", esp32c61="7", esp32h21="3", esp32h4="17"} + {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10", esp32c5="2", esp32c61="2", esp32h21="4", esp32h4="15"} + {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6" , esp32c5="4", esp32c61="3", esp32h21="1", esp32h4="19"} + {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11", esp32c5="5", esp32c61="4", esp32h21="0", esp32h4="18"} Most of the chip's peripheral signals have a direct connection to their dedicated IO_MUX pins. However, the signals can also be routed to any other available pins using the less direct GPIO matrix. If at least one signal is routed through the GPIO matrix, then all signals will be routed through it. @@ -532,10 +532,10 @@ The main parameter that determines the transfer speed for large transactions is Transaction Duration ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_MAX_TRANS_TIME_INTR_DMA:default="N/A", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42", esp32c6="34", esp32h2="58", esp32p4="44", esp32c5="24", esp32c61="32"} -{IDF_TARGET_MAX_TRANS_TIME_POLL_DMA:default="N/A", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17", esp32c6="17", esp32h2="28", esp32p4="27", esp32c5="15", esp32c61="17"} -{IDF_TARGET_MAX_TRANS_TIME_INTR_CPU:default="N/A", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32", esp32h2="54", esp32p4="26", esp32c5="22", esp32c61="29"} -{IDF_TARGET_MAX_TRANS_TIME_POLL_CPU:default="N/A", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15", esp32h2="24", esp32p4="12", esp32c5="12", esp32c61="14"} +{IDF_TARGET_MAX_TRANS_TIME_INTR_DMA:default="N/A", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42", esp32c6="34", esp32h2="58", esp32p4="44", esp32c5="24", esp32c61="32", esp32h21="60", esp32h4="70"} +{IDF_TARGET_MAX_TRANS_TIME_POLL_DMA:default="N/A", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17", esp32c6="17", esp32h2="28", esp32p4="27", esp32c5="15", esp32c61="17", esp32h21="32", esp32h4="35"} +{IDF_TARGET_MAX_TRANS_TIME_INTR_CPU:default="N/A", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32", esp32h2="54", esp32p4="26", esp32c5="22", esp32c61="29", esp32h21="55", esp32h4="60"} +{IDF_TARGET_MAX_TRANS_TIME_POLL_CPU:default="N/A", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15", esp32h2="24", esp32p4="12", esp32c5="12", esp32c61="14", esp32h21="26", esp32h4="25"} Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transactions. diff --git a/docs/zh_CN/api-reference/peripherals/spi_master.rst b/docs/zh_CN/api-reference/peripherals/spi_master.rst index beb77711c6..557f61ad7e 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_master.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_master.rst @@ -481,12 +481,12 @@ GPIO 矩阵与 IO_MUX 管脚 .. only:: not esp32 - {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7" , esp32c5="10", esp32c61="8", esp32h21="12"} - {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9" , esp32c5="6", esp32c61="6", esp32h21="2"} - {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8" , esp32c5="7", esp32c61="7", esp32h21="3"} - {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10", esp32c5="2", esp32c61="2", esp32h21="4"} - {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6" , esp32c5="4", esp32c61="3", esp32h21="1"} - {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11", esp32c5="5", esp32c61="4", esp32h21="0"} + {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7" , esp32c5="10", esp32c61="8", esp32h21="12", esp32h4="20"} + {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9" , esp32c5="6", esp32c61="6", esp32h21="2", esp32h4="16"} + {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8" , esp32c5="7", esp32c61="7", esp32h21="3", esp32h4="17"} + {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10", esp32c5="2", esp32c61="2", esp32h21="4", esp32h4="15"} + {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6" , esp32c5="4", esp32c61="3", esp32h21="1", esp32h4="19"} + {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11", esp32c5="5", esp32c61="4", esp32h21="0", esp32h4="18"} 芯片的大多数外围信号都与之专用的 IO_MUX 管脚连接,但这些信号也可以通过较不直接的 GPIO 矩阵路由到任何其他可用的管脚。只要有一个信号是通过 GPIO 矩阵路由的,那么所有的信号都将通过它路由。 @@ -532,10 +532,10 @@ GPIO 矩阵与 IO_MUX 管脚 传输事务持续时间 ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_MAX_TRANS_TIME_INTR_DMA:default="N/A", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42", esp32c6="34", esp32h2="58", esp32p4="44", esp32c5="24", esp32c61="32"} -{IDF_TARGET_MAX_TRANS_TIME_POLL_DMA:default="N/A", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17", esp32c6="17", esp32h2="28", esp32p4="27", esp32c5="15", esp32c61="17"} -{IDF_TARGET_MAX_TRANS_TIME_INTR_CPU:default="N/A", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32", esp32h2="54", esp32p4="26", esp32c5="22", esp32c61="29"} -{IDF_TARGET_MAX_TRANS_TIME_POLL_CPU:default="N/A", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15", esp32h2="24", esp32p4="12", esp32c5="12", esp32c61="14"} +{IDF_TARGET_MAX_TRANS_TIME_INTR_DMA:default="N/A", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp32c2="42", esp32c6="34", esp32h2="58", esp32p4="44", esp32c5="24", esp32c61="32", esp32h21="60", esp32h4="70"} +{IDF_TARGET_MAX_TRANS_TIME_POLL_DMA:default="N/A", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp32c2="17", esp32c6="17", esp32h2="28", esp32p4="27", esp32c5="15", esp32c61="17", esp32h21="32", esp32h4="35"} +{IDF_TARGET_MAX_TRANS_TIME_INTR_CPU:default="N/A", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32", esp32h2="54", esp32p4="26", esp32c5="22", esp32c61="29", esp32h21="55", esp32h4="60"} +{IDF_TARGET_MAX_TRANS_TIME_POLL_CPU:default="N/A", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15", esp32h2="24", esp32p4="12", esp32c5="12", esp32c61="14", esp32h21="26", esp32h4="25"} 传输事务持续时间包括设置 SPI 外设寄存器,将数据复制到 FIFO 或设置 DMA 链接,以及 SPI 传输事务时间。 diff --git a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md index b34f4ddb8a..67ad7bbf2c 100644 --- a/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md +++ b/examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | # I2S TDM Example -- ES7210 4-Ch ADC Codec diff --git a/examples/peripherals/lcd/spi_lcd_touch/README.md b/examples/peripherals/lcd/spi_lcd_touch/README.md index a02465a92d..2f4e0ec119 100644 --- a/examples/peripherals/lcd/spi_lcd_touch/README.md +++ b/examples/peripherals/lcd/spi_lcd_touch/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | # SPI LCD and Touch Panel Example diff --git a/examples/peripherals/lcd/tjpgd/README.md b/examples/peripherals/lcd/tjpgd/README.md index d037c62190..999eb0f19d 100644 --- a/examples/peripherals/lcd/tjpgd/README.md +++ b/examples/peripherals/lcd/tjpgd/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ## LCD tjpgd example diff --git a/examples/peripherals/spi_master/hd_eeprom/README.md b/examples/peripherals/spi_master/hd_eeprom/README.md index 4bb5ad1c11..5efc228a77 100644 --- a/examples/peripherals/spi_master/hd_eeprom/README.md +++ b/examples/peripherals/spi_master/hd_eeprom/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ## SPI master half duplex EEPROM example diff --git a/examples/peripherals/spi_master/lcd/README.md b/examples/peripherals/spi_master/lcd/README.md index 1ff6cb5768..2ac30e1bb3 100644 --- a/examples/peripherals/spi_master/lcd/README.md +++ b/examples/peripherals/spi_master/lcd/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | # SPI Host Driver Example diff --git a/examples/peripherals/spi_slave/README.md b/examples/peripherals/spi_slave/README.md index 44281db7d2..c5eb327e3a 100644 --- a/examples/peripherals/spi_slave/README.md +++ b/examples/peripherals/spi_slave/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ## SPI slave example diff --git a/examples/peripherals/spi_slave_hd/append_mode/master/README.md b/examples/peripherals/spi_slave_hd/append_mode/master/README.md index ea1cb7ec8f..718bc74519 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/master/README.md +++ b/examples/peripherals/spi_slave_hd/append_mode/master/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | See README.md in the parent directory diff --git a/examples/peripherals/spi_slave_hd/append_mode/slave/README.md b/examples/peripherals/spi_slave_hd/append_mode/slave/README.md index ea1cb7ec8f..718bc74519 100644 --- a/examples/peripherals/spi_slave_hd/append_mode/slave/README.md +++ b/examples/peripherals/spi_slave_hd/append_mode/slave/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | See README.md in the parent directory diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/README.md b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/README.md index ea1cb7ec8f..718bc74519 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/README.md +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | See README.md in the parent directory diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/README.md b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/README.md index ffceaeb158..b91fc54735 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/README.md +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | diff --git a/examples/storage/sd_card/sdspi/README.md b/examples/storage/sd_card/sdspi/README.md index bb5ba7dcb8..5a688e6ec6 100644 --- a/examples/storage/sd_card/sdspi/README.md +++ b/examples/storage/sd_card/sdspi/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | # SD Card example (SDSPI)