diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 15cfceb9ac..505d7a4989 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -121,6 +121,8 @@ We have two bits to control the interrupt: #include "driver/gpio.h" #include "hal/spi_hal.h" #include "esp_heap_caps.h" +//Temporarily include soc/rtc.h, will be replaced by clock tree API +#include "soc/rtc.h" typedef struct spi_device_t spi_device_t; @@ -318,7 +320,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa spi_host_t *host = bus_driver_ctx[host_id]; const spi_bus_attr_t* bus_attr = host->bus_attr; SPI_CHECK(dev_config->spics_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(dev_config->spics_io_num), "spics pin invalid", ESP_ERR_INVALID_ARG); - SPI_CHECK(dev_config->clock_speed_hz > 0, "invalid sclk speed", ESP_ERR_INVALID_ARG); + uint32_t apb_clk_freq_hz = rtc_clk_apb_freq_get(); + assert((apb_clk_freq_hz == 80 * 1000 * 1000) || (apb_clk_freq_hz == 40 * 1000 * 1000)); + SPI_CHECK((dev_config->clock_speed_hz > 0) && (dev_config->clock_speed_hz <= apb_clk_freq_hz) , "invalid sclk speed", ESP_ERR_INVALID_ARG); #ifdef CONFIG_IDF_TARGET_ESP32 //The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full //duplex mode does absolutely nothing on the ESP32. @@ -345,9 +349,11 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa int duty_cycle = (dev_config->duty_cycle_pos==0) ? 128 : dev_config->duty_cycle_pos; int use_gpio = !(bus_attr->flags & SPICOMMON_BUSFLAG_IOMUX_PINS); spi_hal_timing_param_t timing_param = { + .clk_src_hz = rtc_clk_apb_freq_get(), + .clk_sel = SPI_CLK_APB, //Currently, SPI driver only set SPI to APB clock. SPI is not supposed to be used during sleep modes. .half_duplex = half_duplex, .no_compensate = no_compensate, - .clock_speed_hz = dev_config->clock_speed_hz, + .expected_freq = dev_config->clock_speed_hz, .duty_cycle = duty_cycle, .input_delay_ns = dev_config->input_delay_ns, .use_gpio = use_gpio @@ -406,7 +412,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa hal_dev->tx_lsbfirst = dev_config->flags & SPI_DEVICE_TXBIT_LSBFIRST ? 1 : 0; hal_dev->rx_lsbfirst = dev_config->flags & SPI_DEVICE_RXBIT_LSBFIRST ? 1 : 0; hal_dev->no_compensate = dev_config->flags & SPI_DEVICE_NO_DUMMY ? 1 : 0; -#if SOC_SPI_SUPPORT_AS_CS +#if SOC_SPI_AS_CS_SUPPORTED hal_dev->as_cs = dev_config->flags& SPI_DEVICE_CLK_AS_CS ? 1 : 0; #endif hal_dev->positive_cs = dev_config->flags & SPI_DEVICE_POSITIVE_CS ? 1 : 0; @@ -699,7 +705,8 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG); #ifdef CONFIG_IDF_TARGET_ESP32 SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG ); -#elif CONFIG_IDF_TARGET_ESP32S3 +#endif +#if !SOC_SPI_HD_BOTH_INOUT_SUPPORTED SPI_CHECK(!is_half_duplex || !tx_enabled || !rx_enabled, "SPI half duplex mode is not supported when both MOSI and MISO phases are enabled.", ESP_ERR_INVALID_ARG); #endif //MOSI phase is skipped only when both tx_buffer and SPI_TRANS_USE_TXDATA are not set. diff --git a/components/driver/test/include/test/test_common_spi.h b/components/driver/test/include/test/test_common_spi.h index 3a92269a4b..1ef231a8d9 100644 --- a/components/driver/test/include/test/test_common_spi.h +++ b/components/driver/test/include/test/test_common_spi.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,9 @@ // All the tests using the header should use this definition as much as possible, // so that the working host can be changed easily in the future. + +#define TEST_SPI_PERIPH_NUM (SOC_SPI_PERIPH_NUM - 1) + #if CONFIG_IDF_TARGET_ESP32 #define TEST_SPI_HOST SPI2_HOST #define TEST_SLAVE_HOST SPI3_HOST @@ -83,8 +86,8 @@ #define ESP_SPI_SLAVE_TV 0 #define WIRE_DELAY 12.5 -#elif CONFIG_IDF_TARGET_ESP32C3 -//NOTE: On esp32c3, there is only 1 GPSPI controller, so master-slave test on single board should be disabled +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP8684 +//NOTE: On these chips, there is only 1 GPSPI controller, so master-slave test on single board should be disabled #define TEST_SPI_HOST SPI2_HOST #define TEST_SLAVE_HOST SPI2_HOST diff --git a/components/driver/test/test_common_spi.c b/components/driver/test/test_common_spi.c index 78b838eec8..5b23dd517c 100644 --- a/components/driver/test/test_common_spi.c +++ b/components/driver/test/test_common_spi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +9,6 @@ #include "driver/gpio.h" #include "hal/gpio_hal.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) -// TODO: SPI support IDF-4024 int test_freq_default[]=TEST_FREQ_DEFAULT(); @@ -250,5 +248,3 @@ void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_ master_send_buf[i] = rand(); } } - -#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) diff --git a/components/driver/test/test_spi_bus_lock.c b/components/driver/test/test_spi_bus_lock.c index 03de30b102..76d7f3fe40 100644 --- a/components/driver/test/test_spi_bus_lock.c +++ b/components/driver/test/test_spi_bus_lock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,8 +12,6 @@ #include "test/test_common_spi.h" #include "unity.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3, ESP8684) -// No runners currently. #if CONFIG_IDF_TARGET_ESP32 // The VSPI pins on UT_T1_ESP_FLASH are connected to a external flash @@ -24,13 +22,13 @@ #define TEST_BUS_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP #define TEST_BUS_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 -#define TEST_BUS_PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO -#define TEST_BUS_PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI -#define TEST_BUS_PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK -#define TEST_BUS_PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS -#define TEST_BUS_PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP -#define TEST_BUS_PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD +#else +#define TEST_BUS_PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO +#define TEST_BUS_PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI +#define TEST_BUS_PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK +#define TEST_BUS_PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS +#define TEST_BUS_PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP +#define TEST_BUS_PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD #endif @@ -225,17 +223,13 @@ static void test_bus_lock(bool test_flash) devcfg.queue_size = 100; //Initialize the SPI bus and 3 devices - ret=spi_bus_initialize(TEST_SPI_HOST, &buscfg, 1); - TEST_ESP_OK(ret); - ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context1.handle); - TEST_ESP_OK(ret); - ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context2.handle); - TEST_ESP_OK(ret); + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context1.handle)); + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context2.handle)); //only have 3 cs pins, leave one for the flash devcfg.spics_io_num = -1; - ret=spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context3.handle); - TEST_ESP_OK(ret); + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &context3.handle)); esp_flash_spi_device_config_t flash_cfg = { .host_id = TEST_SPI_HOST, .cs_id = 2, @@ -285,7 +279,7 @@ static void test_bus_lock(bool test_flash) TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST) ); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP8684) //no runners TEST_CASE("spi bus lock, with flash","[spi][test_env=UT_T1_ESP_FLASH]") { @@ -299,8 +293,8 @@ TEST_CASE("spi bus lock","[spi]") test_bus_lock(false); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) -//SPI1 not supported by driver +#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP8684, ESP32H2) +//disable, SPI1 is not available for GPSPI usage on chips later than ESP32 static IRAM_ATTR esp_err_t test_polling_send(spi_device_handle_t handle) { for (int i = 0; i < 10; i++) { @@ -347,10 +341,8 @@ TEST_CASE("spi master can be used on SPI1", "[spi]") err = spi_bus_remove_device(handle); TEST_ESP_OK(err); } -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) +#endif //disable, SPI1 is not available for GPSPI usage on chips later than ESP32 //TODO: add a case when a non-polling transaction happened in the bus-acquiring time and then release the bus then queue a new trans #endif //!CONFIG_ESP32_SPIRAM_SUPPORT - -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index 890e9f6aa5..d70fbc48bf 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,9 +29,8 @@ #include "../cache_utils.h" #include "soc/soc_memory_layout.h" #include "driver/spi_common_internal.h" +#include "soc/rtc.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) -// TODO: SPI SUPPORT IDF-4024 const static char TAG[] = "test_spi"; @@ -40,7 +39,6 @@ const static char TAG[] = "test_spi"; static void check_spi_pre_n_for(int clk, int pre, int n) { - esp_err_t ret; spi_device_handle_t handle; spi_device_interface_config_t devcfg = { @@ -57,12 +55,11 @@ static void check_spi_pre_n_for(int clk, int pre, int n) spi_transaction_t t; memset(&t, 0, sizeof(t)); - ret = spi_bus_add_device(TEST_SPI_HOST, &devcfg, &handle); - TEST_ASSERT(ret == ESP_OK); + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &handle)); t.length = 16 * 8; t.tx_buffer = sendbuf; - ret = spi_device_transmit(handle, &t); + TEST_ESP_OK(spi_device_transmit(handle, &t)); spi_dev_t *hw = spi_periph_signal[TEST_SPI_HOST].hw; @@ -71,10 +68,20 @@ static void check_spi_pre_n_for(int clk, int pre, int n) TEST_ASSERT(hw->clock.clkcnt_n + 1 == n); TEST_ASSERT(hw->clock.clkdiv_pre + 1 == pre); - ret = spi_bus_remove_device(handle); - TEST_ASSERT(ret == ESP_OK); + TEST_ESP_OK(spi_bus_remove_device(handle)); } +#define TEST_CLK_TIMES 8 +/** + * In this test, SPI Clock Calculation: + * Fspi = Fclk_spi_mst / (pre + n) + * + * For each item: + * {freq, pre, n} + */ +#define TEST_CLK_PARAM_APB_80 {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 16, 50}, {333333, 4, 60}, {800000, 2, 50}, {900000, 2, 44}, {8000000, 1, 10}, {20000000, 1, 4}, {26000000, 1, 3} } +#define TEST_CLK_PARAM_APB_40 {{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 8, 50}, {333333, 2, 60}, {800000, 1, 50}, {900000, 1, 44}, {8000000, 1, 5}, {10000000, 1, 4}, {20000000, 1, 2} } + TEST_CASE("SPI Master clockdiv calculation routines", "[spi]") { spi_bus_config_t buscfg = { @@ -84,22 +91,23 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]") .quadwp_io_num = -1, .quadhd_io_num = -1 }; - esp_err_t ret; - ret = spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO); - TEST_ASSERT(ret == ESP_OK); + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); - check_spi_pre_n_for(26000000, 1, 3); - check_spi_pre_n_for(20000000, 1, 4); - check_spi_pre_n_for(8000000, 1, 10); - check_spi_pre_n_for(800000, 2, 50); - check_spi_pre_n_for(100000, 16, 50); - check_spi_pre_n_for(333333, 4, 60); - check_spi_pre_n_for(900000, 2, 44); - check_spi_pre_n_for(1, SOC_SPI_MAX_PRE_DIVIDER, 64); //Actually should generate the minimum clock speed, 152Hz - check_spi_pre_n_for(26000000, 1, 3); + uint32_t apb_freq_hz = rtc_clk_apb_freq_get(); + if (apb_freq_hz == (80 * MHZ)) { + uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_80; + for (int i = 0; i < TEST_CLK_TIMES; i++) { + check_spi_pre_n_for(clk_param[i][0], clk_param[i][1], clk_param[i][2]); + } + } else { + TEST_ASSERT(apb_freq_hz == (40 * MHZ)); + uint32_t clk_param[TEST_CLK_TIMES][3] = TEST_CLK_PARAM_APB_40; + for (int i = 0; i < TEST_CLK_TIMES; i++) { + check_spi_pre_n_for(clk_param[i][0], clk_param[i][1], clk_param[i][2]); + } + } - ret = spi_bus_free(TEST_SPI_HOST); - TEST_ASSERT(ret == ESP_OK); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST)); } static spi_device_handle_t setup_spi_bus_loopback(int clkspeed, bool dma) @@ -285,7 +293,7 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi]") TEST_ASSERT(success); } -#if TEST_SOC_HAS_INPUT_ONLY_PINS //There is no input-only pin on esp32c3 and esp32s3, so this test could be ignored. +#if TEST_SOC_HAS_INPUT_ONLY_PINS //There is no input-only pin, so this test could be ignored. static esp_err_t test_master_pins(int mosi, int miso, int sclk, int cs) { esp_err_t ret; @@ -783,7 +791,9 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") } -#if !DISABLED_FOR_TARGETS(ESP32C3) //There is only one GPSPI controller, so single-board test is disabled. +#if (TEST_SPI_PERIPH_NUM >= 2) +//These will only be enabled on chips with 2 or more SPI peripherals + static uint8_t bitswap(uint8_t in) { uint8_t out = 0; @@ -1111,9 +1121,7 @@ TEST_CASE("SPI master hd dma TX without RX test", "[spi]") spi_slave_free(TEST_SLAVE_HOST); master_free_device_bus(spi); } - -//There is only one GPSPI controller, so single-board test is disabled. -#endif //#if !DISABLED_FOR_TARGETS(ESP32C3) +#endif //#if (TEST_SPI_PERIPH_NUM >= 2) #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494 #define FD_TEST_BUF_SIZE 32 @@ -1308,6 +1316,8 @@ TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", #define GET_US_BY_CCOUNT(t) ((double)t/CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ) #elif CONFIG_IDF_TARGET_ESP32C3 #define GET_US_BY_CCOUNT(t) ((double)t/CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ) +#elif CONFIG_IDF_TARGET_ESP8684 +#define GET_US_BY_CCOUNT(t) ((double)t/CONFIG_ESP8684_DEFAULT_CPU_FREQ_MHZ) #endif static void speed_setup(spi_device_handle_t *spi, bool use_dma) @@ -1445,5 +1455,3 @@ TEST_CASE("spi_speed", "[spi]") master_free_device_bus(spi); } #endif // CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE - -#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) diff --git a/components/driver/test/test_spi_param.c b/components/driver/test/test_spi_param.c index 86bfb244d7..aa665c7aab 100644 --- a/components/driver/test/test_spi_param.c +++ b/components/driver/test/test_spi_param.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +11,8 @@ #include "driver/spi_master.h" #include "driver/spi_slave.h" -#if !DISABLED_FOR_TARGETS(ESP32C3, ESP8684) -//There is only one GPSPI controller on ESP32C3 and ESP8684, so single-board test is disabled. +#if (TEST_SPI_PERIPH_NUM >= 2) +//These will only be enabled on chips with 2 or more SPI peripherals #ifndef MIN #define MIN(a, b)((a) > (b)? (b): (a)) @@ -1177,4 +1177,4 @@ TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "") #endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3) -#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3, ESP8684) +#endif // #if (TEST_SPI_PERIPH_NUM >= 2) diff --git a/components/driver/test/test_spi_sio.c b/components/driver/test/test_spi_sio.c index 28584426c9..c8eba810b1 100644 --- a/components/driver/test/test_spi_sio.c +++ b/components/driver/test/test_spi_sio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,88 +29,122 @@ #include "hal/spi_ll.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP8684) -#if !DISABLED_FOR_TARGETS(ESP32C3) //There is only one GPSPI controller, so single-board test is disabled. +#if (TEST_SPI_PERIPH_NUM >= 2) +//These will be only enabled on chips with 2 or more SPI peripherals /******************************************************************************** * Test SIO ********************************************************************************/ -TEST_CASE("local test sio", "[spi]") +#if CONFIG_IDF_TARGET_ESP32 +#define MASTER_DIN_SIGNAL HSPID_IN_IDX +#else +#define MASTER_DIN_SIGNAL FSPID_IN_IDX +#endif +static void inner_connect(spi_bus_config_t bus) { + //Master MOSI(spid_out) output to `mosi_num` + spitest_gpio_output_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); + //Slave MOSI(spid_in) input to `mosi_num` + spitest_gpio_input_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spid_in); + + + //Master MOSI input(spid_in) to `miso_num`, due to SIO mode, we use Master's `spid_in` to receive data + spitest_gpio_input_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_in); + //Slave MISO output(spiq_out) + spitest_gpio_output_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out); + //Force this signal goes through gpio matrix + GPIO.func_in_sel_cfg[MASTER_DIN_SIGNAL].sig_in_sel = 1; +} + +TEST_CASE("SPI Single Board Test SIO", "[spi]") +{ + //Master init spi_device_handle_t spi; + spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG(); + + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_DISABLED)); + + spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); + dev_cfg.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE; + dev_cfg.clock_speed_hz = 4 * 1000 * 1000; + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi)); + + //Slave init + bus_cfg.flags = 0; + spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); + TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, SPI_DMA_DISABLED)); + + + same_pin_func_sel(bus_cfg, dev_cfg, 0); + inner_connect(bus_cfg); + + WORD_ALIGNED_ATTR uint8_t master_rx_buffer[320]; WORD_ALIGNED_ATTR uint8_t slave_rx_buffer[320]; - uint32_t pre_set[16] = {[0 ... 15] = 0xcccccccc,}; - spi_ll_write_buffer(SPI_LL_GET_HW(TEST_SPI_HOST), (uint8_t*)pre_set, 16*32); - spi_ll_write_buffer(SPI_LL_GET_HW(TEST_SLAVE_HOST), (uint8_t*)pre_set, 16*32); - - /* This test use a strange connection to test the SIO mode: - * master spid -> slave spid - * slave spiq -> master spid - */ - spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG(); - spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG(); - spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); - slv_cfg.spics_io_num = dev_cfg.spics_io_num; - TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, 0)); - - int miso_io_num = bus_cfg.miso_io_num; - int mosi_io_num = bus_cfg.mosi_io_num; - bus_cfg.mosi_io_num = miso_io_num; - bus_cfg.miso_io_num = -1; - TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, 0)); - - dev_cfg.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE; - TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi)); - - spitest_gpio_output_sel(mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); - spitest_gpio_output_sel(miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out); - spitest_gpio_output_sel(dev_cfg.spics_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spics_out[0]); - spitest_gpio_output_sel(bus_cfg.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out); + spi_transaction_t mst_trans; + spi_slave_transaction_t slv_trans; + spi_slave_transaction_t* ret; for (int i = 0; i < 8; i ++) { - int tlen = i*2+1; - int rlen = 9-i; + int tlen = i * 2 + 1; + int rlen = 9 - i; - ESP_LOGI(MASTER_TAG, "=========== TEST%d ==========", i); + ESP_LOGI("spi", "=========== TEST(%d) Master TX, Slave RX ==========", i); - spi_transaction_t master_t = { - .length = tlen*8, - .tx_buffer = spitest_master_send+i, - .rxlength = rlen*8, - .rx_buffer = master_rx_buffer+i, - }; - spi_slave_transaction_t slave_t = { - .length = (tlen+rlen)*8, - .tx_buffer = spitest_slave_send+i, - .rx_buffer = slave_rx_buffer, - }; - memset(master_rx_buffer, 0x66, sizeof(master_rx_buffer)); + //Slave RX + memset(&slv_trans, 0x0, sizeof(spi_slave_transaction_t)); memset(slave_rx_buffer, 0x66, sizeof(slave_rx_buffer)); - TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY)); + slv_trans.length = tlen * 8; + slv_trans.rx_buffer = slave_rx_buffer + tlen * 8; + TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slv_trans, portMAX_DELAY)); - TEST_ESP_OK(spi_device_transmit(spi, &master_t)); - spi_slave_transaction_t* ret_t; - TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret_t, portMAX_DELAY)); - TEST_ASSERT(ret_t == &slave_t); + //Master TX + memset(&mst_trans, 0x0, sizeof(spi_transaction_t)); + mst_trans.length = tlen * 8; + mst_trans.tx_buffer = spitest_master_send; + TEST_ESP_OK(spi_device_transmit(spi, &mst_trans)); - ESP_LOG_BUFFER_HEXDUMP("master tx", master_t.tx_buffer, tlen, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("slave rx", slave_t.rx_buffer, tlen+rlen, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("slave tx", slave_t.tx_buffer, tlen+rlen, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEXDUMP("master rx", master_t.rx_buffer, rlen, ESP_LOG_INFO); + TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret, portMAX_DELAY)); + TEST_ASSERT(ret == &slv_trans); - TEST_ASSERT_EQUAL_HEX8_ARRAY(master_t.tx_buffer, slave_t.rx_buffer, tlen); - TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t.tx_buffer + tlen, master_t.rx_buffer, rlen); + ESP_LOG_BUFFER_HEXDUMP("master tx", mst_trans.tx_buffer, tlen, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("slave rx", slv_trans.rx_buffer, tlen, ESP_LOG_INFO); + TEST_ASSERT_EQUAL_HEX8_ARRAY(mst_trans.tx_buffer, slv_trans.rx_buffer, tlen); + + + ESP_LOGI("spi", "=========== TEST(%d) Master RX, Slave TX ==========", i); + //Slave TX + memset(&slv_trans, 0x0, sizeof(spi_slave_transaction_t)); + + slv_trans.length = rlen * 8; + slv_trans.tx_buffer = spitest_slave_send + rlen * 8; + TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slv_trans, portMAX_DELAY)); + + //Master RX + memset(&mst_trans, 0x0, sizeof(spi_transaction_t)); + memset(master_rx_buffer, 0x66, sizeof(master_rx_buffer)); + mst_trans.rxlength = rlen * 8; + mst_trans.rx_buffer = master_rx_buffer; + TEST_ESP_OK(spi_device_transmit(spi, &mst_trans)); + + TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret, portMAX_DELAY)); + TEST_ASSERT(ret == &slv_trans); + + ESP_LOG_BUFFER_HEXDUMP("slave tx", slv_trans.tx_buffer, rlen, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("master rx", mst_trans.rx_buffer, rlen, ESP_LOG_INFO); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(slv_trans.tx_buffer, mst_trans.rx_buffer, rlen); } spi_slave_free(TEST_SLAVE_HOST); master_free_device_bus(spi); } -#endif //!DISABLED_FOR_TARGETS(ESP32C3) //There is only one GPSPI controller, so single-board test is disabled. +#endif //#if (TEST_SPI_PERIPH_NUM >= 2) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP8684) +//TODO IDF-4455 +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP8684, ESP32H2) //These tests are ESP32 only due to lack of runners /******************************************************************************** * Test SIO Master & Slave @@ -228,6 +262,4 @@ void test_sio_slave(void) } TEST_CASE_MULTIPLE_DEVICES("sio mode", "[spi][test_env=Example_SPI_Multi_device]", test_sio_master, test_sio_slave); -#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3) - -#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) +#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP8684, ESP32H2) diff --git a/components/driver/test/test_spi_slave.c b/components/driver/test/test_spi_slave.c index 9b645a86be..571bd97562 100644 --- a/components/driver/test/test_spi_slave.c +++ b/components/driver/test/test_spi_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,11 +17,9 @@ #include "esp_log.h" #include "esp_rom_gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) -// TODO: SPI SUPPORT IDF-4024 -//There is only one GPSPI controller, so single-board test is disabled. -#if !DISABLED_FOR_TARGETS(ESP32C3) +#if (TEST_SPI_PERIPH_NUM >= 2) +//These will only be enabled on chips with 2 or more SPI peripherals #ifndef CONFIG_SPIRAM //This test should be removed once the timing test is merged. @@ -261,15 +259,15 @@ TEST_CASE("test slave send unaligned","[spi]") #endif // !CONFIG_SPIRAM -#endif // !TEMPORARY_DISABLED_FOR_TARGETS +#endif // #if (TEST_SPI_PERIPH_NUM >= 2) - -#if !DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) +#if (TEST_SPI_PERIPH_NUM == 1) //These tests are for chips which only have 1 SPI controller /******************************************************************************** * Test By Master & Slave (2 boards) * - * PIN | Master(C3) | Slave (C3) | + * Master (C3, 8684, H2) && Slave (C3, 8684, H2): + * PIN | Master | Slave | * ----| --------- | --------- | * CS | 10 | 10 | * CLK | 6 | 6 | @@ -385,6 +383,4 @@ static void unaligned_test_slave(void) TEST_CASE_MULTIPLE_DEVICES("SPI_Slave_Unaligned_Test", "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]", unaligned_test_master, unaligned_test_slave); -#endif //#if !DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) - -#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) +#endif //#if (TEST_SPI_PERIPH_NUM == 1) diff --git a/components/driver/test/test_spi_slave_hd.c b/components/driver/test/test_spi_slave_hd.c index b52e3bdb45..bd098d6c6d 100644 --- a/components/driver/test/test_spi_slave_hd.c +++ b/components/driver/test/test_spi_slave_hd.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,11 +17,9 @@ #include "driver/spi_master.h" #include "esp_serial_slave_link/essl_spi.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) -// TODO: SPI SUPPORT IDF-4024 -#if !DISABLED_FOR_TARGETS(ESP32C3) -//There is only one GPSPI controller on ESP32C3, so single-board test is disabled. +#if (TEST_SPI_PERIPH_NUM >= 2) +//These will be only enabled on chips with 2 or more SPI peripherals #if SOC_SPI_SUPPORT_SLAVE_HD_VER2 #include "driver/spi_slave_hd.h" @@ -598,15 +596,17 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]" } #endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2 -#endif //#if !DISABLED_FOR_TARGETS(ESP32C3) +#endif //#if (TEST_SPI_PERIPH_NUM >= 2) -#if !DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) + +#if (TEST_SPI_PERIPH_NUM == 1) #if SOC_SPI_SUPPORT_SLAVE_HD_VER2 //These tests are for chips which only have 1 SPI controller /******************************************************************************** * Test By Master & Slave (2 boards) * - * PIN | Master(C3) | Slave (C3) | + * Master (C3, 8684, H2) && Slave (C3, 8684, H2): + * PIN | Master | Slave | * ----| --------- | --------- | * CS | 10 | 10 | * CLK | 6 | 6 | @@ -752,6 +752,4 @@ TEST_CASE_MULTIPLE_DEVICES("SPI Slave HD: segment mode, master sends too long", #endif //#if SOC_SPI_SUPPORT_SLAVE_HD_VER2 -#endif //#if !DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) - -#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) +#endif //#if (TEST_SPI_PERIPH_NUM == 1) diff --git a/components/hal/esp8684/include/hal/spi_ll.h b/components/hal/esp8684/include/hal/spi_ll.h index a82a197f93..ac7392c9b5 100644 --- a/components/hal/esp8684/include/hal/spi_ll.h +++ b/components/hal/esp8684/include/hal/spi_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -82,7 +82,26 @@ FLAG_ATTR(spi_ll_trans_len_cond_t) */ static inline void spi_ll_master_init(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + //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 unneeded ints + hw->slave.val = 0; + hw->user.val = 0; + + hw->clk_gate.clk_en = 1; + hw->clk_gate.mst_clk_active = 1; + hw->clk_gate.mst_clk_sel = 1; + + hw->dma_conf.val = 0; + hw->dma_conf.tx_seg_trans_clr_en = 1; + hw->dma_conf.rx_seg_trans_clr_en = 1; + hw->dma_conf.dma_seg_trans_en = 0; } /** @@ -92,7 +111,25 @@ static inline void spi_ll_master_init(spi_dev_t *hw) */ static inline void spi_ll_slave_init(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + //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_seg_trans_en = 0; + + //Disable unneeded ints + hw->dma_int_ena.val &= ~SPI_LL_UNUSED_INT_MASK; } /** @@ -102,7 +139,15 @@ static inline void spi_ll_slave_init(spi_dev_t *hw) */ static inline void spi_ll_slave_hd_init(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + 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; } /** @@ -114,7 +159,7 @@ static inline void spi_ll_slave_hd_init(spi_dev_t *hw) */ static inline bool spi_ll_usr_is_done(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + return hw->dma_int_raw.trans_done; } /** @@ -125,7 +170,9 @@ static inline bool spi_ll_usr_is_done(spi_dev_t *hw) */ static inline void spi_ll_master_user_start(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->cmd.update = 1; + while (hw->cmd.update); + hw->cmd.usr = 1; } /** @@ -135,7 +182,7 @@ static inline void spi_ll_master_user_start(spi_dev_t *hw) */ static inline void spi_ll_slave_user_start(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->cmd.usr = 1; } /** @@ -147,7 +194,7 @@ static inline void spi_ll_slave_user_start(spi_dev_t *hw) */ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + return hw->cmd.val; } /** @@ -157,7 +204,8 @@ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw) */ static inline void spi_ll_slave_reset(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->slave.soft_reset = 1; + hw->slave.soft_reset = 0; } /** @@ -169,7 +217,8 @@ static inline void spi_ll_slave_reset(spi_dev_t *hw) */ static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.buf_afifo_rst = 1; + hw->dma_conf.buf_afifo_rst = 0; } /** @@ -181,7 +230,8 @@ static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw) */ static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.rx_afifo_rst = 1; + hw->dma_conf.rx_afifo_rst = 0; } /** @@ -191,7 +241,8 @@ static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw) */ static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.dma_afifo_rst = 1; + hw->dma_conf.dma_afifo_rst = 0; } /** @@ -201,7 +252,8 @@ static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw) */ static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.rx_afifo_rst = 1; + hw->dma_conf.rx_afifo_rst = 0; } /** @@ -211,7 +263,7 @@ static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw) */ static inline void spi_ll_infifo_full_clr(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_clr.infifo_full_err = 1; } /** @@ -221,7 +273,7 @@ static inline void spi_ll_infifo_full_clr(spi_dev_t *hw) */ static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_clr.outfifo_empty_err = 1; } /*------------------------------------------------------------------------------ @@ -235,7 +287,7 @@ static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw) */ static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.dma_rx_ena = enable; } /** @@ -246,7 +298,7 @@ static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable) */ static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.dma_tx_ena = enable; } /** @@ -257,7 +309,7 @@ static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable) */ static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_conf.rx_eof_en = enable; } /*------------------------------------------------------------------------------ @@ -272,7 +324,12 @@ static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable) */ static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_send, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + 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)] = word; + } } /** @@ -285,7 +342,29 @@ static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_s */ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len) { - abort(); // TODO: SPI support IDF-4024 + 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]; //read + } + memcpy(((uint8_t *)&word) + offset, data, copy_len); //modify + hw->data_buf[byte_id / 4] = word; //write + + data += copy_len; + byte_id += copy_len; + len -= copy_len; + } } /** @@ -297,7 +376,15 @@ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t */ static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + 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]; + int len = bitlen - x; + if (len > 32) { + len = 32; + } + memcpy(&buffer_to_rcv[x / 8], &word, (len + 7) / 8); + } } /** @@ -310,7 +397,19 @@ static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, siz */ static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *out_data, int len) { - abort(); // TODO: SPI support IDF-4024 + while (len > 0) { + uint32_t word = hw->data_buf[byte_id / 4]; + 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; + } } /*------------------------------------------------------------------------------ @@ -325,7 +424,11 @@ static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t * */ static inline void spi_ll_master_set_pos_cs(spi_dev_t *hw, int cs, uint32_t pos_cs) { - abort(); // TODO: SPI support IDF-4024 + if (pos_cs) { + hw->misc.master_cs_pol |= (1 << cs); + } else { + hw->misc.master_cs_pol &= ~(1 << cs); + } } /** @@ -358,7 +461,20 @@ static inline void spi_ll_set_rx_lsbfirst(spi_dev_t *hw, bool lsbfirst) */ static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode) { - abort(); // TODO: SPI support IDF-4024 + //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; + } } /** @@ -369,7 +485,28 @@ static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode) */ static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma_used) { - abort(); // TODO: SPI support IDF-4024 + 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; } /** @@ -380,7 +517,7 @@ static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma */ static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex) { - abort(); // TODO: SPI support IDF-4024 + hw->user.doutdin = !half_duplex; } /** @@ -393,7 +530,7 @@ static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex) */ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) { - abort(); // TODO: SPI support IDF-4024 + hw->user.sio = sio_mode; } /** @@ -404,7 +541,16 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) */ static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - abort(); // TODO: SPI support IDF-4024 + 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); } /** @@ -426,7 +572,12 @@ static inline void spi_ll_slave_set_seg_mode(spi_dev_t *hw, bool seg_trans) */ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) { - abort(); // TODO: SPI support IDF-4024 + 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; } /** @@ -451,7 +602,7 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) */ static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_clock_val_t *val) { - abort(); // TODO: SPI support IDF-4024 + hw->clock.val = *(uint32_t *)val; } /** @@ -465,7 +616,7 @@ static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_cl */ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) { - abort(); // TODO: SPI support IDF-4024 + return (fapb / (pre * n)); } /** @@ -480,7 +631,66 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - abort(); // TODO: SPI support IDF-4024 +typeof(GPSPI2.clock) reg; + 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; } /** @@ -500,7 +710,10 @@ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ */ static inline int spi_ll_master_set_clock(spi_dev_t *hw, int fapb, int hz, int duty_cycle) { - abort(); // TODO: SPI support IDF-4024 + 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; } /** @@ -537,7 +750,8 @@ static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int dela */ static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold) { - abort(); // TODO: SPI support IDF-4024 + hw->user1.cs_hold_time = hold; + hw->user.cs_hold = hold ? 1 : 0; } /** @@ -551,7 +765,8 @@ static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold) */ static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup) { - abort(); // TODO: SPI support IDF-4024 + hw->user1.cs_setup_time = setup - 1; + hw->user.cs_setup = setup ? 1 : 0; } /*------------------------------------------------------------------------------ @@ -566,7 +781,9 @@ static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup) */ static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + if (bitlen > 0) { + hw->ms_dlen.ms_data_bitlen = bitlen - 1; + } } /** @@ -577,7 +794,9 @@ static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen) */ static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + if (bitlen > 0) { + hw->ms_dlen.ms_data_bitlen = bitlen - 1; + } } /** @@ -588,7 +807,7 @@ static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen) */ static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + //This is not used in esp8684 } /** @@ -599,7 +818,7 @@ static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen) */ static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen) { - abort(); // TODO: SPI support IDF-4024 + //This is not used in esp8684 } /** @@ -613,7 +832,8 @@ static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen) */ static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen) { - abort(); // TODO: SPI support IDF-4024 + hw->user2.usr_command_bitlen = bitlen - 1; + hw->user.usr_command = bitlen ? 1 : 0; } /** @@ -627,7 +847,8 @@ static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen) */ static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen) { - abort(); // TODO: SPI support IDF-4024 + hw->user1.usr_addr_bitlen = bitlen - 1; + hw->user.usr_addr = bitlen ? 1 : 0; } /** @@ -642,7 +863,21 @@ static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen) */ static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, uint32_t lsbfirst) { - abort(); // TODO: SPI support IDF-4024 + 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 = addr; + } else { + // shift the address to MSB of addr register. + // output address will be sent from MSB to LSB of addr register + hw->addr = addr << (32 - addrlen); + } } /** @@ -657,7 +892,16 @@ static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, */ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst) { - abort(); // TODO: SPI support IDF-4024 + 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)); + } } /** @@ -671,7 +915,8 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b */ static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { - abort(); // TODO: SPI support IDF-4024 + hw->user.usr_dummy = dummy_n ? 1 : 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -682,7 +927,7 @@ static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) */ static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable) { - abort(); // TODO: SPI support IDF-4024 + hw->user.usr_miso = enable; } /** @@ -693,7 +938,7 @@ static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable) */ static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable) { - abort(); // TODO: SPI support IDF-4024 + hw->user.usr_mosi = enable; } /** @@ -705,7 +950,7 @@ static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable) */ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + return hw->slave1.data_bitlen; } /*------------------------------------------------------------------------------ @@ -714,16 +959,16 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) //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, dma_int_raw.trans_done, dma_int_clr.trans_done=1) \ - item(SPI_LL_INTR_RDBUF, dma_int_ena.rd_buf_done, dma_int_raw.rd_buf_done, dma_int_clr.rd_buf_done=1) \ - item(SPI_LL_INTR_WRBUF, dma_int_ena.wr_buf_done, dma_int_raw.wr_buf_done, dma_int_clr.wr_buf_done=1) \ - item(SPI_LL_INTR_RDDMA, dma_int_ena.rd_dma_done, dma_int_raw.rd_dma_done, dma_int_clr.rd_dma_done=1) \ - item(SPI_LL_INTR_WRDMA, dma_int_ena.wr_dma_done, dma_int_raw.wr_dma_done, dma_int_clr.wr_dma_done=1) \ - item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done, dma_int_raw.dma_seg_trans_done, dma_int_clr.dma_seg_trans_done=1) \ - item(SPI_LL_INTR_CMD7, dma_int_ena.cmd7, dma_int_raw.cmd7, dma_int_clr.cmd7=1) \ - item(SPI_LL_INTR_CMD8, dma_int_ena.cmd8, dma_int_raw.cmd8, dma_int_clr.cmd8=1) \ - item(SPI_LL_INTR_CMD9, dma_int_ena.cmd9, dma_int_raw.cmd9, dma_int_clr.cmd9=1) \ - item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda=1) + item(SPI_LL_INTR_TRANS_DONE, dma_int_ena.trans_done, dma_int_raw.trans_done, dma_int_clr.trans_done, dma_int_set.trans_done_int_set) \ + item(SPI_LL_INTR_RDBUF, dma_int_ena.rd_buf_done, dma_int_raw.rd_buf_done, dma_int_clr.rd_buf_done, dma_int_set.rd_buf_done_int_set) \ + item(SPI_LL_INTR_WRBUF, dma_int_ena.wr_buf_done, dma_int_raw.wr_buf_done, dma_int_clr.wr_buf_done, dma_int_set.wr_buf_done_int_set) \ + item(SPI_LL_INTR_RDDMA, dma_int_ena.rd_dma_done, dma_int_raw.rd_dma_done, dma_int_clr.rd_dma_done, dma_int_set.rd_dma_done_int_set) \ + item(SPI_LL_INTR_WRDMA, dma_int_ena.wr_dma_done, dma_int_raw.wr_dma_done, dma_int_clr.wr_dma_done, dma_int_set.wr_dma_done_int_set) \ + item(SPI_LL_INTR_SEG_DONE, dma_int_ena.dma_seg_trans_done, dma_int_raw.dma_seg_trans_done, dma_int_clr.dma_seg_trans_done, dma_int_set.dma_seg_trans_done_int_set) \ + item(SPI_LL_INTR_CMD7, dma_int_ena.cmd7, dma_int_raw.cmd7, dma_int_clr.cmd7, dma_int_set.cmd7_int_set) \ + item(SPI_LL_INTR_CMD8, dma_int_ena.cmd8, dma_int_raw.cmd8, dma_int_clr.cmd8, dma_int_set.cmd8_int_set) \ + item(SPI_LL_INTR_CMD9, dma_int_ena.cmd9, dma_int_raw.cmd9, dma_int_clr.cmd9, dma_int_set.cmd9_int_set) \ + item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda, dma_int_set.cmda_int_set) static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) @@ -742,21 +987,21 @@ static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { -#define SET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit)) hw->st_reg = 1; +#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; +#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; +#define GET_INTR(intr_bit, _, raw_reg, ...) if (intr_mask & (intr_bit) && hw->raw_reg) return true; FOR_EACH_ITEM(GET_INTR, INTR_LIST); return false; #undef GET_INTR @@ -772,7 +1017,7 @@ static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) */ static inline void spi_ll_disable_int(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_ena.trans_done = 0; } /** @@ -782,7 +1027,7 @@ static inline void spi_ll_disable_int(spi_dev_t *hw) */ static inline void spi_ll_clear_int_stat(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_clr.trans_done = 1; } /** @@ -792,7 +1037,7 @@ static inline void spi_ll_clear_int_stat(spi_dev_t *hw) */ static inline void spi_ll_set_int_stat(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_set.trans_done_int_set = 1; } /** @@ -802,7 +1047,7 @@ static inline void spi_ll_set_int_stat(spi_dev_t *hw) */ static inline void spi_ll_enable_int(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + hw->dma_int_ena.trans_done = 1; } /*------------------------------------------------------------------------------ @@ -810,17 +1055,20 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) *----------------------------------------------------------------------------*/ static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) { - abort(); // TODO: SPI support IDF-4024 + hw->slave.rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; + hw->slave.wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; + hw->slave.rddma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDDMA) ? 1 : 0; + hw->slave.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) { - abort(); // TODO: SPI support IDF-4024 + return hw->slave1.data_bitlen / 8; } static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { - abort(); // TODO: SPI support IDF-4024 + return hw->slave1.last_addr; } #undef SPI_LL_RST_MASK diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index 5be7db32ea..8950e26dac 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -44,10 +36,12 @@ * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration */ typedef struct { + spi_clock_source_t clk_sel; ///< Select SPI clock source + uint32_t clk_src_hz; ///< Selected SPI clock source speed in Hz uint32_t half_duplex; ///< Whether half duplex mode is used, device specific uint32_t no_compensate; ///< No need to add dummy to compensate the timing, device specific - uint32_t clock_speed_hz; ///< Desired frequency. - uint32_t duty_cycle; ///< Desired duty cycle of SPI clock + uint32_t expected_freq; ///< Expected frequency in Hz. + uint32_t duty_cycle; ///< Expected duty cycle of SPI clock uint32_t input_delay_ns; /**< Maximum delay between SPI launch clock and the data to be valid. * This is used to compensate/calculate the maximum frequency allowed. * Left 0 if not known. @@ -151,7 +145,7 @@ typedef struct { uint32_t tx_lsbfirst : 1; ///< Whether LSB is sent first for TX data, device specific uint32_t rx_lsbfirst : 1; ///< Whether LSB is received first for RX data, device specific uint32_t no_compensate : 1; ///< No need to add dummy to compensate the timing, device specific -#if SOC_SPI_SUPPORT_AS_CS +#if SOC_SPI_AS_CS_SUPPORTED uint32_t as_cs : 1; ///< Whether to toggle the CS while the clock toggles, device specific #endif uint32_t positive_cs : 1; ///< Whether the postive CS feature is abled, device specific diff --git a/components/hal/include/hal/spi_types.h b/components/hal/include/hal/spi_types.h index 300d7da46d..37e9e53787 100644 --- a/components/hal/include/hal/spi_types.h +++ b/components/hal/include/hal/spi_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,11 @@ typedef enum { SPI_HOST_MAX, ///< invalid host value } spi_host_device_t; +typedef enum { + SPI_CLK_APB, ///< Select APB as the source clock + SPI_CLK_XTAL ///< Select XTAL as the source clock +} spi_clock_source_t; + /// SPI Events typedef enum { /* Slave HD Only */ diff --git a/components/hal/spi_hal.c b/components/hal/spi_hal.c index be12d2065c..495e0129d4 100644 --- a/components/hal/spi_hal.c +++ b/components/hal/spi_hal.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The HAL layer for SPI (common part) @@ -85,7 +77,9 @@ esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int { spi_hal_timing_conf_t temp_conf; - int eff_clk_n = spi_ll_master_cal_clock(SPI_LL_PERIPH_CLK_FREQ, timing_param->clock_speed_hz, timing_param->duty_cycle, &temp_conf.clock_reg); + int clk_src_freq_hz = timing_param->clk_src_hz; + assert((clk_src_freq_hz == 80 * 1000 * 1000) || (clk_src_freq_hz == 40 * 1000 * 1000)); + int eff_clk_n = spi_ll_master_cal_clock(clk_src_freq_hz, timing_param->expected_freq, timing_param->duty_cycle, &temp_conf.clock_reg); //When the speed is too fast, we may need to use dummy cycles to compensate the reading. //But these don't work for full-duplex connections. diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index e36a3ebd43..a843240226 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The HAL layer for SPI (common part, in iram) // make these functions in a seperate file to make sure all LL functions are in the IRAM. @@ -40,7 +32,7 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de { //Configure clock settings spi_dev_t *hw = hal->hw; -#if SOC_SPI_SUPPORT_AS_CS +#if SOC_SPI_AS_CS_SUPPORTED spi_ll_master_set_cksel(hw, dev->cs_pin_id, dev->as_cs); #endif spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs); diff --git a/components/idf_test/include/esp32/idf_performance_target.h b/components/idf_test/include/esp32/idf_performance_target.h index 5700d9f39e..d214d3b489 100644 --- a/components/idf_test/include/esp32/idf_performance_target.h +++ b/components/idf_test/include/esp32/idf_performance_target.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -30,6 +22,8 @@ #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 90000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 870000 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 30 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 27 diff --git a/components/idf_test/include/esp32c3/idf_performance_target.h b/components/idf_test/include/esp32c3/idf_performance_target.h index c77e3efb1e..d817c32988 100644 --- a/components/idf_test/include/esp32c3/idf_performance_target.h +++ b/components/idf_test/include/esp32c3/idf_performance_target.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -26,6 +18,8 @@ #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 670000 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30 diff --git a/components/idf_test/include/esp32h2/idf_performance_target.h b/components/idf_test/include/esp32h2/idf_performance_target.h index af5738d1fc..0a0370612f 100644 --- a/components/idf_test/include/esp32h2/idf_performance_target.h +++ b/components/idf_test/include/esp32h2/idf_performance_target.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -26,6 +18,8 @@ #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 670000 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30 diff --git a/components/idf_test/include/esp32s2/idf_performance_target.h b/components/idf_test/include/esp32s2/idf_performance_target.h index dc8a060f54..65cf74ea8f 100644 --- a/components/idf_test/include/esp32s2/idf_performance_target.h +++ b/components/idf_test/include/esp32s2/idf_performance_target.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,8 @@ #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 62000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 800000 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30 diff --git a/components/idf_test/include/esp32s3/idf_performance_target.h b/components/idf_test/include/esp32s3/idf_performance_target.h index b744cda8fa..8fcb334c62 100644 --- a/components/idf_test/include/esp32s3/idf_performance_target.h +++ b/components/idf_test/include/esp32s3/idf_performance_target.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,8 @@ #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 80000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 1500000 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30 diff --git a/components/idf_test/include/esp8684/idf_performance_target.h b/components/idf_test/include/esp8684/idf_performance_target.h index 790074f410..82407190c1 100644 --- a/components/idf_test/include/esp8684/idf_performance_target.h +++ b/components/idf_test/include/esp8684/idf_performance_target.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,8 +18,10 @@ #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 670000 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32 -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 20 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 45 +#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 40 /* * Flash Performance value diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index b558feb4ca..32ca1fdf1d 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -20,13 +20,6 @@ #define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1000 #endif -#ifndef IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 15 -#endif -#ifndef IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA -#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 15 -#endif - /* Due to code size & linker layout differences interacting with cache, VFS microbenchmark currently runs slower with PSRAM enabled. */ #ifndef IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index b293331fc6..e8167fa931 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -407,6 +407,14 @@ config SOC_SIGMADELTA_CHANNEL_NUM int default 8 +config SOC_SPI_HD_BOTH_INOUT_SUPPORTED + bool + default y + +config SOC_SPI_AS_CS_SUPPORTED + bool + default y + config SOC_SPI_PERIPH_NUM int default 3 @@ -423,10 +431,6 @@ config SOC_SPI_MAX_PRE_DIVIDER int default 8192 -config SOC_SPI_SUPPORT_AS_CS - bool - default y - config SOC_TIMER_GROUPS int default 2 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 39521e4426..1efa79cf41 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -237,15 +237,17 @@ #define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels /*-------------------------- SPI CAPS ----------------------------------------*/ -#define SOC_SPI_PERIPH_NUM 3 -#define SOC_SPI_DMA_CHAN_NUM 2 +#define SOC_SPI_HD_BOTH_INOUT_SUPPORTED 1 //Support enabling MOSI and MISO phases together under Halfduplex mode +#define SOC_SPI_AS_CS_SUPPORTED 1 //Support to toggle the CS while the clock toggles +#define SOC_SPI_PERIPH_NUM 3 +#define SOC_SPI_DMA_CHAN_NUM 2 -#define SOC_SPI_PERIPH_CS_NUM(i) 3 +#define SOC_SPI_PERIPH_CS_NUM(i) 3 + +#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define SOC_SPI_MAX_PRE_DIVIDER 8192 -#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 -#define SOC_SPI_MAX_PRE_DIVIDER 8192 -#define SOC_SPI_SUPPORT_AS_CS 1 //Support to toggle the CS while the clock toggles // Peripheral supports DIO, DOUT, QIO, or QOUT #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(spi_host) ({(void)spi_host; 1;}) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index c26a6e4692..e14c8500cb 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -451,6 +451,10 @@ config SOC_SIGMADELTA_CHANNEL_NUM int default 8 +config SOC_SPI_HD_BOTH_INOUT_SUPPORTED + bool + default y + config SOC_SPI_PERIPH_NUM int default 3 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index cb8b6c75eb..9374d84e37 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -220,14 +220,14 @@ #define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels /*-------------------------- SPI CAPS ----------------------------------------*/ -#define SOC_SPI_PERIPH_NUM 3 -#define SOC_SPI_DMA_CHAN_NUM 3 -#define SOC_SPI_PERIPH_CS_NUM(i) (((i)==0)? 2: (((i)==1)? 6: 3)) +#define SOC_SPI_HD_BOTH_INOUT_SUPPORTED 1 //Support enabling MOSI and MISO phases together under Halfduplex mode +#define SOC_SPI_PERIPH_NUM 3 +#define SOC_SPI_DMA_CHAN_NUM 3 +#define SOC_SPI_PERIPH_CS_NUM(i) (((i)==0)? 2: (((i)==1)? 6: 3)) -#define SOC_SPI_MAXIMUM_BUFFER_SIZE 72 -#define SOC_SPI_MAX_PRE_DIVIDER 8192 +#define SOC_SPI_MAXIMUM_BUFFER_SIZE 72 +#define SOC_SPI_MAX_PRE_DIVIDER 8192 -//#define SOC_SPI_SUPPORT_AS_CS //don't support to toggle the CS while the clock toggles #define SOC_SPI_SUPPORT_DDRCLK 1 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 #define SOC_SPI_SUPPORT_CD_SIG 1 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index d4d79083ef..3cd05c3311 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -539,10 +539,6 @@ config SOC_SPI_PERIPH_NUM int default 3 -config SOC_SPI_DMA_CHAN_NUM - int - default 3 - config SOC_SPI_MAXIMUM_BUFFER_SIZE int default 64 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 7001f57762..527f0759a4 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -202,7 +202,6 @@ /*-------------------------- SPI CAPS ----------------------------------------*/ #define SOC_SPI_PERIPH_NUM 3 -#define SOC_SPI_DMA_CHAN_NUM 3 #define SOC_SPI_PERIPH_CS_NUM(i) 3 #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 #define SOC_SPI_SUPPORT_DDRCLK 1 diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 2e6ffe15da..411510464f 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -7,7 +7,7 @@ SPI Master driver is a program that controls {IDF_TARGET_NAME}'s SPI peripherals Overview of {IDF_TARGET_NAME}'s SPI peripherals ----------------------------------------------- -{IDF_TARGET_MAX_PERIPH_NUM:default="4", esp32c3="3"} +{IDF_TARGET_MAX_PERIPH_NUM:default="4", esp32c3="3", esp8684="3"} {IDF_TARGET_SPI2_CS_NUM:default="6", esp32="3"} {IDF_TARGET_SPI3_CS_NUM:default="3"} @@ -32,7 +32,7 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals - SPI2 and SPI3 are general purpose SPI controllers. They are open to users. SPI2 and SPI3 have independent signal buses with the same respective names. SPI2 has {IDF_TARGET_SPI2_CS_NUM} CS lines. SPI3 has {IDF_TARGET_SPI3_CS_NUM} CS lines. Each CS line can be used to drive one SPI slave. -.. only:: esp32c3 +.. only:: esp32c3 or esp8684 - SPI2 is a general purpose SPI controller. It has an independent signal bus with the same name. The bus has {IDF_TARGET_SPI2_CS_NUM} CS lines to drive up to {IDF_TARGET_SPI2_CS_NUM} SPI slaves. @@ -230,7 +230,7 @@ If using more than one data lines to transmit, please set `SPI_DEVICE_HALFDUPLEX Half-duplex transactions with both read and write phases are not supported when using DMA. For details and workarounds, see :ref:`spi_known_issues`. -.. only:: esp32s3 or esp32c3 +.. only:: esp32s3 or esp32c3 or esp8684 .. note:: @@ -439,10 +439,10 @@ The main parameter that determines the transfer speed for large transactions is Transaction Duration ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26"} -{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11"} -{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24"} -{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9"} +{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26", esp8684="42"} +{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11", esp8684="17"} +{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp8684="40"} +{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp8684="15"} Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction. diff --git a/docs/en/api-reference/peripherals/spi_slave.rst b/docs/en/api-reference/peripherals/spi_slave.rst index 9eac56573e..4cce72ac36 100644 --- a/docs/en/api-reference/peripherals/spi_slave.rst +++ b/docs/en/api-reference/peripherals/spi_slave.rst @@ -18,7 +18,7 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals SPI2 and SPI3 have independent signal buses with the same respective names. -.. only:: esp32c3 +.. only:: esp32c3 or esp8684 {IDF_TARGET_NAME} integrates one general purpose SPI controller which can be used as slave node driven by an off-chip SPI master. The controller is called SPI2 and has an independent signal bus with the same name. @@ -158,7 +158,7 @@ You can also configure a GPIO pin through which the Device will signal to the Ho SCLK Frequency Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_MAX_FREQ:default="40", esp32="10", esp32s2="40", esp32c3="60", esp32s3="60} +{IDF_TARGET_MAX_FREQ:default="60", esp32="10", esp32s2="40"} The SPI slaves are designed to operate at up to {IDF_TARGET_MAX_FREQ} MHz. The data cannot be recognized or received correctly if the clock is too fast or does not have a 50% duty cycle. diff --git a/examples/peripherals/spi_slave_hd/segment_mode/README.md b/examples/peripherals/spi_slave_hd/segment_mode/README.md index 5e1715f466..0618904a37 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/README.md +++ b/examples/peripherals/spi_slave_hd/segment_mode/README.md @@ -21,7 +21,8 @@ Following is the connection between 2 ESP32S2 boards: | SCLK | GPIO12 | GPIO12 | | CS | GPIO10 | GPIO10 | -(Feel free to change the GPIO settings by editing the macro definations at the top of ``app_main.c`` files.) +Plase refer to the macro definations at the top of ``app_main.c`` files, to know the connection on different chips. +Feel free to change the GPIO settings by editing the macro definations. ### Build and Flash diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c index c9035069b7..622efd959c 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c @@ -15,12 +15,12 @@ #include "esp_serial_slave_link/essl_spi.h" //Pin setting -#if !CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define GPIO_MOSI 11 #define GPIO_MISO 13 #define GPIO_SCLK 12 #define GPIO_CS 10 -#else +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP8684 #define GPIO_MOSI 7 #define GPIO_MISO 2 #define GPIO_SCLK 6 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 5d650cc9d3..f63e06766a 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-S2 | -| ----------------- | -------- | +| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-C3 | ESP8684 | +| ----------------- | -------- | -------- | -------- | ------- | diff --git a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c index 219f08ef60..b0f1d2081e 100644 --- a/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c +++ b/examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c @@ -16,16 +16,21 @@ #define TIME_IS_OUT(start, end, timeout) (timeout) > ((end)-(start)) ? 0 : 1 //Pin setting -#ifdef CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define GPIO_MOSI 11 #define GPIO_MISO 13 #define GPIO_SCLK 12 #define GPIO_CS 10 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP8684 +#define GPIO_MOSI 7 +#define GPIO_MISO 2 +#define GPIO_SCLK 6 +#define GPIO_CS 10 +#endif #define SLAVE_HOST SPI2_HOST #define DMA_CHAN SPI_DMA_CH_AUTO #define QUEUE_SIZE 4 -#endif /** * Helper Macros for Master-Slave synchronization, each setting is 4-byte-width diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index a83f04094c..e74a63ea6d 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1125,7 +1125,6 @@ components/hal/include/hal/soc_hal.h components/hal/include/hal/spi_flash_encrypt_hal.h components/hal/include/hal/spi_flash_hal.h components/hal/include/hal/spi_flash_types.h -components/hal/include/hal/spi_hal.h components/hal/include/hal/spi_slave_hal.h components/hal/include/hal/spi_slave_hd_hal.h components/hal/include/hal/systimer_hal.h @@ -1157,8 +1156,6 @@ components/hal/soc_hal.c components/hal/spi_flash_encrypt_hal_iram.c components/hal/spi_flash_hal.c components/hal/spi_flash_hal_gpspi.c -components/hal/spi_hal.c -components/hal/spi_hal_iram.c components/hal/spi_slave_hal.c components/hal/spi_slave_hal_iram.c components/hal/spi_slave_hd_hal.c @@ -1195,9 +1192,6 @@ components/heap/test/test_realloc.c components/heap/test/test_runtime_heap_reg.c components/heap/test_multi_heap_host/main.cpp components/heap/test_multi_heap_host/test_multi_heap.cpp -components/idf_test/include/esp32/idf_performance_target.h -components/idf_test/include/esp32c3/idf_performance_target.h -components/idf_test/include/esp32h2/idf_performance_target.h components/idf_test/include/idf_performance.h components/linux/include/sys/queue.h components/log/esp_log_private.h