Merge branch 'feature/support_spi_on_8684' into 'master'

spi: support spi on 8684

Closes IDF-4470 and IDF-4024

See merge request espressif/esp-idf!16475
This commit is contained in:
Armando (Dou Yiwen) 2022-01-12 09:10:21 +00:00
commit 342c830d9b
34 changed files with 616 additions and 365 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;
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)

View File

@ -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)

View File

@ -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)

View File

@ -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, &reg_val);
spi_ll_master_set_clock_by_reg(hw, &reg_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

View File

@ -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

View File

@ -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 */

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,6 +237,8 @@
#define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels
/*-------------------------- SPI CAPS ----------------------------------------*/
#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
@ -245,7 +247,7 @@
#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;})

View File

@ -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

View File

@ -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,6 +220,7 @@
#define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels
/*-------------------------- SPI CAPS ----------------------------------------*/
#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))
@ -227,7 +228,6 @@
#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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32-S2 |
| ----------------- | -------- |
| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-C3 | ESP8684 |
| ----------------- | -------- | -------- | -------- | ------- |

View File

@ -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

View File

@ -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