Merge branch 'feature/esp32p4_hp_spi_support' into 'master'

Feature/esp32p4 hp spi master driver support

Closes IDF-7502

See merge request espressif/esp-idf!24963
This commit is contained in:
Wan Lei 2023-10-09 18:37:35 +08:00
commit f92b18053a
52 changed files with 1937 additions and 806 deletions

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -12,6 +12,7 @@
#include "driver/spi_common.h" #include "driver/spi_common.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "hal/spi_types.h" #include "hal/spi_types.h"
#include "hal/dma_types.h"
#include "esp_pm.h" #include "esp_pm.h"
#if SOC_GDMA_SUPPORTED #if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h" #include "esp_private/gdma.h"
@ -45,6 +46,13 @@ extern "C"
#define BUS_LOCK_DEBUG_EXECUTE_CHECK(x) #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)
#endif #endif
#if SOC_GPSPI_SUPPORTED && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
#define DMA_DESC_MEM_ALIGN_SIZE 8
typedef dma_descriptor_align8_t spi_dma_desc_t;
#else
#define DMA_DESC_MEM_ALIGN_SIZE 4
typedef dma_descriptor_align4_t spi_dma_desc_t;
#endif
struct spi_bus_lock_t; struct spi_bus_lock_t;
struct spi_bus_lock_dev_t; struct spi_bus_lock_dev_t;
@ -56,22 +64,21 @@ typedef struct spi_bus_lock_dev_t* spi_bus_lock_dev_handle_t;
/// Background operation control function /// Background operation control function
typedef void (*bg_ctrl_func_t)(void*); typedef void (*bg_ctrl_func_t)(void*);
typedef struct lldesc_s lldesc_t;
/// Attributes of an SPI bus /// Attributes of an SPI bus
typedef struct { typedef struct {
spi_bus_config_t bus_cfg; ///< Config used to initialize the bus spi_bus_config_t bus_cfg; ///< Config used to initialize the bus
uint32_t flags; ///< Flags (attributes) of the bus uint32_t flags; ///< Flags (attributes) of the bus
int max_transfer_sz; ///< Maximum length of bytes available to send int max_transfer_sz; ///< Maximum length of bytes available to send
bool dma_enabled; ///< To enable DMA or not bool dma_enabled; ///< To enable DMA or not
int tx_dma_chan; ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same uint16_t internal_mem_align_size; ///< Buffer align byte requirement for internal memory
int rx_dma_chan; ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same int tx_dma_chan; ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx. int rx_dma_chan; ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
lldesc_t *dmadesc_tx; ///< DMA descriptor array for TX int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
lldesc_t *dmadesc_rx; ///< DMA descriptor array for RX spi_dma_desc_t *dmadesc_tx; ///< DMA descriptor array for TX
spi_dma_desc_t *dmadesc_rx; ///< DMA descriptor array for RX
spi_bus_lock_handle_t lock; spi_bus_lock_handle_t lock;
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock; ///< Power management lock esp_pm_lock_handle_t pm_lock; ///< Power management lock
#endif #endif
} spi_bus_attr_t; } spi_bus_attr_t;

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -13,7 +13,6 @@
#include "esp_check.h" #include "esp_check.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "soc/lldesc.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
@ -26,6 +25,14 @@
#endif #endif
#if SOC_GDMA_SUPPORTED #if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h" #include "esp_private/gdma.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#endif
#if SOC_PERIPH_CLK_CTRL_SHARED
#define SPI_COMMON_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define SPI_COMMON_RCC_CLOCK_ATOMIC()
#endif #endif
static const char *SPI_TAG = "spi"; static const char *SPI_TAG = "spi";
@ -100,7 +107,15 @@ bool spicommon_periph_claim(spi_host_device_t host, const char* source)
bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true); bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true);
if (ret) { if (ret) {
spi_claiming_func[host] = source; spi_claiming_func[host] = source;
#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159
SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_ll_enable_bus_clock(host, true);
spi_ll_reset_register(host);
spi_ll_enable_clock(host, true);
}
#else
periph_module_enable(spi_periph_signal[host].module); periph_module_enable(spi_periph_signal[host].module);
#endif
} else { } else {
ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]); ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]);
} }
@ -117,7 +132,15 @@ bool spicommon_periph_free(spi_host_device_t host)
{ {
bool true_var = true; bool true_var = true;
bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false); bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false);
if (ret) periph_module_disable(spi_periph_signal[host].module); if (ret) {
#if CONFIG_IDF_TARGET_ESP32P4
SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_ll_enable_bus_clock(host, false);
}
#else
periph_module_disable(spi_periph_signal[host].module);
#endif
}
return ret; return ret;
} }
@ -218,6 +241,12 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
} }
#else //SOC_GDMA_SUPPORTED #else //SOC_GDMA_SUPPORTED
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB)
static esp_err_t (*spi_gdma_chan_allocator)(const gdma_channel_alloc_config_t *, gdma_channel_handle_t *) = gdma_new_ahb_channel;
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
static esp_err_t (*spi_gdma_chan_allocator)(const gdma_channel_alloc_config_t *, gdma_channel_handle_t *) = gdma_new_axi_channel;
#endif
static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan)
{ {
assert(is_valid_host(host_id)); assert(is_valid_host(host_id));
@ -231,19 +260,13 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
.flags.reserve_sibling = 1, .flags.reserve_sibling = 1,
.direction = GDMA_CHANNEL_DIRECTION_TX, .direction = GDMA_CHANNEL_DIRECTION_TX,
}; };
ret = gdma_new_channel(&tx_alloc_config, &ctx->tx_channel); ESP_RETURN_ON_ERROR(spi_gdma_chan_allocator(&tx_alloc_config, &ctx->tx_channel), SPI_TAG, "alloc gdma tx failed");
if (ret != ESP_OK) {
return ret;
}
gdma_channel_alloc_config_t rx_alloc_config = { gdma_channel_alloc_config_t rx_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_RX, .direction = GDMA_CHANNEL_DIRECTION_RX,
.sibling_chan = ctx->tx_channel, .sibling_chan = ctx->tx_channel,
}; };
ret = gdma_new_channel(&rx_alloc_config, &ctx->rx_channel); ESP_RETURN_ON_ERROR(spi_gdma_chan_allocator(&rx_alloc_config, &ctx->rx_channel), SPI_TAG, "alloc gdma rx failed");
if (ret != ESP_OK) {
return ret;
}
if (host_id == SPI2_HOST) { if (host_id == SPI2_HOST) {
gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2)); gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
@ -802,17 +825,22 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
bus_attr->tx_dma_chan = actual_tx_dma_chan; bus_attr->tx_dma_chan = actual_tx_dma_chan;
bus_attr->rx_dma_chan = actual_rx_dma_chan; bus_attr->rx_dma_chan = actual_rx_dma_chan;
int dma_desc_ct = lldesc_get_required_num(bus_config->max_transfer_sz); int dma_desc_ct = (bus_config->max_transfer_sz + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
bus_attr->max_transfer_sz = dma_desc_ct * LLDESC_MAX_NUM_PER_DESC; bus_attr->max_transfer_sz = dma_desc_ct * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
bus_attr->dmadesc_tx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA); bus_attr->dmadesc_tx = heap_caps_aligned_alloc(DMA_DESC_MEM_ALIGN_SIZE, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA);
bus_attr->dmadesc_rx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA); bus_attr->dmadesc_rx = heap_caps_aligned_alloc(DMA_DESC_MEM_ALIGN_SIZE, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA);
if (bus_attr->dmadesc_tx == NULL || bus_attr->dmadesc_rx == NULL) { if (bus_attr->dmadesc_tx == NULL || bus_attr->dmadesc_rx == NULL) {
err = ESP_ERR_NO_MEM; err = ESP_ERR_NO_MEM;
goto cleanup; goto cleanup;
} }
bus_attr->dma_desc_num = dma_desc_ct; bus_attr->dma_desc_num = dma_desc_ct;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
bus_attr->internal_mem_align_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
#else
bus_attr->internal_mem_align_size = 4;
#endif
} else { } else {
bus_attr->dma_enabled = 0; bus_attr->dma_enabled = 0;
bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE; bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;

View File

@ -112,6 +112,7 @@ We have two bits to control the interrupt:
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#include "esp_private/periph_ctrl.h"
#include "esp_private/spi_common_internal.h" #include "esp_private/spi_common_internal.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "esp_clk_tree.h" #include "esp_clk_tree.h"
@ -126,6 +127,9 @@ We have two bits to control the interrupt:
#include "hal/spi_hal.h" #include "hal/spi_hal.h"
#include "hal/spi_ll.h" #include "hal/spi_ll.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "esp_cache.h"
#endif
typedef struct spi_device_t spi_device_t; typedef struct spi_device_t spi_device_t;
@ -172,6 +176,11 @@ static spi_host_t* bus_driver_ctx[SOC_SPI_PERIPH_NUM] = {};
static const char *SPI_TAG = "spi_master"; static const char *SPI_TAG = "spi_master";
#define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str) #define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str)
#if SOC_PERIPH_CLK_CTRL_SHARED
#define SPI_MASTER_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define SPI_MASTER_RCC_CLOCK_ATOMIC()
#endif
static void spi_intr(void *arg); static void spi_intr(void *arg);
static void spi_bus_intr_enable(void *host); static void spi_bus_intr_enable(void *host);
@ -547,6 +556,9 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
if (spi_bus_lock_touch(dev_lock)) { if (spi_bus_lock_touch(dev_lock)) {
/* Configuration has not been applied yet. */ /* Configuration has not been applied yet. */
spi_hal_setup_device(hal, hal_dev); spi_hal_setup_device(hal, hal_dev);
SPI_MASTER_RCC_CLOCK_ATOMIC() {
spi_ll_set_clk_source(hal->hw, hal_dev->timing_conf.clock_source);
}
} }
} }
@ -680,13 +692,24 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
const int cs = host->cur_cs; const int cs = host->cur_cs;
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset. //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
#if CONFIG_IDF_TARGET_ESP32
if (bus_attr->dma_enabled) { if (bus_attr->dma_enabled) {
#if CONFIG_IDF_TARGET_ESP32
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same //This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan); spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan);
}
#endif //#if CONFIG_IDF_TARGET_ESP32 #endif //#if CONFIG_IDF_TARGET_ESP32
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE //invalidate here to let user access rx data in post_cb if possible
if (host->cur_trans_buf.buffer_to_rcv) {
uint16_t alignment = bus_attr->internal_mem_align_size;
uint32_t buffer_byte_len = (host->cur_trans_buf.trans->rxlength + 7) / 8;
buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1));
// invalidate priv_trans.buffer_to_rcv anyway, only user provide aligned buffer can rcv correct data in post_cb
esp_err_t ret = esp_cache_msync((void *)host->cur_trans_buf.buffer_to_rcv, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
assert(ret == ESP_OK);
}
#endif
}
//cur_cs is changed to DEV_NUM_MAX here //cur_cs is changed to DEV_NUM_MAX here
spi_post_trans(host); spi_post_trans(host);
@ -824,9 +847,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
free((void *)trans_buf->buffer_to_send); //force free, ignore const free((void *)trans_buf->buffer_to_send); //force free, ignore const
} }
// copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one. // copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
if (trans_buf->buffer_to_rcv && if (trans_buf->buffer_to_rcv && (void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] && trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc)
(void *)trans_buf->buffer_to_rcv != &trans_desc->rx_data[0] &&
trans_buf->buffer_to_rcv != trans_desc->rx_buffer) { // NOLINT(clang-analyzer-unix.Malloc)
if (trans_desc->flags & SPI_TRANS_USE_RXDATA) { if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); memcpy((uint8_t *) & trans_desc->rx_data[0], trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8);
} else { } else {
@ -836,9 +857,11 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
} }
} }
static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_desc, spi_trans_priv_t* new_desc, bool isdma) static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans_priv_t* priv_desc)
{ {
*new_desc = (spi_trans_priv_t) { .trans = trans_desc, }; spi_transaction_t *trans_desc = priv_desc->trans;
const spi_bus_attr_t *bus_attr = host->bus_attr;
uint16_t alignment = bus_attr->internal_mem_align_size;
// rx memory assign // rx memory assign
uint32_t* rcv_ptr; uint32_t* rcv_ptr;
@ -848,13 +871,6 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
//if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL //if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL
rcv_ptr = trans_desc->rx_buffer; rcv_ptr = trans_desc->rx_buffer;
} }
if (rcv_ptr && isdma && (!esp_ptr_dma_capable(rcv_ptr) || ((int)rcv_ptr % 4 != 0))) {
//if rxbuf in the desc not DMA-capable, malloc a new one. The rx buffer need to be length of multiples of 32 bits to avoid heap corruption.
ESP_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
rcv_ptr = heap_caps_malloc(((trans_desc->rxlength + 31) / 32) * 4, MALLOC_CAP_DMA);
if (rcv_ptr == NULL) goto clean_up;
}
new_desc->buffer_to_rcv = rcv_ptr;
// tx memory assign // tx memory assign
const uint32_t *send_ptr; const uint32_t *send_ptr;
@ -864,21 +880,53 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
//if not use TXDATA neither tx_buffer, tx data assigned to NULL //if not use TXDATA neither tx_buffer, tx data assigned to NULL
send_ptr = trans_desc->tx_buffer ; send_ptr = trans_desc->tx_buffer ;
} }
if (send_ptr && isdma && !esp_ptr_dma_capable( send_ptr )) {
//if txbuf in the desc not DMA-capable, malloc a new one
ESP_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
uint32_t *temp = heap_caps_malloc((trans_desc->length + 7) / 8, MALLOC_CAP_DMA);
if (temp == NULL) goto clean_up;
memcpy( temp, send_ptr, (trans_desc->length + 7) / 8 ); uint32_t tx_byte_len = (trans_desc->length + 7) / 8;
send_ptr = temp; uint32_t rx_byte_len = (trans_desc->rxlength + 7) / 8;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
bool tx_un_align = ((((uint32_t)send_ptr) | tx_byte_len) & (alignment - 1));
bool rx_un_align = ((((uint32_t)rcv_ptr) | rx_byte_len) & (alignment - 1));
#else
bool tx_un_align = false; //tx don't need align on addr or length, for other chips
bool rx_un_align = (((uint32_t)rcv_ptr) & (alignment - 1));
#endif
if (send_ptr && bus_attr->dma_enabled) {
if ((!esp_ptr_dma_capable(send_ptr) || tx_un_align )) {
ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d, or not dma_capable", alignment);
//if txbuf in the desc not DMA-capable, or not bytes aligned to alignment, malloc a new one
ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
tx_byte_len = (tx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment
uint32_t *temp = heap_caps_aligned_alloc(alignment, tx_byte_len, MALLOC_CAP_DMA);
if (temp == NULL) {
goto clean_up;
}
memcpy( temp, send_ptr, (trans_desc->length + 7) / 8 );
send_ptr = temp;
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_err_t ret = esp_cache_msync((void *)send_ptr, tx_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
assert(ret == ESP_OK);
#endif
} }
new_desc->buffer_to_send = send_ptr;
if (rcv_ptr && bus_attr->dma_enabled && (!esp_ptr_dma_capable(rcv_ptr) || rx_un_align )) {
ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment);
//if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one
ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment
rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA);
if (rcv_ptr == NULL) {
goto clean_up;
}
}
priv_desc->buffer_to_send = send_ptr;
priv_desc->buffer_to_rcv = rcv_ptr;
return ESP_OK; return ESP_OK;
clean_up: clean_up:
uninstall_priv_desc(new_desc); uninstall_priv_desc(priv_desc);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -897,8 +945,8 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
spi_trans_priv_t trans_buf; spi_trans_priv_t trans_buf = { .trans = trans_desc, };
ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled)); ret = setup_priv_desc(host, &trans_buf);
if (ret != ESP_OK) return ret; if (ret != ESP_OK) return ret;
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
@ -935,6 +983,7 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle
BaseType_t r; BaseType_t r;
spi_trans_priv_t trans_buf; spi_trans_priv_t trans_buf;
SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG); SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
bool use_dma = handle->host->bus_attr->dma_enabled;
//if SPI_DEVICE_NO_RETURN_RESULT is set, ret_queue will always be empty //if SPI_DEVICE_NO_RETURN_RESULT is set, ret_queue will always be empty
SPI_CHECK(!(handle->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT), "API not Supported!", ESP_ERR_NOT_SUPPORTED); SPI_CHECK(!(handle->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT), "API not Supported!", ESP_ERR_NOT_SUPPORTED);
@ -947,8 +996,10 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle
// Every in-flight transaction request occupies internal memory as DMA buffer if needed. // Every in-flight transaction request occupies internal memory as DMA buffer if needed.
return ESP_ERR_TIMEOUT; return ESP_ERR_TIMEOUT;
} }
//release temporary buffers //release temporary buffers used by dma
uninstall_priv_desc(&trans_buf); if (use_dma) {
uninstall_priv_desc(&trans_buf);
}
(*trans_desc) = trans_buf.trans; (*trans_desc) = trans_buf.trans;
return ESP_OK; return ESP_OK;
@ -1043,8 +1094,8 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE ); SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
spi_host_t *host = handle->host; spi_host_t *host = handle->host;
spi_trans_priv_t priv_polling_trans; spi_trans_priv_t priv_polling_trans = { .trans = trans_desc, };
ret = setup_priv_desc(trans_desc, &priv_polling_trans, (host->bus_attr->dma_enabled)); ret = setup_priv_desc(host, &priv_polling_trans);
if (ret!=ESP_OK) return ret; if (ret!=ESP_OK) return ret;
/* If device_acquiring_lock is set to handle, it means that the user has already /* If device_acquiring_lock is set to handle, it means that the user has already
@ -1065,6 +1116,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
ESP_LOGE(SPI_TAG, "polling can't get buslock"); ESP_LOGE(SPI_TAG, "polling can't get buslock");
return ret; return ret;
} }
//After holding the buslock, common resource can be accessed !!
//Polling, no interrupt is used. //Polling, no interrupt is used.
host->polling = true; host->polling = true;

View File

@ -163,6 +163,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
bool use_dma = (dma_chan != SPI_DMA_DISABLED); bool use_dma = (dma_chan != SPI_DMA_DISABLED);
spihost[host]->dma_enabled = use_dma; spihost[host]->dma_enabled = use_dma;
if (use_dma) { if (use_dma) {
#if CONFIG_IDF_TARGET_ESP32P4
abort(); //will supported in IDF-7503
#endif
ret = spicommon_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); ret = spicommon_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
if (ret != ESP_OK) { if (ret != ESP_OK) {
goto cleanup; goto cleanup;

View File

@ -115,6 +115,7 @@ typedef struct {
#define SPI_TRANS_MULTILINE_CMD (1<<9) ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase) #define SPI_TRANS_MULTILINE_CMD (1<<9) ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase)
#define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode #define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode
#define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase) #define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase)
#define SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL (1<<11) ///< By default driver will automatically re-alloc dma buffer if it doesn't meet hardware alignment or dma_capable requirements, this flag is for you to disable this feature, you will need to take care of the alignment otherwise driver will return you error ESP_ERR_INVALID_ARG
/** /**
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes. * This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
@ -208,6 +209,7 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
* @return * @return
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while * - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
* the bus was not acquired (`spi_device_acquire_bus()` should be called first) * the bus was not acquired (`spi_device_acquire_bus()` should be called first)
* or set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but tx or rx buffer not DMA-capable, or addr&len not align to cache line size
* - ESP_ERR_TIMEOUT if there was no room in the queue before ticks_to_wait expired * - ESP_ERR_TIMEOUT if there was no room in the queue before ticks_to_wait expired
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed * - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
* - ESP_ERR_INVALID_STATE if previous transactions are not finished * - ESP_ERR_INVALID_STATE if previous transactions are not finished
@ -273,6 +275,7 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra
* @return * @return
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while * - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
* the bus was not acquired (`spi_device_acquire_bus()` should be called first) * the bus was not acquired (`spi_device_acquire_bus()` should be called first)
* or set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but tx or rx buffer not DMA-capable, or addr&len not align to cache line size
* - ESP_ERR_TIMEOUT if the device cannot get control of the bus before ``ticks_to_wait`` expired * - ESP_ERR_TIMEOUT if the device cannot get control of the bus before ``ticks_to_wait`` expired
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed * - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
* - ESP_ERR_INVALID_STATE if previous transactions are not finished * - ESP_ERR_INVALID_STATE if previous transactions are not finished

View File

@ -146,10 +146,21 @@ components/driver/test_apps/spi/master:
components/driver/test_apps/spi/param: components/driver/test_apps/spi/param:
disable: disable:
- if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7503
components/driver/test_apps/spi/slave: components/driver/test_apps/spi/slave:
disable: disable:
- if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7503 slave support
components/driver/test_apps/spi/slave_hd:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
- if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1
components/driver/test_apps/temperature_sensor: components/driver/test_apps/temperature_sensor:
disable: disable:

View File

@ -76,7 +76,7 @@
#define ESP_SPI_SLAVE_TV (12.5*3.5) #define ESP_SPI_SLAVE_TV (12.5*3.5)
#define WIRE_DELAY 12.5 #define WIRE_DELAY 12.5
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
#define SLAVE_IOMUX_PIN_MISO -1 #define SLAVE_IOMUX_PIN_MISO -1
#define SLAVE_IOMUX_PIN_MOSI -1 #define SLAVE_IOMUX_PIN_MOSI -1
#define SLAVE_IOMUX_PIN_SCLK -1 #define SLAVE_IOMUX_PIN_SCLK -1

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -11,23 +11,15 @@
// iterator to load partition tables in `test spi bus lock, with flash` will lead memory not free // iterator to load partition tables in `test spi bus lock, with flash` will lead memory not free
#define TEST_MEMORY_LEAK_THRESHOLD (350) #define TEST_MEMORY_LEAK_THRESHOLD (350)
static size_t before_free_8bit;
static size_t before_free_32bit;
void setUp(void) void setUp(void)
{ {
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); unity_utils_record_free_mem();
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
} }
void tearDown(void) void tearDown(void)
{ {
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
} }
void app_main(void) void app_main(void)

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -287,8 +287,8 @@ TEST_CASE("SPI Master test", "[spi]")
success &= spi_test(handle, 4096 - 2); //multiple descs, edge case 1 success &= spi_test(handle, 4096 - 2); //multiple descs, edge case 1
success &= spi_test(handle, 4096 - 1); //multiple descs, edge case 2 success &= spi_test(handle, 4096 - 1); //multiple descs, edge case 2
success &= spi_test(handle, 4096 * 3); //multiple descs success &= spi_test(handle, 4096 * 3); //multiple descs
master_free_device_bus(handle); master_free_device_bus(handle);
TEST_ASSERT(success);
printf("Testing bus at 80KHz, non-DMA\n"); printf("Testing bus at 80KHz, non-DMA\n");
handle = setup_spi_bus_loopback(80000, false); handle = setup_spi_bus_loopback(80000, false);
@ -299,19 +299,18 @@ TEST_CASE("SPI Master test", "[spi]")
success &= spi_test(handle, 47); //small, unaligned success &= spi_test(handle, 47); //small, unaligned
success &= spi_test(handle, 63); //small success &= spi_test(handle, 63); //small
success &= spi_test(handle, 64); //small, unaligned success &= spi_test(handle, 64); //small, unaligned
master_free_device_bus(handle); master_free_device_bus(handle);
TEST_ASSERT(success);
printf("Testing bus at 26MHz\n"); printf("Testing bus at 20MHz\n");
handle = setup_spi_bus_loopback(20000000, true); handle = setup_spi_bus_loopback(20000000, true);
success &= spi_test(handle, 128); //DMA, aligned success &= spi_test(handle, 128); //DMA, aligned
success &= spi_test(handle, 4096 * 3); //DMA, multiple descs success &= spi_test(handle, 4096 * 3); //DMA, multiple descs
master_free_device_bus(handle); master_free_device_bus(handle);
TEST_ASSERT(success);
printf("Testing bus at 900KHz\n"); printf("Testing bus at 900KHz\n");
handle = setup_spi_bus_loopback(9000000, true); handle = setup_spi_bus_loopback(9000000, true);
success &= spi_test(handle, 128); //DMA, aligned success &= spi_test(handle, 128); //DMA, aligned
success &= spi_test(handle, 4096 * 3); //DMA, multiple descs success &= spi_test(handle, 4096 * 3); //DMA, multiple descs
master_free_device_bus(handle); master_free_device_bus(handle);
@ -790,11 +789,8 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
//connect MOSI to two devices breaks the output, fix it. //connect MOSI to two devices breaks the output, fix it.
spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
memset(rx_buf, 0x66, 320);
for ( int i = 0; i < 8; i ++ ) { for ( int i = 0; i < 8; i ++ ) {
memset( rx_buf, 0x66, sizeof(rx_buf)); memset( rx_buf, 0x66, sizeof(rx_buf));
spi_transaction_t t = {}; spi_transaction_t t = {};
t.length = 8 * (i + 1); t.length = 8 * (i + 1);
t.rxlength = 0; t.rxlength = 0;
@ -881,12 +877,12 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
vTaskDelay(50); vTaskDelay(50);
//prepare master tx data //prepare master tx data
int cmd_bits = (i + 1) * 2; int cmd_bits = (i + 1) * 2;
int addr_bits = int addr_bits = 0;
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
56 - 8 * i; addr_bits = 56 - 8 * i;
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
//ESP32S2 only supportes up to 32 bits address //ESP32S2 only supportes up to 32 bits address
28 - 4 * i; addr_bits = 28 - 4 * i;
#endif #endif
int round_up = (cmd_bits + addr_bits + 7) / 8 * 8; int round_up = (cmd_bits + addr_bits + 7) / 8 * 8;
addr_bits = round_up - cmd_bits; addr_bits = round_up - cmd_bits;
@ -1073,6 +1069,7 @@ TEST_CASE("SPI master variable dummy test", "[spi]")
master_free_device_bus(spi); master_free_device_bus(spi);
} }
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support
/** /**
* This test is to check when the first transaction of the HD master is to send data without receiving data via DMA, * This test is to check when the first transaction of the HD master is to send data without receiving data via DMA,
* then if the master could receive data correctly. * then if the master could receive data correctly.
@ -1161,8 +1158,10 @@ TEST_CASE("SPI master hd dma TX without RX test", "[spi]")
spi_slave_free(TEST_SLAVE_HOST); spi_slave_free(TEST_SLAVE_HOST);
master_free_device_bus(spi); master_free_device_bus(spi);
} }
#endif
#endif //#if (TEST_SPI_PERIPH_NUM >= 2) #endif //#if (TEST_SPI_PERIPH_NUM >= 2)
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494 #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494
#define FD_TEST_BUF_SIZE 32 #define FD_TEST_BUF_SIZE 32
#define TEST_NUM 4 #define TEST_NUM 4
@ -1338,6 +1337,7 @@ static void fd_slave(void)
TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", "[spi_ms][test_env=generic_multi_device]", fd_master, fd_slave); TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", "[spi_ms][test_env=generic_multi_device]", fd_master, fd_slave);
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494 #endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494
#endif //p4 slave support
//NOTE: Explained in IDF-1445 | MR !14996 //NOTE: Explained in IDF-1445 | MR !14996
@ -1491,6 +1491,7 @@ TEST_CASE("spi_speed", "[spi]")
#endif // CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE #endif // CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
#endif // !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384) #endif // !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support
//****************************************spi master add device test************************************// //****************************************spi master add device test************************************//
//add dummy devices first //add dummy devices first
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
@ -1601,7 +1602,7 @@ void test_add_device_slave(void)
} }
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms]", test_add_device_master, test_add_device_slave); TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms]", test_add_device_master, test_add_device_slave);
#endif //p4 slave support
#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE) #if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
@ -1661,8 +1662,8 @@ TEST_CASE("test_master_isr_pin_to_core","[spi]")
} }
#endif #endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support
#if CONFIG_SPI_MASTER_IN_IRAM #if CONFIG_SPI_MASTER_IN_IRAM
#define TEST_MASTER_IRAM_TRANS_LEN 120 #define TEST_MASTER_IRAM_TRANS_LEN 120
static IRAM_ATTR void test_master_iram_post_trans_cbk(spi_transaction_t *trans) static IRAM_ATTR void test_master_iram_post_trans_cbk(spi_transaction_t *trans)
{ {
@ -1767,3 +1768,4 @@ static void test_iram_slave_normal(void)
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:IRAM_safe", "[spi_ms]", test_master_iram, test_iram_slave_normal); TEST_CASE_MULTIPLE_DEVICES("SPI_Master:IRAM_safe", "[spi_ms]", test_master_iram, test_iram_slave_normal);
#endif #endif
#endif //p4 slave support

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -37,6 +37,8 @@
********************************************************************************/ ********************************************************************************/
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#define MASTER_DIN_SIGNAL HSPID_IN_IDX #define MASTER_DIN_SIGNAL HSPID_IN_IDX
#elif CONFIG_IDF_TARGET_ESP32P4
#define MASTER_DIN_SIGNAL SPI2_D_PAD_IN_IDX
#else #else
#define MASTER_DIN_SIGNAL FSPID_IN_IDX #define MASTER_DIN_SIGNAL FSPID_IN_IDX
#endif #endif
@ -142,7 +144,7 @@ TEST_CASE("SPI Single Board Test SIO", "[spi]")
} }
#endif //#if (TEST_SPI_PERIPH_NUM >= 2) #endif //#if (TEST_SPI_PERIPH_NUM >= 2)
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4) //IDF-7503 slave support
/******************************************************************************** /********************************************************************************
* Test SIO Master * Test SIO Master
* SIO Slave is not suported, and one unit test is limited to one feature, so,,, * SIO Slave is not suported, and one unit test is limited to one feature, so,,,
@ -326,3 +328,4 @@ void test_slave_run(void)
} }
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test_SIO_Mode_Multi_Board", "[spi_ms][test_env=generic_multi_device]", test_master_run, test_slave_run); TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test_SIO_Mode_Multi_Board", "[spi_ms][test_env=generic_multi_device]", test_master_run, test_slave_run);
#endif //p4 slave support

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -5,7 +5,11 @@ import pytest
# If `test_env` is define, should not run on generic runner # If `test_env` is define, should not run on generic runner
@pytest.mark.supported_targets @pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c2
@pytest.mark.esp32c3
@pytest.mark.esp32c6
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.generic @pytest.mark.generic
def test_slave_hd_single_dev(case_tester) -> None: # type: ignore def test_slave_hd_single_dev(case_tester) -> None: # type: ignore
@ -16,7 +20,11 @@ def test_slave_hd_single_dev(case_tester) -> None: # type: ignore
# if `test_env` not defined, will run on `generic_multi_device` by default # if `test_env` not defined, will run on `generic_multi_device` by default
@pytest.mark.supported_targets @pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c2
@pytest.mark.esp32c3
@pytest.mark.esp32c6
@pytest.mark.esp32h2 @pytest.mark.esp32h2
@pytest.mark.generic_multi_device @pytest.mark.generic_multi_device
@pytest.mark.parametrize('count', [2,], indirect=True) @pytest.mark.parametrize('count', [2,], indirect=True)

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -127,7 +127,11 @@ void static test_isr(void*arg)
TEST_CASE("Allocate previously freed interrupt, with different flags", "[intr_alloc]") TEST_CASE("Allocate previously freed interrupt, with different flags", "[intr_alloc]")
{ {
intr_handle_t intr; intr_handle_t intr;
#if CONFIG_IDF_TARGET_ESP32P4
int test_intr_source = ETS_GPIO_INTR0_SOURCE;
#else
int test_intr_source = ETS_GPIO_INTR_SOURCE; int test_intr_source = ETS_GPIO_INTR_SOURCE;
#endif
int isr_flags = ESP_INTR_FLAG_LEVEL2; int isr_flags = ESP_INTR_FLAG_LEVEL2;
TEST_ESP_OK(esp_intr_alloc(test_intr_source, isr_flags, test_isr, NULL, &intr)); TEST_ESP_OK(esp_intr_alloc(test_intr_source, isr_flags, test_isr, NULL, &intr));
@ -179,7 +183,15 @@ TEST_CASE("allocate 2 handlers for a same source and remove the later one", "[in
intr_handle_t handle1, handle2; intr_handle_t handle1, handle2;
// enable SPI2 // enable SPI2
#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159
PERIPH_RCC_ATOMIC() {
spi_ll_enable_bus_clock(1, true);
spi_ll_reset_register(1);
spi_ll_enable_clock(1, true);
}
#else
periph_module_enable(spi_periph_signal[1].module); periph_module_enable(spi_periph_signal[1].module);
#endif
esp_err_t r; esp_err_t r;
r = esp_intr_alloc(spi_periph_signal[1].irq, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1); r = esp_intr_alloc(spi_periph_signal[1].irq, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1);

View File

@ -1,4 +1,4 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
This test app is used to test LCDs with SPI interface. This test app is used to test LCDs with SPI interface.

View File

@ -15,7 +15,6 @@
#include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h" #include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_commands.h" #include "esp_lcd_panel_commands.h"
#include "esp_random.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "test_spi_board.h" #include "test_spi_board.h"
@ -92,9 +91,9 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1); gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
for (int i = 0; i < 200; i++) { for (int i = 0; i < 200; i++) {
uint8_t color_byte = esp_random() & 0xFF; uint8_t color_byte = rand() & 0xFF;
int x_start = esp_random() % (TEST_LCD_H_RES - 200); int x_start = rand() % (TEST_LCD_H_RES - 200);
int y_start = esp_random() % (TEST_LCD_V_RES - 200); int y_start = rand() % (TEST_LCD_V_RES - 200);
memset(img, color_byte, TEST_IMG_SIZE); memset(img, color_byte, TEST_IMG_SIZE);
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 200, y_start + 200, img); esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 200, y_start + 200, img);
} }
@ -202,7 +201,7 @@ TEST_CASE("spi_lcd_send_colors_to_fixed_region", "[lcd]")
size_t color_size = (x_end - x_start) * (y_end - y_start) * 2; size_t color_size = (x_end - x_start) * (y_end - y_start) * 2;
void *color_data = malloc(color_size); void *color_data = malloc(color_size);
TEST_ASSERT_NOT_NULL(color_data); TEST_ASSERT_NOT_NULL(color_data);
uint8_t color_byte = esp_random() & 0xFF; uint8_t color_byte = rand() & 0xFF;
memset(color_data, color_byte, color_size); memset(color_data, color_byte, color_size);
esp_lcd_panel_io_handle_t io_handle = NULL; esp_lcd_panel_io_handle_t io_handle = NULL;
@ -249,7 +248,7 @@ TEST_CASE("spi_lcd_send_colors_to_fixed_region", "[lcd]")
} }
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1000));
// change to another color // change to another color
color_byte = esp_random() & 0xFF; color_byte = rand() & 0xFF;
memset(color_data, color_byte, color_size); memset(color_data, color_byte, color_size);
for (int i = 0; i < steps; i++) { for (int i = 0; i < steps; i++) {
TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, -1, color_data + i * color_size_per_step, color_size_per_step)); TEST_ESP_OK(esp_lcd_panel_io_tx_color(io_handle, -1, color_data + i * color_size_per_step, color_size_per_step));

View File

@ -63,6 +63,7 @@ typedef spi_dev_t spi_dma_dev_t;
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{ {
//empty, keep this for compatibility //empty, keep this for compatibility

View File

@ -97,6 +97,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){ static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source) switch (clk_source)
{ {

View File

@ -99,6 +99,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){ static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source) switch (clk_source)
{ {

View File

@ -98,6 +98,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{ {
switch (clk_source) switch (clk_source)

View File

@ -100,6 +100,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{ {
switch (clk_source) switch (clk_source)

View File

@ -23,7 +23,7 @@ extern "C" {
* @brief Given a L2MEM cached address, get the corresponding non-cacheable address * @brief Given a L2MEM cached address, get the corresponding non-cacheable address
* @example 0x4FF0_0000 => 0x8FF0_0000 * @example 0x4FF0_0000 => 0x8FF0_0000
*/ */
#define CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) ((intptr_t)(addr) + 0x40000000) #define CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) ((intptr_t)(addr) + SOC_NON_CACHEABLE_OFFSET)
/** /**
* Cache capabilities * Cache capabilities

View File

@ -44,12 +44,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return HP_SYS_CLKRST_REG_TWAI1_CLK_EN; return HP_SYS_CLKRST_REG_TWAI1_CLK_EN;
case PERIPH_TWAI2_MODULE: case PERIPH_TWAI2_MODULE:
return HP_SYS_CLKRST_REG_TWAI2_CLK_EN; return HP_SYS_CLKRST_REG_TWAI2_CLK_EN;
case PERIPH_GPSPI_MODULE:
return HP_SYS_CLKRST_REG_GPSPI2_HS_CLK_EN;
case PERIPH_GPSPI2_MODULE:
return HP_SYS_CLKRST_REG_GPSPI2_MST_CLK_EN;
case PERIPH_GPSPI3_MODULE:
return HP_SYS_CLKRST_REG_GPSPI3_MST_CLK_EN;
case PERIPH_I3C_MODULE: case PERIPH_I3C_MODULE:
return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN; return HP_SYS_CLKRST_REG_I3C_MST_CLK_EN;
case PERIPH_CAM_MODULE: case PERIPH_CAM_MODULE:
@ -125,10 +119,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return HP_SYS_CLKRST_REG_RST_EN_CAN2; return HP_SYS_CLKRST_REG_RST_EN_CAN2;
case PERIPH_LEDC_MODULE: case PERIPH_LEDC_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_LEDC; return HP_SYS_CLKRST_REG_RST_EN_LEDC;
case PERIPH_GPSPI2_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_SPI2;
case PERIPH_GPSPI3_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_SPI3;
case PERIPH_LCD_MODULE: case PERIPH_LCD_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_LCDCAM; return HP_SYS_CLKRST_REG_RST_EN_LCDCAM;
case PERIPH_SARADC_MODULE: case PERIPH_SARADC_MODULE:
@ -194,10 +184,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
case PERIPH_TWAI1_MODULE: case PERIPH_TWAI1_MODULE:
case PERIPH_TWAI2_MODULE: case PERIPH_TWAI2_MODULE:
return HP_SYS_CLKRST_PERI_CLK_CTRL116_REG; return HP_SYS_CLKRST_PERI_CLK_CTRL116_REG;
case PERIPH_GPSPI_MODULE:
case PERIPH_GPSPI2_MODULE:
case PERIPH_GPSPI3_MODULE:
return HP_SYS_CLKRST_PERI_CLK_CTRL117_REG;
case PERIPH_I3C_MODULE: case PERIPH_I3C_MODULE:
case PERIPH_CAM_MODULE: case PERIPH_CAM_MODULE:
return HP_SYS_CLKRST_PERI_CLK_CTRL119_REG; return HP_SYS_CLKRST_PERI_CLK_CTRL119_REG;
@ -247,8 +233,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
case PERIPH_TWAI1_MODULE: case PERIPH_TWAI1_MODULE:
case PERIPH_TWAI2_MODULE: case PERIPH_TWAI2_MODULE:
case PERIPH_LEDC_MODULE: case PERIPH_LEDC_MODULE:
case PERIPH_GPSPI2_MODULE:
case PERIPH_GPSPI3_MODULE:
case PERIPH_CAM_MODULE: case PERIPH_CAM_MODULE:
case PERIPH_SARADC_MODULE: case PERIPH_SARADC_MODULE:
case PERIPH_AES_MODULE: case PERIPH_AES_MODULE:

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
{ {
//empty, keep this for compatibility //empty, keep this for compatibility

View File

@ -99,6 +99,7 @@ typedef enum {
* @param hw Beginning address of the peripheral registers. * @param hw Beginning address of the peripheral registers.
* @param clk_source clock source to select, see valid sources in type `spi_clock_source_t` * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
*/ */
__attribute__((always_inline))
static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){ static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source){
switch (clk_source) switch (clk_source)
{ {

View File

@ -29,9 +29,9 @@
#include "esp_err.h" #include "esp_err.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "hal/spi_types.h" #include "hal/spi_types.h"
#include "hal/dma_types.h"
#if SOC_GPSPI_SUPPORTED #if SOC_GPSPI_SUPPORTED
#include "hal/spi_ll.h" #include "hal/spi_ll.h"
#include "soc/lldesc.h"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -40,6 +40,12 @@ extern "C" {
#if SOC_GPSPI_SUPPORTED #if SOC_GPSPI_SUPPORTED
#if SOC_GPSPI_SUPPORTED && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
typedef dma_descriptor_align8_t spi_dma_desc_t;
#else
typedef dma_descriptor_align4_t spi_dma_desc_t;
#endif
/** /**
* Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
*/ */
@ -76,11 +82,11 @@ typedef struct {
spi_dma_dev_t *dma_in; ///< Input DMA(DMA -> RAM) peripheral register address spi_dma_dev_t *dma_in; ///< Input DMA(DMA -> RAM) peripheral register address
spi_dma_dev_t *dma_out; ///< Output DMA(RAM -> DMA) peripheral register address spi_dma_dev_t *dma_out; ///< Output DMA(RAM -> DMA) peripheral register address
bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization
lldesc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA. spi_dma_desc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA.
* The amount should be larger than dmadesc_n. The driver should ensure that * The amount should be larger than dmadesc_n. The driver should ensure that
* the data to be sent is shorter than the descriptors can hold. * the data to be sent is shorter than the descriptors can hold.
*/ */
lldesc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA. spi_dma_desc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA.
* The amount should be larger than dmadesc_n. The driver should ensure that * The amount should be larger than dmadesc_n. The driver should ensure that
* the data to be sent is shorter than the descriptors can hold. * the data to be sent is shorter than the descriptors can hold.
*/ */
@ -112,11 +118,11 @@ typedef struct {
*/ */
typedef struct { typedef struct {
/* These two need to be malloced by the driver first */ /* These two need to be malloced by the driver first */
lldesc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA. spi_dma_desc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA.
* The amount should be larger than dmadesc_n. The driver should ensure that * The amount should be larger than dmadesc_n. The driver should ensure that
* the data to be sent is shorter than the descriptors can hold. * the data to be sent is shorter than the descriptors can hold.
*/ */
lldesc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA. spi_dma_desc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA.
* The amount should be larger than dmadesc_n. The driver should ensure that * The amount should be larger than dmadesc_n. The driver should ensure that
* the data to be sent is shorter than the descriptors can hold. * the data to be sent is shorter than the descriptors can hold.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -13,17 +13,27 @@
#include "soc/clk_tree_defs.h" #include "soc/clk_tree_defs.h"
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_AHB_GDMA_VERSION == 1 #if SOC_GDMA_SUPPORTED
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
#include "soc/gdma_struct.h" #include "soc/gdma_struct.h"
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) gdma_ll_rx_enable_data_burst(&GDMA, chan, enable); #define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) gdma_ll_rx_enable_data_burst(&GDMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) gdma_ll_tx_enable_data_burst(&GDMA, chan, enable); #define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) gdma_ll_tx_enable_data_burst(&GDMA, chan, enable);
#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable); #define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable); #define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable);
#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable); #define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable);
#define spi_dma_ll_set_out_eof_generation(dev, chan, enable) gdma_ll_tx_set_eof_mode(&GDMA, chan, enable); #define spi_dma_ll_set_out_eof_generation(dev, chan, enable) gdma_ll_tx_set_eof_mode(&GDMA, chan, enable);
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI) //TODO: IDF-6152, refactor spi hal layer
#include "hal/axi_dma_ll.h"
#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) axi_dma_ll_rx_enable_data_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) axi_dma_ll_tx_enable_data_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) axi_dma_ll_rx_enable_descriptor_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) axi_dma_ll_tx_enable_descriptor_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) axi_dma_ll_tx_enable_auto_write_back(&AXI_DMA, chan, enable);
#define spi_dma_ll_set_out_eof_generation(dev, chan, enable) axi_dma_ll_tx_set_eof_mode(&AXI_DMA, chan, enable);
#endif #endif
#endif //SOC_GDMA_SUPPORTED
/* The tag may be unused if log level is set to NONE */ /* The tag may be unused if log level is set to NONE */
static const __attribute__((unused)) char SPI_HAL_TAG[] = "spi_hal"; static const __attribute__((unused)) char SPI_HAL_TAG[] = "spi_hal";

View File

@ -9,13 +9,14 @@
#include "hal/spi_hal.h" #include "hal/spi_hal.h"
#include "hal/assert.h" #include "hal/assert.h"
#include "soc/ext_mem_defs.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_AHB_GDMA_VERSION == 1 #if SOC_GDMA_SUPPORTED
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
#include "soc/gdma_struct.h" #include "soc/gdma_struct.h"
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan) #define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan)
#define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan); #define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan);
#define spi_dma_ll_rx_start(dev, chan, addr) do {\ #define spi_dma_ll_rx_start(dev, chan, addr) do {\
@ -26,7 +27,21 @@
gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\ gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
gdma_ll_tx_start(&GDMA, chan);\ gdma_ll_tx_start(&GDMA, chan);\
} while (0) } while (0)
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI) //TODO: IDF-6152, refactor spi hal layer
#include "hal/axi_dma_ll.h"
#define spi_dma_ll_rx_reset(dev, chan) axi_dma_ll_rx_reset_channel(&AXI_DMA, chan)
#define spi_dma_ll_tx_reset(dev, chan) axi_dma_ll_tx_reset_channel(&AXI_DMA, chan);
#define spi_dma_ll_rx_start(dev, chan, addr) do {\
axi_dma_ll_rx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
axi_dma_ll_rx_start(&AXI_DMA, chan);\
} while (0)
#define spi_dma_ll_tx_start(dev, chan, addr) do {\
axi_dma_ll_tx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
axi_dma_ll_tx_start(&AXI_DMA, chan);\
} while (0)
#endif #endif
#endif //SOC_GDMA_SUPPORTED
void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev) void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev)
{ {
@ -37,7 +52,6 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
#endif #endif
spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs); spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs);
spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg); spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg);
spi_ll_set_clk_source(hw, dev->timing_conf.clock_source);
//Configure bit order //Configure bit order
spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst); spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst);
spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst); spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst);
@ -131,6 +145,43 @@ void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev
memcpy(&hal->trans_config, trans, sizeof(spi_hal_trans_config_t)); memcpy(&hal->trans_config, trans, sizeof(spi_hal_trans_config_t));
} }
#if SOC_NON_CACHEABLE_OFFSET
#define ADDR_DMA_2_CPU(addr) ((typeof(addr))((uint32_t)(addr) + SOC_NON_CACHEABLE_OFFSET))
#define ADDR_CPU_2_DMA(addr) ((typeof(addr))((uint32_t)(addr) - SOC_NON_CACHEABLE_OFFSET))
#else
#define ADDR_DMA_2_CPU(addr) (addr)
#define ADDR_CPU_2_DMA(addr) (addr)
#endif
//TODO: IDF-6152, refactor spi hal layer
static void s_spi_hal_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
{
dmadesc = ADDR_DMA_2_CPU(dmadesc);
int n = 0;
while (len) {
int dmachunklen = len;
if (dmachunklen > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) {
dmachunklen = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
}
if (is_rx) {
//Receive needs DMA length rounded to next 32-bit boundary
dmadesc[n].dw0.size = (dmachunklen + 3) & (~3);
dmadesc[n].dw0.length = (dmachunklen + 3) & (~3);
} else {
dmadesc[n].dw0.size = dmachunklen;
dmadesc[n].dw0.length = dmachunklen;
}
dmadesc[n].buffer = (uint8_t *)data;
dmadesc[n].dw0.suc_eof = 0;
dmadesc[n].dw0.owner = 1;
dmadesc[n].next = ADDR_CPU_2_DMA(&dmadesc[n + 1]);
len -= dmachunklen;
data += dmachunklen;
n++;
}
dmadesc[n - 1].dw0.suc_eof = 1; //Mark last DMA desc as end of stream.
dmadesc[n - 1].next = NULL;
}
void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev, const spi_hal_trans_config_t *trans) void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev, const spi_hal_trans_config_t *trans)
{ {
spi_dev_t *hw = hal->hw; spi_dev_t *hw = hal->hw;
@ -140,13 +191,13 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
if (!hal->dma_enabled) { if (!hal->dma_enabled) {
//No need to setup anything; we'll copy the result out of the work registers directly later. //No need to setup anything; we'll copy the result out of the work registers directly later.
} else { } else {
lldesc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true); s_spi_hal_dma_desc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan); spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
spi_ll_dma_rx_fifo_reset(hal->hw); spi_ll_dma_rx_fifo_reset(hal->hw);
spi_ll_infifo_full_clr(hal->hw); spi_ll_infifo_full_clr(hal->hw);
spi_ll_dma_rx_enable(hal->hw, 1); spi_ll_dma_rx_enable(hal->hw, 1);
spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, hal->dmadesc_rx); spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, (lldesc_t *)hal->dmadesc_rx);
} }
} }
@ -165,13 +216,13 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
//Need to copy data to registers manually //Need to copy data to registers manually
spi_ll_write_buffer(hw, trans->send_buffer, trans->tx_bitlen); spi_ll_write_buffer(hw, trans->send_buffer, trans->tx_bitlen);
} else { } else {
lldesc_setup_link(hal->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false); s_spi_hal_dma_desc_setup_link(hal->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan); spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
spi_ll_dma_tx_fifo_reset(hal->hw); spi_ll_dma_tx_fifo_reset(hal->hw);
spi_ll_outfifo_empty_clr(hal->hw); spi_ll_outfifo_empty_clr(hal->hw);
spi_ll_dma_tx_enable(hal->hw, 1); spi_ll_dma_tx_enable(hal->hw, 1);
spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, hal->dmadesc_tx); spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (lldesc_t *)hal->dmadesc_tx);
} }
} }

View File

@ -3,17 +3,27 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_AHB_GDMA_VERSION == 1 #if SOC_GDMA_SUPPORTED
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
#include "soc/gdma_struct.h" #include "soc/gdma_struct.h"
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) gdma_ll_rx_enable_data_burst(&GDMA, chan, enable); #define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) gdma_ll_rx_enable_data_burst(&GDMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) gdma_ll_tx_enable_data_burst(&GDMA, chan, enable); #define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) gdma_ll_tx_enable_data_burst(&GDMA, chan, enable);
#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable); #define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) gdma_ll_rx_enable_descriptor_burst(&GDMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable); #define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) gdma_ll_tx_enable_descriptor_burst(&GDMA, chan, enable);
#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable); #define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) gdma_ll_tx_enable_auto_write_back(&GDMA, chan, enable);
#define spi_dma_ll_set_out_eof_generation(dev, chan, enable) gdma_ll_tx_set_eof_mode(&GDMA, chan, enable); #define spi_dma_ll_set_out_eof_generation(dev, chan, enable) gdma_ll_tx_set_eof_mode(&GDMA, chan, enable);
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI) //TODO: IDF-6152, refactor spi hal layer
#include "hal/axi_dma_ll.h"
#define spi_dma_ll_rx_enable_burst_data(dev, chan, enable) axi_dma_ll_rx_enable_data_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_data(dev, chan, enable) axi_dma_ll_tx_enable_data_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_rx_enable_burst_desc(dev, chan, enable) axi_dma_ll_rx_enable_descriptor_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_tx_enable_burst_desc(dev, chan, enable) axi_dma_ll_tx_enable_descriptor_burst(&AXI_DMA, chan, enable);
#define spi_dma_ll_enable_out_auto_wrback(dev, chan, enable) axi_dma_ll_tx_enable_auto_write_back(&AXI_DMA, chan, enable);
#define spi_dma_ll_set_out_eof_generation(dev, chan, enable) axi_dma_ll_tx_set_eof_mode(&AXI_DMA, chan, enable);
#endif #endif
#endif //SOC_GDMA_SUPPORTED
static void s_spi_slave_hal_dma_init_config(const spi_slave_hal_context_t *hal) static void s_spi_slave_hal_dma_init_config(const spi_slave_hal_context_t *hal)
{ {

View File

@ -1,12 +1,13 @@
#include "hal/spi_slave_hal.h" #include "hal/spi_slave_hal.h"
#include "hal/spi_ll.h" #include "hal/spi_ll.h"
#include "soc/ext_mem_defs.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros. //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
#if SOC_AHB_GDMA_VERSION == 1 #if SOC_GDMA_SUPPORTED
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
#include "soc/gdma_struct.h" #include "soc/gdma_struct.h"
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan) #define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan)
#define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan); #define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan);
#define spi_dma_ll_rx_start(dev, chan, addr) do {\ #define spi_dma_ll_rx_start(dev, chan, addr) do {\
@ -17,7 +18,21 @@
gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\ gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
gdma_ll_tx_start(&GDMA, chan);\ gdma_ll_tx_start(&GDMA, chan);\
} while (0) } while (0)
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI) //TODO: IDF-6152, refactor spi hal layer
#include "hal/axi_dma_ll.h"
#define spi_dma_ll_rx_reset(dev, chan) axi_dma_ll_rx_reset_channel(&AXI_DMA, chan)
#define spi_dma_ll_tx_reset(dev, chan) axi_dma_ll_tx_reset_channel(&AXI_DMA, chan);
#define spi_dma_ll_rx_start(dev, chan, addr) do {\
axi_dma_ll_rx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
axi_dma_ll_rx_start(&AXI_DMA, chan);\
} while (0)
#define spi_dma_ll_tx_start(dev, chan, addr) do {\
axi_dma_ll_tx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
axi_dma_ll_tx_start(&AXI_DMA, chan);\
} while (0)
#endif #endif
#endif //SOC_GDMA_SUPPORTED
bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal) bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal)
{ {
@ -45,10 +60,11 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
spi_ll_infifo_full_clr(hal->hw); spi_ll_infifo_full_clr(hal->hw);
spi_ll_dma_rx_enable(hal->hw, 1); spi_ll_dma_rx_enable(hal->hw, 1);
spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, &hal->dmadesc_rx[0]); spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, hal->dmadesc_rx);
} }
if (hal->tx_buffer) { if (hal->tx_buffer) {
lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false); lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
//reset dma outlink, this should be reset before spi related reset //reset dma outlink, this should be reset before spi related reset
spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan); spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
spi_ll_dma_tx_fifo_reset(hal->dma_out); spi_ll_dma_tx_fifo_reset(hal->dma_out);
@ -56,7 +72,7 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
spi_ll_outfifo_empty_clr(hal->hw); spi_ll_outfifo_empty_clr(hal->hw);
spi_ll_dma_tx_enable(hal->hw, 1); spi_ll_dma_tx_enable(hal->hw, 1);
spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (&hal->dmadesc_tx[0])); spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, hal->dmadesc_tx);
} }
} else { } else {
//No DMA. Turn off SPI and copy data to transmit buffers. //No DMA. Turn off SPI and copy data to transmit buffers.

View File

@ -3,3 +3,10 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
//TODO: IDF-8313 update after chips back and PLL setup
#define IDF_PERFORMANCE_MAX_SPI_CLK_FREQ 10*1000*1000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 1000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 1000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 1000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 1000

View File

@ -71,6 +71,10 @@ config SOC_I2S_SUPPORTED
bool bool
default y default y
config SOC_GPSPI_SUPPORTED
bool
default y
config SOC_I2C_SUPPORTED config SOC_I2C_SUPPORTED
bool bool
default y default y
@ -801,25 +805,21 @@ config SOC_SDM_CLK_SUPPORT_XTAL
config SOC_SPI_PERIPH_NUM config SOC_SPI_PERIPH_NUM
int int
default 2 default 3
config SOC_SPI_MAX_CS_NUM config SOC_SPI_MAX_CS_NUM
int int
default 6 default 6
config SOC_MEMSPI_IS_INDEPENDENT
bool
default y
config SOC_SPI_MAXIMUM_BUFFER_SIZE config SOC_SPI_MAXIMUM_BUFFER_SIZE
int int
default 64 default 64
config SOC_SPI_SUPPORT_DDRCLK config SOC_SPI_SLAVE_SUPPORT_SEG_TRANS
bool bool
default y default y
config SOC_SPI_SLAVE_SUPPORT_SEG_TRANS config SOC_SPI_SUPPORT_DDRCLK
bool bool
default y default y
@ -827,23 +827,15 @@ config SOC_SPI_SUPPORT_CD_SIG
bool bool
default y default y
config SOC_SPI_SUPPORT_CONTINUOUS_TRANS config SOC_SPI_SUPPORT_OCT
bool bool
default y default y
config SOC_SPI_SUPPORT_SLAVE_HD_VER2
bool
default n
config SOC_SPI_SUPPORT_CLK_XTAL config SOC_SPI_SUPPORT_CLK_XTAL
bool bool
default y default y
config SOC_SPI_SUPPORT_CLK_PLL_F80M config SOC_MEMSPI_IS_INDEPENDENT
bool
default y
config SOC_SPI_SUPPORT_CLK_RC_FAST
bool bool
default y default y

View File

@ -391,16 +391,20 @@ typedef enum {
/** /**
* @brief Array initializer for all supported clock sources of SPI * @brief Array initializer for all supported clock sources of SPI
*/ */
#define SOC_SPI_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST} #define SOC_SPI_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_SPLL}
/** /**
* @brief Type of SPI clock source. * @brief Type of SPI clock source.
*/ */
typedef enum { typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_80M as SPI source clock */
SPI_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_80M as SPI source clock */
SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */ SPI_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as SPI source clock */ #if SOC_CLK_TREE_SUPPORTED
SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST,
SPI_CLK_SRC_SPLL_480 = SOC_MOD_CLK_SPLL,
SPI_CLK_SRC_DEFAULT = SPI_CLK_SRC_SPLL_480, /*!< Select SPLL_480M as SPI source clock */
#else
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as SPI source clock */
#endif
} soc_periph_spi_clk_src_t; } soc_periph_spi_clk_src_t;
/////////////////////////////////////////////////PSRAM//////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////PSRAM////////////////////////////////////////////////////////////////////

View File

@ -57,6 +57,7 @@ extern "C" {
#define SOC_MMU_FLASH_SENSITIVE BIT(13) #define SOC_MMU_FLASH_SENSITIVE BIT(13)
#define SOC_MMU_PSRAM_SENSITIVE BIT(12) #define SOC_MMU_PSRAM_SENSITIVE BIT(12)
#define SOC_NON_CACHEABLE_OFFSET 0x40000000
/** /**
* MMU entry valid bit mask for mapping value. * MMU entry valid bit mask for mapping value.

View File

@ -52,7 +52,7 @@
#define SOC_I2S_SUPPORTED 1 #define SOC_I2S_SUPPORTED 1
// #define SOC_RMT_SUPPORTED 1 //TODO: IDF-7476 // #define SOC_RMT_SUPPORTED 1 //TODO: IDF-7476
// #define SOC_SDM_SUPPORTED 1 //TODO: IDF-7551 // #define SOC_SDM_SUPPORTED 1 //TODO: IDF-7551
// #define SOC_GPSPI_SUPPORTED 1 //TODO: IDF-7502, TODO: IDF-7503 #define SOC_GPSPI_SUPPORTED 1
// #define SOC_LEDC_SUPPORTED 1 //TODO: IDF-6510 // #define SOC_LEDC_SUPPORTED 1 //TODO: IDF-6510
#define SOC_I2C_SUPPORTED 1 //TODO: IDF-6507, TODO: IDF-7491 #define SOC_I2C_SUPPORTED 1 //TODO: IDF-6507, TODO: IDF-7491
#define SOC_SYSTIMER_SUPPORTED 1 #define SOC_SYSTIMER_SUPPORTED 1
@ -378,29 +378,29 @@
#define SOC_SDM_CLK_SUPPORT_PLL_F80M 1 #define SOC_SDM_CLK_SUPPORT_PLL_F80M 1
#define SOC_SDM_CLK_SUPPORT_XTAL 1 #define SOC_SDM_CLK_SUPPORT_XTAL 1
// TODO: IDF-5334 (Copy from esp32c3, need check)
/*-------------------------- SPI CAPS ----------------------------------------*/ /*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_PERIPH_NUM 2 #define SOC_SPI_PERIPH_NUM 3
#define SOC_SPI_PERIPH_CS_NUM(i) 6 #define SOC_SPI_PERIPH_CS_NUM(i) (((i)==0)? 2: (((i)==1)? 6: 3))
#define SOC_SPI_MAX_CS_NUM 6 #define SOC_SPI_MAX_CS_NUM 6
#define SOC_MEMSPI_IS_INDEPENDENT 1
#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 #define SOC_SPI_MAXIMUM_BUFFER_SIZE 64
#define SOC_SPI_SUPPORT_DDRCLK 1 // #define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 //TODO: IDF-7505
#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1
#define SOC_SPI_SUPPORT_DDRCLK 1
#define SOC_SPI_SUPPORT_CD_SIG 1 #define SOC_SPI_SUPPORT_CD_SIG 1
#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 #define SOC_SPI_SUPPORT_OCT 1
#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 0
#define SOC_SPI_SUPPORT_CLK_XTAL 1 #define SOC_SPI_SUPPORT_CLK_XTAL 1
#define SOC_SPI_SUPPORT_CLK_PLL_F80M 1 // #define SOC_SPI_SUPPORT_CLK_RC_FAST 1 //bellow clks are waiting for clock tree
#define SOC_SPI_SUPPORT_CLK_RC_FAST 1 // #define SOC_SPI_SUPPORT_CLK_SPLL_F480M 1 //super pll
// #define SOC_SPI_SUPPORT_CLK_SDIO 1 //sdio pll
// #define SOC_SPI_SUPPORT_CLK_APLL 1 //audio pll
// Peripheral supports DIO, DOUT, QIO, or QOUT // Peripheral supports DIO, DOUT, QIO, or QOUT
// host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2, // host_id = 0 -> SPI0/SPI1, host_id = 1 -> SPI2,
#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;}) #define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;})
#define SOC_SPI_MAX_PRE_DIVIDER 16 #define SOC_MEMSPI_IS_INDEPENDENT 1
#define SOC_SPI_MAX_PRE_DIVIDER 16
/*-------------------------- SPI MEM CAPS ---------------------------------------*/ /*-------------------------- SPI MEM CAPS ---------------------------------------*/
#define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1) #define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1)

View File

@ -5,3 +5,27 @@
*/ */
#pragma once #pragma once
// Normal IOMUX pins
#define SPI2_FUNC_NUM 3
#define SPI2_IOMUX_PIN_NUM_HD 6
#define SPI2_IOMUX_PIN_NUM_CS 7
#define SPI2_IOMUX_PIN_NUM_MOSI 8
#define SPI2_IOMUX_PIN_NUM_CLK 9
#define SPI2_IOMUX_PIN_NUM_MISO 10
#define SPI2_IOMUX_PIN_NUM_WP 11
// When using Octal SPI, we make use of SPI2_FUNC_NUM_OCT to route them as follows.
#define SPI2_FUNC_NUM_OCT 2
#define SPI2_IOMUX_PIN_NUM_HD_OCT 32
#define SPI2_IOMUX_PIN_NUM_CS_OCT 28
#define SPI2_IOMUX_PIN_NUM_MOSI_OCT 29
#define SPI2_IOMUX_PIN_NUM_CLK_OCT 30
#define SPI2_IOMUX_PIN_NUM_MISO_OCT 31
#define SPI2_IOMUX_PIN_NUM_WP_OCT 33
#define SPI2_IOMUX_PIN_NUM_IO4_OCT 34
#define SPI2_IOMUX_PIN_NUM_IO5_OCT 35
#define SPI2_IOMUX_PIN_NUM_IO6_OCT 36
#define SPI2_IOMUX_PIN_NUM_IO7_OCT 37
//SPI3 have no iomux pins

View File

@ -839,198 +839,8 @@ typedef union {
uint32_t val; uint32_t val;
} spi_dout_mode_reg_t; } spi_dout_mode_reg_t;
/** Type of dma_int register
/** Group: Interrupt registers */ * SPI interrupt raw/ena/clr/sta/set register
/** Type of dma_int_ena register
* SPI interrupt enable register
*/
typedef union {
struct {
/** dma_infifo_full_err_int_ena : R/W; bitpos: [0]; default: 0;
* The enable bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/
uint32_t dma_infifo_full_err_int_ena:1;
/** dma_outfifo_empty_err_int_ena : R/W; bitpos: [1]; default: 0;
* The enable bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
*/
uint32_t dma_outfifo_empty_err_int_ena:1;
/** slv_ex_qpi_int_ena : R/W; bitpos: [2]; default: 0;
* The enable bit for SPI slave Ex_QPI interrupt.
*/
uint32_t slv_ex_qpi_int_ena:1;
/** slv_en_qpi_int_ena : R/W; bitpos: [3]; default: 0;
* The enable bit for SPI slave En_QPI interrupt.
*/
uint32_t slv_en_qpi_int_ena:1;
/** slv_cmd7_int_ena : R/W; bitpos: [4]; default: 0;
* The enable bit for SPI slave CMD7 interrupt.
*/
uint32_t slv_cmd7_int_ena:1;
/** slv_cmd8_int_ena : R/W; bitpos: [5]; default: 0;
* The enable bit for SPI slave CMD8 interrupt.
*/
uint32_t slv_cmd8_int_ena:1;
/** slv_cmd9_int_ena : R/W; bitpos: [6]; default: 0;
* The enable bit for SPI slave CMD9 interrupt.
*/
uint32_t slv_cmd9_int_ena:1;
/** slv_cmda_int_ena : R/W; bitpos: [7]; default: 0;
* The enable bit for SPI slave CMDA interrupt.
*/
uint32_t slv_cmda_int_ena:1;
/** slv_rd_dma_done_int_ena : R/W; bitpos: [8]; default: 0;
* The enable bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
*/
uint32_t slv_rd_dma_done_int_ena:1;
/** slv_wr_dma_done_int_ena : R/W; bitpos: [9]; default: 0;
* The enable bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
*/
uint32_t slv_wr_dma_done_int_ena:1;
/** slv_rd_buf_done_int_ena : R/W; bitpos: [10]; default: 0;
* The enable bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
*/
uint32_t slv_rd_buf_done_int_ena:1;
/** slv_wr_buf_done_int_ena : R/W; bitpos: [11]; default: 0;
* The enable bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
*/
uint32_t slv_wr_buf_done_int_ena:1;
/** trans_done_int_ena : R/W; bitpos: [12]; default: 0;
* The enable bit for SPI_TRANS_DONE_INT interrupt.
*/
uint32_t trans_done_int_ena:1;
/** dma_seg_trans_done_int_ena : R/W; bitpos: [13]; default: 0;
* The enable bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
*/
uint32_t dma_seg_trans_done_int_ena:1;
/** seg_magic_err_int_ena : R/W; bitpos: [14]; default: 0;
* The enable bit for SPI_SEG_MAGIC_ERR_INT interrupt.
*/
uint32_t seg_magic_err_int_ena:1; //this field is only for GPSPI2
/** slv_buf_addr_err_int_ena : R/W; bitpos: [15]; default: 0;
* The enable bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
*/
uint32_t slv_buf_addr_err_int_ena:1;
/** slv_cmd_err_int_ena : R/W; bitpos: [16]; default: 0;
* The enable bit for SPI_SLV_CMD_ERR_INT interrupt.
*/
uint32_t slv_cmd_err_int_ena:1;
/** mst_rx_afifo_wfull_err_int_ena : R/W; bitpos: [17]; default: 0;
* The enable bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
*/
uint32_t mst_rx_afifo_wfull_err_int_ena:1;
/** mst_tx_afifo_rempty_err_int_ena : R/W; bitpos: [18]; default: 0;
* The enable bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
*/
uint32_t mst_tx_afifo_rempty_err_int_ena:1;
/** app2_int_ena : R/W; bitpos: [19]; default: 0;
* The enable bit for SPI_APP2_INT interrupt.
*/
uint32_t app2_int_ena:1;
/** app1_int_ena : R/W; bitpos: [20]; default: 0;
* The enable bit for SPI_APP1_INT interrupt.
*/
uint32_t app1_int_ena:1;
uint32_t reserved_21:11;
};
uint32_t val;
} spi_dma_int_ena_reg_t;
/** Type of dma_int_clr register
* SPI interrupt clear register
*/
typedef union {
struct {
/** dma_infifo_full_err_int_clr : WT; bitpos: [0]; default: 0;
* The clear bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/
uint32_t dma_infifo_full_err_int_clr:1;
/** dma_outfifo_empty_err_int_clr : WT; bitpos: [1]; default: 0;
* The clear bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
*/
uint32_t dma_outfifo_empty_err_int_clr:1;
/** slv_ex_qpi_int_clr : WT; bitpos: [2]; default: 0;
* The clear bit for SPI slave Ex_QPI interrupt.
*/
uint32_t slv_ex_qpi_int_clr:1;
/** slv_en_qpi_int_clr : WT; bitpos: [3]; default: 0;
* The clear bit for SPI slave En_QPI interrupt.
*/
uint32_t slv_en_qpi_int_clr:1;
/** slv_cmd7_int_clr : WT; bitpos: [4]; default: 0;
* The clear bit for SPI slave CMD7 interrupt.
*/
uint32_t slv_cmd7_int_clr:1;
/** slv_cmd8_int_clr : WT; bitpos: [5]; default: 0;
* The clear bit for SPI slave CMD8 interrupt.
*/
uint32_t slv_cmd8_int_clr:1;
/** slv_cmd9_int_clr : WT; bitpos: [6]; default: 0;
* The clear bit for SPI slave CMD9 interrupt.
*/
uint32_t slv_cmd9_int_clr:1;
/** slv_cmda_int_clr : WT; bitpos: [7]; default: 0;
* The clear bit for SPI slave CMDA interrupt.
*/
uint32_t slv_cmda_int_clr:1;
/** slv_rd_dma_done_int_clr : WT; bitpos: [8]; default: 0;
* The clear bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
*/
uint32_t slv_rd_dma_done_int_clr:1;
/** slv_wr_dma_done_int_clr : WT; bitpos: [9]; default: 0;
* The clear bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
*/
uint32_t slv_wr_dma_done_int_clr:1;
/** slv_rd_buf_done_int_clr : WT; bitpos: [10]; default: 0;
* The clear bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
*/
uint32_t slv_rd_buf_done_int_clr:1;
/** slv_wr_buf_done_int_clr : WT; bitpos: [11]; default: 0;
* The clear bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
*/
uint32_t slv_wr_buf_done_int_clr:1;
/** trans_done_int_clr : WT; bitpos: [12]; default: 0;
* The clear bit for SPI_TRANS_DONE_INT interrupt.
*/
uint32_t trans_done_int_clr:1;
/** dma_seg_trans_done_int_clr : WT; bitpos: [13]; default: 0;
* The clear bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
*/
uint32_t dma_seg_trans_done_int_clr:1;
/** seg_magic_err_int_clr : WT; bitpos: [14]; default: 0;
* The clear bit for SPI_SEG_MAGIC_ERR_INT interrupt.
*/
uint32_t seg_magic_err_int_clr:1; //this field is only for GPSPI2
/** slv_buf_addr_err_int_clr : WT; bitpos: [15]; default: 0;
* The clear bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
*/
uint32_t slv_buf_addr_err_int_clr:1;
/** slv_cmd_err_int_clr : WT; bitpos: [16]; default: 0;
* The clear bit for SPI_SLV_CMD_ERR_INT interrupt.
*/
uint32_t slv_cmd_err_int_clr:1;
/** mst_rx_afifo_wfull_err_int_clr : WT; bitpos: [17]; default: 0;
* The clear bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
*/
uint32_t mst_rx_afifo_wfull_err_int_clr:1;
/** mst_tx_afifo_rempty_err_int_clr : WT; bitpos: [18]; default: 0;
* The clear bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
*/
uint32_t mst_tx_afifo_rempty_err_int_clr:1;
/** app2_int_clr : WT; bitpos: [19]; default: 0;
* The clear bit for SPI_APP2_INT interrupt.
*/
uint32_t app2_int_clr:1;
/** app1_int_clr : WT; bitpos: [20]; default: 0;
* The clear bit for SPI_APP1_INT interrupt.
*/
uint32_t app1_int_clr:1;
uint32_t reserved_21:11;
};
uint32_t val;
} spi_dma_int_clr_reg_t;
/** Type of dma_int_raw register
* SPI interrupt raw register
*/ */
typedef union { typedef union {
struct { struct {
@ -1038,301 +848,112 @@ typedef union {
* 1: The current data rate of DMA Rx is smaller than that of SPI, which will lose the * 1: The current data rate of DMA Rx is smaller than that of SPI, which will lose the
* receive data. 0: Others. * receive data. 0: Others.
*/ */
uint32_t dma_infifo_full_err_int_raw:1; uint32_t dma_infifo_full_err_int:1;
/** dma_outfifo_empty_err_int_raw : R/WTC/SS; bitpos: [1]; default: 0; /** dma_outfifo_empty_err_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
* 1: The current data rate of DMA TX is smaller than that of SPI. SPI will stop in * 1: The current data rate of DMA TX is smaller than that of SPI. SPI will stop in
* master mode and send out all 0 in slave mode. 0: Others. * master mode and send out all 0 in slave mode. 0: Others.
*/ */
uint32_t dma_outfifo_empty_err_int_raw:1; uint32_t dma_outfifo_empty_err_int:1;
/** slv_ex_qpi_int_raw : R/WTC/SS; bitpos: [2]; default: 0; /** slv_ex_qpi_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
* The raw bit for SPI slave Ex_QPI interrupt. 1: SPI slave mode Ex_QPI transmission * The raw bit for SPI slave Ex_QPI interrupt. 1: SPI slave mode Ex_QPI transmission
* is ended. 0: Others. * is ended. 0: Others.
*/ */
uint32_t slv_ex_qpi_int_raw:1; uint32_t slv_ex_qpi_int:1;
/** slv_en_qpi_int_raw : R/WTC/SS; bitpos: [3]; default: 0; /** slv_en_qpi_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
* The raw bit for SPI slave En_QPI interrupt. 1: SPI slave mode En_QPI transmission * The raw bit for SPI slave En_QPI interrupt. 1: SPI slave mode En_QPI transmission
* is ended. 0: Others. * is ended. 0: Others.
*/ */
uint32_t slv_en_qpi_int_raw:1; uint32_t slv_en_qpi_int:1;
/** slv_cmd7_int_raw : R/WTC/SS; bitpos: [4]; default: 0; /** slv_cmd7_int_raw : R/WTC/SS; bitpos: [4]; default: 0;
* The raw bit for SPI slave CMD7 interrupt. 1: SPI slave mode CMD7 transmission is * The raw bit for SPI slave CMD7 interrupt. 1: SPI slave mode CMD7 transmission is
* ended. 0: Others. * ended. 0: Others.
*/ */
uint32_t slv_cmd7_int_raw:1; uint32_t slv_cmd7_int:1;
/** slv_cmd8_int_raw : R/WTC/SS; bitpos: [5]; default: 0; /** slv_cmd8_int_raw : R/WTC/SS; bitpos: [5]; default: 0;
* The raw bit for SPI slave CMD8 interrupt. 1: SPI slave mode CMD8 transmission is * The raw bit for SPI slave CMD8 interrupt. 1: SPI slave mode CMD8 transmission is
* ended. 0: Others. * ended. 0: Others.
*/ */
uint32_t slv_cmd8_int_raw:1; uint32_t slv_cmd8_int:1;
/** slv_cmd9_int_raw : R/WTC/SS; bitpos: [6]; default: 0; /** slv_cmd9_int_raw : R/WTC/SS; bitpos: [6]; default: 0;
* The raw bit for SPI slave CMD9 interrupt. 1: SPI slave mode CMD9 transmission is * The raw bit for SPI slave CMD9 interrupt. 1: SPI slave mode CMD9 transmission is
* ended. 0: Others. * ended. 0: Others.
*/ */
uint32_t slv_cmd9_int_raw:1; uint32_t slv_cmd9_int:1;
/** slv_cmda_int_raw : R/WTC/SS; bitpos: [7]; default: 0; /** slv_cmda_int_raw : R/WTC/SS; bitpos: [7]; default: 0;
* The raw bit for SPI slave CMDA interrupt. 1: SPI slave mode CMDA transmission is * The raw bit for SPI slave CMDA interrupt. 1: SPI slave mode CMDA transmission is
* ended. 0: Others. * ended. 0: Others.
*/ */
uint32_t slv_cmda_int_raw:1; uint32_t slv_cmda_int:1;
/** slv_rd_dma_done_int_raw : R/WTC/SS; bitpos: [8]; default: 0; /** slv_rd_dma_done_int_raw : R/WTC/SS; bitpos: [8]; default: 0;
* The raw bit for SPI_SLV_RD_DMA_DONE_INT interrupt. 1: SPI slave mode Rd_DMA * The raw bit for SPI_SLV_RD_DMA_DONE_INT interrupt. 1: SPI slave mode Rd_DMA
* transmission is ended. 0: Others. * transmission is ended. 0: Others.
*/ */
uint32_t slv_rd_dma_done_int_raw:1; uint32_t slv_rd_dma_done_int:1;
/** slv_wr_dma_done_int_raw : R/WTC/SS; bitpos: [9]; default: 0; /** slv_wr_dma_done_int_raw : R/WTC/SS; bitpos: [9]; default: 0;
* The raw bit for SPI_SLV_WR_DMA_DONE_INT interrupt. 1: SPI slave mode Wr_DMA * The raw bit for SPI_SLV_WR_DMA_DONE_INT interrupt. 1: SPI slave mode Wr_DMA
* transmission is ended. 0: Others. * transmission is ended. 0: Others.
*/ */
uint32_t slv_wr_dma_done_int_raw:1; uint32_t slv_wr_dma_done_int:1;
/** slv_rd_buf_done_int_raw : R/WTC/SS; bitpos: [10]; default: 0; /** slv_rd_buf_done_int_raw : R/WTC/SS; bitpos: [10]; default: 0;
* The raw bit for SPI_SLV_RD_BUF_DONE_INT interrupt. 1: SPI slave mode Rd_BUF * The raw bit for SPI_SLV_RD_BUF_DONE_INT interrupt. 1: SPI slave mode Rd_BUF
* transmission is ended. 0: Others. * transmission is ended. 0: Others.
*/ */
uint32_t slv_rd_buf_done_int_raw:1; uint32_t slv_rd_buf_done_int:1;
/** slv_wr_buf_done_int_raw : R/WTC/SS; bitpos: [11]; default: 0; /** slv_wr_buf_done_int_raw : R/WTC/SS; bitpos: [11]; default: 0;
* The raw bit for SPI_SLV_WR_BUF_DONE_INT interrupt. 1: SPI slave mode Wr_BUF * The raw bit for SPI_SLV_WR_BUF_DONE_INT interrupt. 1: SPI slave mode Wr_BUF
* transmission is ended. 0: Others. * transmission is ended. 0: Others.
*/ */
uint32_t slv_wr_buf_done_int_raw:1; uint32_t slv_wr_buf_done_int:1;
/** trans_done_int_raw : R/WTC/SS; bitpos: [12]; default: 0; /** trans_done_int_raw : R/WTC/SS; bitpos: [12]; default: 0;
* The raw bit for SPI_TRANS_DONE_INT interrupt. 1: SPI master mode transmission is * The raw bit for SPI_TRANS_DONE_INT interrupt. 1: SPI master mode transmission is
* ended. 0: others. * ended. 0: others.
*/ */
uint32_t trans_done_int_raw:1; uint32_t trans_done_int:1;
/** dma_seg_trans_done_int_raw : R/WTC/SS; bitpos: [13]; default: 0; /** dma_seg_trans_done_int_raw : R/WTC/SS; bitpos: [13]; default: 0;
* The raw bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. 1: spi master DMA * The raw bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. 1: spi master DMA
* full-duplex/half-duplex seg-conf-trans ends or slave half-duplex seg-trans ends. * full-duplex/half-duplex seg-conf-trans ends or slave half-duplex seg-trans ends.
* And data has been pushed to corresponding memory. 0: seg-conf-trans or seg-trans * And data has been pushed to corresponding memory. 0: seg-conf-trans or seg-trans
* is not ended or not occurred. * is not ended or not occurred.
*/ */
uint32_t dma_seg_trans_done_int_raw:1; uint32_t dma_seg_trans_done_int:1;
/** seg_magic_err_int_raw : R/WTC/SS; bitpos: [14]; default: 0; /** seg_magic_err_int_raw : R/WTC/SS; bitpos: [14]; default: 0;
* The raw bit for SPI_SEG_MAGIC_ERR_INT interrupt. 1: The magic value in CONF buffer * The raw bit for SPI_SEG_MAGIC_ERR_INT interrupt. 1: The magic value in CONF buffer
* is error in the DMA seg-conf-trans. 0: others. * is error in the DMA seg-conf-trans. 0: others.
*/ */
uint32_t seg_magic_err_int_raw:1; //this field is only for GPSPI2 uint32_t seg_magic_err_int_raw:1; //this field is only forPI2
/** slv_buf_addr_err_int_raw : R/WTC/SS; bitpos: [15]; default: 0; /** slv_buf_addr_err_int_raw : R/WTC/SS; bitpos: [15]; default: 0;
* The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address * The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address
* of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is * of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is
* bigger than 63. 0: Others. * bigger than 63. 0: Others.
*/ */
uint32_t slv_buf_addr_err_int_raw:1; uint32_t slv_buf_addr_err_int:1;
/** slv_cmd_err_int_raw : R/WTC/SS; bitpos: [16]; default: 0; /** slv_cmd_err_int_raw : R/WTC/SS; bitpos: [16]; default: 0;
* The raw bit for SPI_SLV_CMD_ERR_INT interrupt. 1: The slave command value in the * The raw bit for SPI_SLV_CMD_ERR_INT interrupt. 1: The slave command value in the
* current SPI slave HD mode transmission is not supported. 0: Others. * current SPI slave HD mode transmission is not supported. 0: Others.
*/ */
uint32_t slv_cmd_err_int_raw:1; uint32_t slv_cmd_err_int:1;
/** mst_rx_afifo_wfull_err_int_raw : R/WTC/SS; bitpos: [17]; default: 0; /** mst_rx_afifo_wfull_err_int_raw : R/WTC/SS; bitpos: [17]; default: 0;
* The raw bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. 1: There is a RX AFIFO * The raw bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. 1: There is a RX AFIFO
* write-full error when SPI inputs data in master mode. 0: Others. * write-full error when SPI inputs data in master mode. 0: Others.
*/ */
uint32_t mst_rx_afifo_wfull_err_int_raw:1; uint32_t mst_rx_afifo_wfull_err_int:1;
/** mst_tx_afifo_rempty_err_int_raw : R/WTC/SS; bitpos: [18]; default: 0; /** mst_tx_afifo_rempty_err_int_raw : R/WTC/SS; bitpos: [18]; default: 0;
* The raw bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. 1: There is a TX BUF * The raw bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. 1: There is a TX BUF
* AFIFO read-empty error when SPI outputs data in master mode. 0: Others. * AFIFO read-empty error when SPI outputs data in master mode. 0: Others.
*/ */
uint32_t mst_tx_afifo_rempty_err_int_raw:1; uint32_t mst_tx_afifo_rempty_err_int:1;
/** app2_int_raw : R/WTC/SS; bitpos: [19]; default: 0; /** app2_int_raw : R/WTC/SS; bitpos: [19]; default: 0;
* The raw bit for SPI_APP2_INT interrupt. The value is only controlled by software. * The raw bit for SPI_APP2_INT interrupt. The value is only controlled by software.
*/ */
uint32_t app2_int_raw:1; uint32_t app2_int:1;
/** app1_int_raw : R/WTC/SS; bitpos: [20]; default: 0; /** app1_int_raw : R/WTC/SS; bitpos: [20]; default: 0;
* The raw bit for SPI_APP1_INT interrupt. The value is only controlled by software. * The raw bit for SPI_APP1_INT interrupt. The value is only controlled by software.
*/ */
uint32_t app1_int_raw:1; uint32_t app1_int:1;
uint32_t reserved_21:11; uint32_t reserved_21:11;
}; };
uint32_t val; uint32_t val;
} spi_dma_int_raw_reg_t; } spi_dma_int_reg_t;
/** Type of dma_int_st register
* SPI interrupt status register
*/
typedef union {
struct {
/** dma_infifo_full_err_int_st : RO; bitpos: [0]; default: 0;
* The status bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/
uint32_t dma_infifo_full_err_int_st:1;
/** dma_outfifo_empty_err_int_st : RO; bitpos: [1]; default: 0;
* The status bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
*/
uint32_t dma_outfifo_empty_err_int_st:1;
/** slv_ex_qpi_int_st : RO; bitpos: [2]; default: 0;
* The status bit for SPI slave Ex_QPI interrupt.
*/
uint32_t slv_ex_qpi_int_st:1;
/** slv_en_qpi_int_st : RO; bitpos: [3]; default: 0;
* The status bit for SPI slave En_QPI interrupt.
*/
uint32_t slv_en_qpi_int_st:1;
/** slv_cmd7_int_st : RO; bitpos: [4]; default: 0;
* The status bit for SPI slave CMD7 interrupt.
*/
uint32_t slv_cmd7_int_st:1;
/** slv_cmd8_int_st : RO; bitpos: [5]; default: 0;
* The status bit for SPI slave CMD8 interrupt.
*/
uint32_t slv_cmd8_int_st:1;
/** slv_cmd9_int_st : RO; bitpos: [6]; default: 0;
* The status bit for SPI slave CMD9 interrupt.
*/
uint32_t slv_cmd9_int_st:1;
/** slv_cmda_int_st : RO; bitpos: [7]; default: 0;
* The status bit for SPI slave CMDA interrupt.
*/
uint32_t slv_cmda_int_st:1;
/** slv_rd_dma_done_int_st : RO; bitpos: [8]; default: 0;
* The status bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
*/
uint32_t slv_rd_dma_done_int_st:1;
/** slv_wr_dma_done_int_st : RO; bitpos: [9]; default: 0;
* The status bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
*/
uint32_t slv_wr_dma_done_int_st:1;
/** slv_rd_buf_done_int_st : RO; bitpos: [10]; default: 0;
* The status bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
*/
uint32_t slv_rd_buf_done_int_st:1;
/** slv_wr_buf_done_int_st : RO; bitpos: [11]; default: 0;
* The status bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
*/
uint32_t slv_wr_buf_done_int_st:1;
/** trans_done_int_st : RO; bitpos: [12]; default: 0;
* The status bit for SPI_TRANS_DONE_INT interrupt.
*/
uint32_t trans_done_int_st:1;
/** dma_seg_trans_done_int_st : RO; bitpos: [13]; default: 0;
* The status bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
*/
uint32_t dma_seg_trans_done_int_st:1;
/** seg_magic_err_int_st : RO; bitpos: [14]; default: 0;
* The status bit for SPI_SEG_MAGIC_ERR_INT interrupt.
*/
uint32_t seg_magic_err_int_st:1; //this field is only for GPSPI2
/** slv_buf_addr_err_int_st : RO; bitpos: [15]; default: 0;
* The status bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
*/
uint32_t slv_buf_addr_err_int_st:1;
/** slv_cmd_err_int_st : RO; bitpos: [16]; default: 0;
* The status bit for SPI_SLV_CMD_ERR_INT interrupt.
*/
uint32_t slv_cmd_err_int_st:1;
/** mst_rx_afifo_wfull_err_int_st : RO; bitpos: [17]; default: 0;
* The status bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
*/
uint32_t mst_rx_afifo_wfull_err_int_st:1;
/** mst_tx_afifo_rempty_err_int_st : RO; bitpos: [18]; default: 0;
* The status bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
*/
uint32_t mst_tx_afifo_rempty_err_int_st:1;
/** app2_int_st : RO; bitpos: [19]; default: 0;
* The status bit for SPI_APP2_INT interrupt.
*/
uint32_t app2_int_st:1;
/** app1_int_st : RO; bitpos: [20]; default: 0;
* The status bit for SPI_APP1_INT interrupt.
*/
uint32_t app1_int_st:1;
uint32_t reserved_21:11;
};
uint32_t val;
} spi_dma_int_st_reg_t;
/** Type of dma_int_set register
* SPI interrupt software set register
*/
typedef union {
struct {
/** dma_infifo_full_err_int_set : WT; bitpos: [0]; default: 0;
* The software set bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/
uint32_t dma_infifo_full_err_int_set:1;
/** dma_outfifo_empty_err_int_set : WT; bitpos: [1]; default: 0;
* The software set bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt.
*/
uint32_t dma_outfifo_empty_err_int_set:1;
/** slv_ex_qpi_int_set : WT; bitpos: [2]; default: 0;
* The software set bit for SPI slave Ex_QPI interrupt.
*/
uint32_t slv_ex_qpi_int_set:1;
/** slv_en_qpi_int_set : WT; bitpos: [3]; default: 0;
* The software set bit for SPI slave En_QPI interrupt.
*/
uint32_t slv_en_qpi_int_set:1;
/** slv_cmd7_int_set : WT; bitpos: [4]; default: 0;
* The software set bit for SPI slave CMD7 interrupt.
*/
uint32_t slv_cmd7_int_set:1;
/** slv_cmd8_int_set : WT; bitpos: [5]; default: 0;
* The software set bit for SPI slave CMD8 interrupt.
*/
uint32_t slv_cmd8_int_set:1;
/** slv_cmd9_int_set : WT; bitpos: [6]; default: 0;
* The software set bit for SPI slave CMD9 interrupt.
*/
uint32_t slv_cmd9_int_set:1;
/** slv_cmda_int_set : WT; bitpos: [7]; default: 0;
* The software set bit for SPI slave CMDA interrupt.
*/
uint32_t slv_cmda_int_set:1;
/** slv_rd_dma_done_int_set : WT; bitpos: [8]; default: 0;
* The software set bit for SPI_SLV_RD_DMA_DONE_INT interrupt.
*/
uint32_t slv_rd_dma_done_int_set:1;
/** slv_wr_dma_done_int_set : WT; bitpos: [9]; default: 0;
* The software set bit for SPI_SLV_WR_DMA_DONE_INT interrupt.
*/
uint32_t slv_wr_dma_done_int_set:1;
/** slv_rd_buf_done_int_set : WT; bitpos: [10]; default: 0;
* The software set bit for SPI_SLV_RD_BUF_DONE_INT interrupt.
*/
uint32_t slv_rd_buf_done_int_set:1;
/** slv_wr_buf_done_int_set : WT; bitpos: [11]; default: 0;
* The software set bit for SPI_SLV_WR_BUF_DONE_INT interrupt.
*/
uint32_t slv_wr_buf_done_int_set:1;
/** trans_done_int_set : WT; bitpos: [12]; default: 0;
* The software set bit for SPI_TRANS_DONE_INT interrupt.
*/
uint32_t trans_done_int_set:1;
/** dma_seg_trans_done_int_set : WT; bitpos: [13]; default: 0;
* The software set bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt.
*/
uint32_t dma_seg_trans_done_int_set:1;
/** seg_magic_err_int_set : WT; bitpos: [14]; default: 0;
* The software set bit for SPI_SEG_MAGIC_ERR_INT interrupt.
*/
uint32_t seg_magic_err_int_set:1; //this field is only for GPSPI2
/** slv_buf_addr_err_int_set : WT; bitpos: [15]; default: 0;
* The software set bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt.
*/
uint32_t slv_buf_addr_err_int_set:1;
/** slv_cmd_err_int_set : WT; bitpos: [16]; default: 0;
* The software set bit for SPI_SLV_CMD_ERR_INT interrupt.
*/
uint32_t slv_cmd_err_int_set:1;
/** mst_rx_afifo_wfull_err_int_set : WT; bitpos: [17]; default: 0;
* The software set bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt.
*/
uint32_t mst_rx_afifo_wfull_err_int_set:1;
/** mst_tx_afifo_rempty_err_int_set : WT; bitpos: [18]; default: 0;
* The software set bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt.
*/
uint32_t mst_tx_afifo_rempty_err_int_set:1;
/** app2_int_set : WT; bitpos: [19]; default: 0;
* The software set bit for SPI_APP2_INT interrupt.
*/
uint32_t app2_int_set:1;
/** app1_int_set : WT; bitpos: [20]; default: 0;
* The software set bit for SPI_APP1_INT interrupt.
*/
uint32_t app1_int_set:1;
uint32_t reserved_21:11;
};
uint32_t val;
} spi_dma_int_set_reg_t;
/** Type of wn register /** Type of wn register
* SPI CPU-controlled buffer * SPI CPU-controlled buffer
@ -1378,11 +999,11 @@ typedef struct {
volatile spi_din_num_reg_t din_num; volatile spi_din_num_reg_t din_num;
volatile spi_dout_mode_reg_t dout_mode; volatile spi_dout_mode_reg_t dout_mode;
volatile spi_dma_conf_reg_t dma_conf; volatile spi_dma_conf_reg_t dma_conf;
volatile spi_dma_int_ena_reg_t dma_int_ena; volatile spi_dma_int_reg_t dma_int_ena;
volatile spi_dma_int_clr_reg_t dma_int_clr; volatile spi_dma_int_reg_t dma_int_clr;
volatile spi_dma_int_raw_reg_t dma_int_raw; volatile spi_dma_int_reg_t dma_int_raw;
volatile spi_dma_int_st_reg_t dma_int_st; volatile spi_dma_int_reg_t dma_int_sta;
volatile spi_dma_int_set_reg_t dma_int_set; volatile spi_dma_int_reg_t dma_int_set;
uint32_t reserved_048[20]; uint32_t reserved_048[20];
volatile spi_wn_reg_t data_buf[16]; volatile spi_wn_reg_t data_buf[16];
uint32_t reserved_0d8[2]; uint32_t reserved_0d8[2];

View File

@ -11,5 +11,88 @@
Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc
*/ */
const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = {
{
// MSPI on P4 has dedicated iomux pins
.spiclk_out = -1,
.spiclk_in = -1,
.spid_out = -1,
.spiq_out = -1,
.spiwp_out = -1,
.spihd_out = -1,
.spid_in = -1,
.spiq_in = -1,
.spiwp_in = -1,
.spihd_in = -1,
.spics_out = {-1},
.spics_in = -1,
.spiclk_iomux_pin = -1,
.spid_iomux_pin = -1,
.spiq_iomux_pin = -1,
.spiwp_iomux_pin = -1,
.spihd_iomux_pin = -1,
.spics0_iomux_pin = -1,
.irq = -1,
.irq_dma = -1,
.module = -1,
.hw = NULL,
.func = -1,
}, {
.spiclk_out = SPI2_CK_PAD_OUT_IDX,
.spiclk_in = SPI2_CK_PAD_IN_IDX,
.spid_out = SPI2_D_PAD_OUT_IDX,
.spiq_out = SPI2_Q_PAD_OUT_IDX,
.spiwp_out = SPI2_WP_PAD_OUT_IDX,
.spihd_out = SPI2_HOLD_PAD_OUT_IDX,
.spid4_out = SPI2_IO4_PAD_OUT_IDX,
.spid5_out = SPI2_IO5_PAD_OUT_IDX,
.spid6_out = SPI2_IO6_PAD_OUT_IDX,
.spid7_out = SPI2_IO7_PAD_OUT_IDX,
.spid_in = SPI2_D_PAD_IN_IDX,
.spiq_in = SPI2_Q_PAD_IN_IDX,
.spiwp_in = SPI2_WP_PAD_IN_IDX,
.spihd_in = SPI2_HOLD_PAD_IN_IDX,
.spid4_in = SPI2_IO4_PAD_IN_IDX,
.spid5_in = SPI2_IO5_PAD_IN_IDX,
.spid6_in = SPI2_IO6_PAD_IN_IDX,
.spid7_in = SPI2_IO7_PAD_IN_IDX,
.spics_out = {SPI2_CS_PAD_OUT_IDX, SPI2_CS1_PAD_OUT_IDX, SPI2_CS2_PAD_OUT_IDX, SPI2_CS3_PAD_OUT_IDX, SPI2_CS4_PAD_OUT_IDX, SPI2_CS5_PAD_OUT_IDX},
.spics_in = SPI2_CS_PAD_IN_IDX,
.spiclk_iomux_pin = SPI2_IOMUX_PIN_NUM_CLK,
.spid_iomux_pin = SPI2_IOMUX_PIN_NUM_MOSI,
.spiq_iomux_pin = SPI2_IOMUX_PIN_NUM_MISO,
.spiwp_iomux_pin = SPI2_IOMUX_PIN_NUM_WP,
.spihd_iomux_pin = SPI2_IOMUX_PIN_NUM_HD,
.spics0_iomux_pin = SPI2_IOMUX_PIN_NUM_CS,
.irq = ETS_SPI2_INTR_SOURCE,
.irq_dma = -1,
.module = PERIPH_GPSPI2_MODULE,
.hw = &GPSPI2,
.func = SPI2_FUNC_NUM,
}, {
.spiclk_out = SPI3_CK_PAD_OUT_IDX,
.spiclk_in = SPI3_CK_PAD_IN_IDX,
.spid_out = SPI3_D_PAD_OUT_IDX,
.spiq_out = SPI3_QO_PAD_OUT_IDX,
//SPI3 doesn't have wp and hd signals
.spiwp_out = SPI3_WP_PAD_OUT_IDX,
.spihd_out = SPI3_HOLD_PAD_OUT_IDX,
.spid_in = SPI3_D_PAD_IN_IDX,
.spiq_in = SPI3_Q_PAD_IN_IDX,
.spiwp_in = SPI3_WP_PAD_IN_IDX,
.spihd_in = SPI3_HOLD_PAD_IN_IDX,
.spics_out = {SPI3_CS_PAD_OUT_IDX, SPI3_CS1_PAD_OUT_IDX, SPI3_CS2_PAD_OUT_IDX},
.spics_in = SPI3_CS_PAD_IN_IDX,
//SPI3 doesn't have iomux pins
.spiclk_iomux_pin = -1,
.spid_iomux_pin = -1,
.spiq_iomux_pin = -1,
.spiwp_iomux_pin = -1,
.spihd_iomux_pin = -1,
.spics0_iomux_pin = -1,
.irq = ETS_SPI3_INTR_SOURCE,
.irq_dma = -1,
.module = PERIPH_GPSPI3_MODULE,
.hw = &GPSPI3,
.func = -1,
}
}; };

View File

@ -117,7 +117,6 @@ api-reference/peripherals/ana_cmpr.rst
api-reference/peripherals/secure_element.rst api-reference/peripherals/secure_element.rst
api-reference/peripherals/ledc.rst api-reference/peripherals/ledc.rst
api-reference/peripherals/temp_sensor.rst api-reference/peripherals/temp_sensor.rst
api-reference/peripherals/spi_features.rst
api-reference/peripherals/sdio_slave.rst api-reference/peripherals/sdio_slave.rst
api-reference/peripherals/clk_tree.rst api-reference/peripherals/clk_tree.rst
api-reference/peripherals/spi_flash/xip_from_psram.inc api-reference/peripherals/spi_flash/xip_from_psram.inc
@ -136,7 +135,6 @@ api-reference/peripherals/ds.rst
api-reference/peripherals/i2c.rst api-reference/peripherals/i2c.rst
api-reference/peripherals/dedic_gpio.rst api-reference/peripherals/dedic_gpio.rst
api-reference/peripherals/sd_pullup_requirements.rst api-reference/peripherals/sd_pullup_requirements.rst
api-reference/peripherals/spi_master.rst
api-reference/peripherals/index.rst api-reference/peripherals/index.rst
api-reference/peripherals/sdmmc_host.rst api-reference/peripherals/sdmmc_host.rst
api-reference/peripherals/uart.rst api-reference/peripherals/uart.rst

View File

@ -8,7 +8,7 @@ SPI Master driver is a program that controls {IDF_TARGET_NAME}'s General Purpose
.. only:: esp32 .. only:: esp32
.. note:: .. note::
SPI1 is not a GP-SPI. SPI Master driver also supports SPI1 but with quite a few limitations, see :ref:`spi_master_on_spi1_bus`. SPI1 is not a GP-SPI. SPI Master driver also supports SPI1 but with quite a few limitations, see :ref:`spi_master_on_spi1_bus`.
For more hardware information about the GP-SPI peripheral(s), see **{IDF_TARGET_NAME} Technical Reference Manual** > **SPI Controller** [`PDF <{IDF_TARGET_TRM_EN_URL}#spi>`__]. For more hardware information about the GP-SPI peripheral(s), see **{IDF_TARGET_NAME} Technical Reference Manual** > **SPI Controller** [`PDF <{IDF_TARGET_TRM_EN_URL}#spi>`__].
@ -182,28 +182,28 @@ Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of
- 1 - 1
- 1 - 1
- 2 - 2
- {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
- {SPICOMMON_BUSFLAG_DUAL} - SPICOMMON_BUSFLAG_DUAL
* - Dual I/O * - Dual I/O
- 1 - 1
- 2 - 2
- 2 - 2
- * {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- - SPICOMMON_BUSFLAG_DUAL
* - Quad Output * - Quad Output
- 1 - 1
- 1 - 1
- 4 - 4
- {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - Quad I/O * - Quad I/O
- 1 - 1
- 4 - 4
- 4 - 4
- * {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
.. only:: SOC_SPI_SUPPORT_OCT .. only:: SOC_SPI_SUPPORT_OCT
@ -227,42 +227,42 @@ Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of
- 1 - 1
- 1 - 1
- 2 - 2
- {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
- {SPICOMMON_BUSFLAG_DUAL} - SPICOMMON_BUSFLAG_DUAL
* - Dual I/O * - Dual I/O
- 1 - 1
- 2 - 2
- 2 - 2
- * {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- - SPICOMMON_BUSFLAG_DUAL
* - Quad Output * - Quad Output
- 1 - 1
- 1 - 1
- 4 - 4
- {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - Quad I/O * - Quad I/O
- 1 - 1
- 4 - 4
- 4 - 4
- * {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - Octal Output * - Octal Output
- 1 - 1
- 1 - 1
- 8 - 8
- {SPI_TRANS_MODE_OCT} - SPI_TRANS_MODE_OCT
- {SPICOMMON_BUSFLAG_OCTAL} - SPICOMMON_BUSFLAG_OCTAL
* - OPI * - OPI
- 8 - 8
- 8 - 8
- 8 - 8
- * {SPI_TRANS_MODE_OCT} - SPI_TRANS_MODE_OCT
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
* {SPI_TRANS_MULTILINE_CMD} SPI_TRANS_MULTILINE_CMD
- {SPICOMMON_BUSFLAG_OCTAL} - SPICOMMON_BUSFLAG_OCTAL
Command and Address Phases Command and Address Phases
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -292,7 +292,7 @@ If using more than one data line 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`. 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 or esp32c2 or esp32c6 or esp32h2 .. only:: not SOC_SPI_HD_BOTH_INOUT_SUPPORTED
.. note:: .. note::
@ -455,7 +455,7 @@ GPIO Matrix and IO_MUX
* - CS0 [1]_ * - CS0 [1]_
- 15 - 15
- 5 - 5
* - SCLK * - SCLK
- 14 - 14
- 18 - 18
* - MISO * - MISO
@ -469,16 +469,16 @@ GPIO Matrix and IO_MUX
- 22 - 22
* - QUADHD * - QUADHD
- 4 - 4
- 21 - 21
.. only:: not esp32 .. only:: not esp32
{IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1"} {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7"}
{IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4"} {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9"}
{IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5"} {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8"}
{IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0"} {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10"}
{IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3"} {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6"}
{IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2"} {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11"}
Most of the chip's peripheral signals have a direct connection to their dedicated IO_MUX pins. However, the signals can also be routed to any other available pins using the less direct GPIO matrix. If at least one signal is routed through the GPIO matrix, then all signals will be routed through it. Most of the chip's peripheral signals have a direct connection to their dedicated IO_MUX pins. However, the signals can also be routed to any other available pins using the less direct GPIO matrix. If at least one signal is routed through the GPIO matrix, then all signals will be routed through it.
@ -639,7 +639,7 @@ For an interrupt transaction, the overall cost is **20+8n/Fspi[MHz]** [µs] for
- 25 - 25
- 128 - 128
- 153 - 153
- 836.6 - 836.6
When a transaction length is short, the cost of the transaction interval is high. If possible, try to squash several short transactions into one transaction to achieve a higher transfer speed. When a transaction length is short, the cost of the transaction interval is high. If possible, try to squash several short transactions into one transaction to achieve a higher transfer speed.
@ -769,11 +769,9 @@ Please note that the ISR is disabled during flash operation by default. To keep
- 11.43 - 11.43
* - 75 * - 75
- 100 - 100
- 8.89 - 8.89
.. only:: esp32
.. _spi_known_issues: .. _spi_known_issues:
Known Issues Known Issues
@ -802,6 +800,7 @@ Application Example
The code example for using the SPI master half duplex mode to read/write an AT93C46D EEPROM (8-bit mode) can be found in the :example:`peripherals/spi_master/hd_eeprom` directory of ESP-IDF examples. The code example for using the SPI master half duplex mode to read/write an AT93C46D EEPROM (8-bit mode) can be found in the :example:`peripherals/spi_master/hd_eeprom` directory of ESP-IDF examples.
The code example for using the SPI master full duplex mode to drive a SPI_LCD (e.g. ST7789V or ILI9341) can be found in the :example:`peripherals/spi_master/lcd` directory of ESP-IDF examples.
API Reference - SPI Common API Reference - SPI Common
-------------------------- --------------------------

View File

@ -8,7 +8,7 @@ SPI 主机驱动程序是一个软件程序,用于在 {IDF_TARGET_NAME} 的通
.. only:: esp32 .. only:: esp32
.. note:: .. note::
SPI1 不属于 GP-SPI。SPI 主机驱动程序也支持 SPI1。但在 SPI1 总线上使用 SPI 主机驱动程序存在诸多限制,请参阅 :ref:`spi_master_on_spi1_bus` SPI1 不属于 GP-SPI。SPI 主机驱动程序也支持 SPI1。但在 SPI1 总线上使用 SPI 主机驱动程序存在诸多限制,请参阅 :ref:`spi_master_on_spi1_bus`
有关 GP-SPI 硬件相关信息,请参考 **{IDF_TARGET_NAME} 技术参考手册** > **SPI 控制器** [`PDF <{IDF_TARGET_TRM_CN_URL}#spi>`__]。 有关 GP-SPI 硬件相关信息,请参考 **{IDF_TARGET_NAME} 技术参考手册** > **SPI 控制器** [`PDF <{IDF_TARGET_TRM_CN_URL}#spi>`__]。
@ -182,28 +182,28 @@ SPI 总线传输事务由五个阶段构成,详见下表(任意阶段均可
- 1 - 1
- 1 - 1
- 2 - 2
- {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
- {SPICOMMON_BUSFLAG_DUAL} - SPICOMMON_BUSFLAG_DUAL
* - 双线 I/O 模式 * - 双线 I/O 模式
- 1 - 1
- 2 - 2
- 2 - 2
- * {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- - SPICOMMON_BUSFLAG_DUAL
* - 四线输出模式 * - 四线输出模式
- 1 - 1
- 1 - 1
- 4 - 4
- {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - 四线 I/O 模式 * - 四线 I/O 模式
- 1 - 1
- 4 - 4
- 4 - 4
- * {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
.. only:: SOC_SPI_SUPPORT_OCT .. only:: SOC_SPI_SUPPORT_OCT
@ -227,42 +227,42 @@ SPI 总线传输事务由五个阶段构成,详见下表(任意阶段均可
- 1 - 1
- 1 - 1
- 2 - 2
- {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
- {SPICOMMON_BUSFLAG_DUAL} - SPICOMMON_BUSFLAG_DUAL
* - 双线 I/O 模式 * - 双线 I/O 模式
- 1 - 1
- 2 - 2
- 2 - 2
- * {SPI_TRANS_MODE_DIO} - SPI_TRANS_MODE_DIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- - SPICOMMON_BUSFLAG_DUAL
* - 四线输出模式 * - 四线输出模式
- 1 - 1
- 1 - 1
- 4 - 4
- {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - 四线 I/O 模式 * - 四线 I/O 模式
- 1 - 1
- 4 - 4
- 4 - 4
- * {SPI_TRANS_MODE_QIO} - SPI_TRANS_MODE_QIO
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
- {SPICOMMON_BUSFLAG_QUAD} - SPICOMMON_BUSFLAG_QUAD
* - 八线输出模式 * - 八线输出模式
- 1 - 1
- 1 - 1
- 8 - 8
- {SPI_TRANS_MODE_OCT} - SPI_TRANS_MODE_OCT
- {SPICOMMON_BUSFLAG_OCTAL} - SPICOMMON_BUSFLAG_OCTAL
* - OPI 模式 * - OPI 模式
- 8 - 8
- 8 - 8
- 8 - 8
- * {SPI_TRANS_MODE_OCT} - SPI_TRANS_MODE_OCT
* {SPI_TRANS_MULTILINE_ADDR} SPI_TRANS_MULTILINE_ADDR
* {SPI_TRANS_MULTILINE_CMD} SPI_TRANS_MULTILINE_CMD
- {SPICOMMON_BUSFLAG_OCTAL} - SPICOMMON_BUSFLAG_OCTAL
命令阶段和地址阶段 命令阶段和地址阶段
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -292,7 +292,7 @@ SPI 总线传输事务由五个阶段构成,详见下表(任意阶段均可
当启用 DMA 时,不支持同时具有读取阶段和写入阶段的半双工传输事务。有关细节和解决方法,请参阅 :ref:`spi_known_issues` 当启用 DMA 时,不支持同时具有读取阶段和写入阶段的半双工传输事务。有关细节和解决方法,请参阅 :ref:`spi_known_issues`
.. only:: esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2 .. only:: not SOC_SPI_HD_BOTH_INOUT_SUPPORTED
.. note:: .. note::
@ -364,7 +364,7 @@ SPI 主机逐字节地将数据读入和写入内存。默认情况下,数据
在某些情况下,要传输的数据大小与 ``uint8_t`` 数组不同,可使用以下宏将数据转换为可由 SPI 驱动直接发送的格式: 在某些情况下,要传输的数据大小与 ``uint8_t`` 数组不同,可使用以下宏将数据转换为可由 SPI 驱动直接发送的格式:
- 需传输的数据,使用 :c:macro:`SPI_SWAP_DATA_TX` - 需传输的数据,使用 :c:macro:`SPI_SWAP_DATA_TX`
- 接收到的数据,使用 :c:macro:`SPI_SWAP_DATA_RX` - 接收到的数据,使用 :c:macro:`SPI_SWAP_DATA_RX`
.. _mixed_transactions: .. _mixed_transactions:
@ -393,7 +393,7 @@ ISR 会干扰飞行中的轮询传输事务,以适应中断传输事务。在
因具备 :ref:`spi_bus_lock` 特性SPI 主机驱动程序可在 SPI1 总线上运行,但该过程十分棘手,且需要许多特殊处理。这是一个适合高级开发者的功能。 因具备 :ref:`spi_bus_lock` 特性SPI 主机驱动程序可在 SPI1 总线上运行,但该过程十分棘手,且需要许多特殊处理。这是一个适合高级开发者的功能。
要在 SPI1 总线上运行 SPI 主机驱动程序,需注意以下两个问题: 要在 SPI1 总线上运行 SPI 主机驱动程序,需注意以下两个问题:
1. 当驱动在 SPI1 上运行时,代码和数据应在内部存储器中。 1. 当驱动在 SPI1 上运行时,代码和数据应在内部存储器中。
@ -455,7 +455,7 @@ GPIO 矩阵与 IO_MUX 管脚
* - CS0 [1]_ * - CS0 [1]_
- 15 - 15
- 5 - 5
* - SCLK * - SCLK
- 14 - 14
- 18 - 18
* - MISO * - MISO
@ -469,16 +469,16 @@ GPIO 矩阵与 IO_MUX 管脚
- 22 - 22
* - QUADHD * - QUADHD
- 4 - 4
- 21 - 21
.. only:: not esp32 .. only:: not esp32
{IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1"} {IDF_TARGET_SPI2_IOMUX_PIN_CS:default="N/A", esp32s2="10", esp32s3="10", esp32c2="10", esp32c3="10", esp32c6="16", esp32h2="1", esp32p4="7"}
{IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4"} {IDF_TARGET_SPI2_IOMUX_PIN_CLK:default="N/A", esp32s2="12", esp32s3="12", esp32c2="6", esp32c3="6", esp32c6="6", esp32h2="4", esp32p4="9"}
{IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5"} {IDF_TARGET_SPI2_IOMUX_PIN_MOSI:default="N/A", esp32s2="11" esp32s3="11", esp32c2="7" esp32c3="7", esp32c6="7", esp32h2="5", esp32p4="8"}
{IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0"} {IDF_TARGET_SPI2_IOMUX_PIN_MISO:default="N/A", esp32s2="13" esp32s3="13", esp32c2="2" esp32c3="2", esp32c6="2", esp32h2="0", esp32p4="10"}
{IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3"} {IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3", esp32p4="6"}
{IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2"} {IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2", esp32p4="11"}
芯片的大多数外围信号都与之专用的 IO_MUX 管脚连接,但这些信号也可以通过较不直接的 GPIO 矩阵路由到任何其他可用的管脚。只要有一个信号是通过 GPIO 矩阵路由的,那么所有的信号都将通过它路由。 芯片的大多数外围信号都与之专用的 IO_MUX 管脚连接,但这些信号也可以通过较不直接的 GPIO 矩阵路由到任何其他可用的管脚。只要有一个信号是通过 GPIO 矩阵路由的,那么所有的信号都将通过它路由。
@ -639,7 +639,7 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg
- 25 - 25
- 128 - 128
- 153 - 153
- 836.6 - 836.6
传输事务长度较短时将提高传输事务间隔成本,因此应尽可能将几个短传输事务压缩成一个传输事务,以提升传输速度。 传输事务长度较短时将提高传输事务间隔成本,因此应尽可能将几个短传输事务压缩成一个传输事务,以提升传输速度。
@ -721,7 +721,7 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg
* - 使用 IO_MUX 的 ESP32 从机设备 * - 使用 IO_MUX 的 ESP32 从机设备
- 50 - 50
* - 使用 GPIO_MATRIX 的 ESP32 从机设备 * - 使用 GPIO_MATRIX 的 ESP32 从机设备
- 75 - 75
MISO 路径延迟(有效时间)由从机的 **输入延迟** 与主机的 **GPIO 矩阵延迟** 组成。该延迟决定了频率限制,超过这个频率的全双工传输将无法如半双工交易中使用的 Dummy 位一样工作。该频率限制的计算方法为: MISO 路径延迟(有效时间)由从机的 **输入延迟** 与主机的 **GPIO 矩阵延迟** 组成。该延迟决定了频率限制,超过这个频率的全双工传输将无法如半双工交易中使用的 Dummy 位一样工作。该频率限制的计算方法为:
@ -769,11 +769,9 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg
- 11.43 - 11.43
* - 75 * - 75
- 100 - 100
- 8.89 - 8.89
.. only:: esp32
.. _spi_known_issues: .. _spi_known_issues:
已知问题 已知问题
@ -802,6 +800,7 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg
查看使用 SPI 主机驱动程序在半双工模式下读取/写入 AT93C46D EEPROM8 位模式)的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/spi_master/hd_eeprom` 目录。 查看使用 SPI 主机驱动程序在半双工模式下读取/写入 AT93C46D EEPROM8 位模式)的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/spi_master/hd_eeprom` 目录。
查看使用 SPI 主机驱动程序在全双工模式下驱动 LCD 屏幕(如 ST7789V 或 ILI9341的示例代码请前往 ESP-IDF 示例的 :example:`peripherals/spi_master/lcd` 目录。
API 参考 - SPI Common API 参考 - SPI Common
-------------------------- --------------------------

View File

@ -232,13 +232,12 @@ examples/peripherals/spi_master/lcd:
disable: disable:
- if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_GPSPI_SUPPORTED != 1
examples/peripherals/spi_slave/receiver: examples/peripherals/spi_slave:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
examples/peripherals/spi_slave/sender:
disable: disable:
- if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7503 slave support
examples/peripherals/spi_slave_hd/append_mode/master: examples/peripherals/spi_slave_hd/append_mode/master:
disable: disable:
@ -255,10 +254,16 @@ examples/peripherals/spi_slave_hd/append_mode/slave:
examples/peripherals/spi_slave_hd/segment_mode/seg_master: examples/peripherals/spi_slave_hd/segment_mode/seg_master:
disable: disable:
- if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7505 slave hd support
examples/peripherals/spi_slave_hd/segment_mode/seg_slave: examples/peripherals/spi_slave_hd/segment_mode/seg_slave:
disable: disable:
- if: IDF_TARGET == "esp32" or SOC_GPSPI_SUPPORTED != 1 - if: IDF_TARGET == "esp32" or SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7505 slave hd support
examples/peripherals/temperature_sensor/temp_sensor: examples/peripherals/temperature_sensor/temp_sensor:
disable: disable:

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 | | Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | | ----------------- | -------- | -------- | -------- | -------- | -------- |
# I2S TDM Example -- ES7210 4-Ch ADC Codec # I2S TDM Example -- ES7210 4-Ch ADC Codec

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# SPI LCD and Touch Panel Example # SPI LCD and Touch Panel Example

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
## LCD tjpgd example ## LCD tjpgd example

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
## SPI master half duplex EEPROM example ## SPI master half duplex EEPROM example

View File

@ -22,51 +22,29 @@
This code demonstrates how to use the SPI master half duplex mode to read/write a AT932C46D EEPROM (8-bit mode). This code demonstrates how to use the SPI master half duplex mode to read/write a AT932C46D EEPROM (8-bit mode).
*/ */
#ifdef CONFIG_IDF_TARGET_ESP32 //////////////////////////////////////////////////////////////////////////////////////////////////////////
# ifdef CONFIG_EXAMPLE_USE_SPI1_PINS ////////////// Please update the following configuration according to your HardWare spec /////////////////
# define EEPROM_HOST SPI1_HOST //////////////////////////////////////////////////////////////////////////////////////////////////////////
#if CONFIG_IDF_TARGET_ESP32
# if CONFIG_EXAMPLE_USE_SPI1_PINS
# define EEPROM_HOST SPI1_HOST
// Use default pins, same as the flash chip. // Use default pins, same as the flash chip.
# define PIN_NUM_MISO 7 # define PIN_NUM_MISO 7
# define PIN_NUM_MOSI 8 # define PIN_NUM_MOSI 8
# define PIN_NUM_CLK 6 # define PIN_NUM_CLK 6
# else # else
# define EEPROM_HOST HSPI_HOST # define EEPROM_HOST HSPI_HOST
# define PIN_NUM_MISO 18 # define PIN_NUM_MISO 18
# define PIN_NUM_MOSI 23 # define PIN_NUM_MOSI 23
# define PIN_NUM_CLK 19 # define PIN_NUM_CLK 19
# endif # endif
# define PIN_NUM_CS 13
# define PIN_NUM_CS 13 #else
#elif defined CONFIG_IDF_TARGET_ESP32S2 # define EEPROM_HOST SPI2_HOST
# define EEPROM_HOST SPI2_HOST # define PIN_NUM_MISO 13
# define PIN_NUM_MOSI 12
# define PIN_NUM_MISO 37 # define PIN_NUM_CLK 11
# define PIN_NUM_MOSI 35 # define PIN_NUM_CS 10
# define PIN_NUM_CLK 36
# define PIN_NUM_CS 34
#elif defined CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
# define EEPROM_HOST SPI2_HOST
# define PIN_NUM_MISO 2
# define PIN_NUM_MOSI 7
# define PIN_NUM_CLK 6
# define PIN_NUM_CS 10
#elif CONFIG_IDF_TARGET_ESP32S3
# define EEPROM_HOST SPI2_HOST
# define PIN_NUM_MISO 13
# define PIN_NUM_MOSI 11
# define PIN_NUM_CLK 12
# define PIN_NUM_CS 10
#elif CONFIG_IDF_TARGET_ESP32H2
# define EEPROM_HOST SPI2_HOST
# define PIN_NUM_MISO 0
# define PIN_NUM_MOSI 5
# define PIN_NUM_CLK 4
# define PIN_NUM_CS 1
#endif #endif
static const char TAG[] = "main"; static const char TAG[] = "main";
@ -124,11 +102,10 @@ void app_main(void)
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
} }
ESP_LOGI(TAG, "Read: %s", test_buf); ESP_LOGI(TAG, "Read: %s", test_buf);
ESP_LOGI(TAG, "Example finished."); ESP_LOGI(TAG, "Example finished.");
while (1) { while (1) {
// Add your main loop handling code here. // Add your main loop handling code here.
vTaskDelay(1); vTaskDelay(100);
} }
} }

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# SPI Host Driver Example # SPI Host Driver Example
@ -15,9 +15,11 @@ If you are looking for code to drive LCDs in general, rather than code that uses
* An ESP development board, with SPI LCD * An ESP development board, with SPI LCD
Connection : **Connection** :
Depends on boards. Refer to `spi_master_example_main.c` No wiring is required on ESP-WROVER-KIT Depends on boards. The GPIO number used by this example can be changed in `spi_master_example_main.c` No wiring is required on ESP-WROVER-KIT
Especially, please pay attention to the level used to turn on the LCD backlight, some LCD module needs a low level to turn it on, while others take a high level. You can change the backlight level macro LCD_BK_LIGHT_ON_LEVEL in `spi_master_example_main.c`.
### Build and Flash ### Build and Flash

View File

@ -29,8 +29,10 @@
before the transaction is sent, the callback will set this line to the correct state. before the transaction is sent, the callback will set this line to the correct state.
*/ */
#ifdef CONFIG_IDF_TARGET_ESP32 //////////////////////////////////////////////////////////////////////////////////////////////////////////
#define LCD_HOST HSPI_HOST ////////////// Please update the following configuration according to your HardWare spec /////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#define LCD_HOST SPI2_HOST
#define PIN_NUM_MISO 25 #define PIN_NUM_MISO 25
#define PIN_NUM_MOSI 23 #define PIN_NUM_MOSI 23
@ -40,41 +42,8 @@
#define PIN_NUM_DC 21 #define PIN_NUM_DC 21
#define PIN_NUM_RST 18 #define PIN_NUM_RST 18
#define PIN_NUM_BCKL 5 #define PIN_NUM_BCKL 5
#elif defined CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define LCD_HOST SPI2_HOST
#define PIN_NUM_MISO 37 #define LCD_BK_LIGHT_ON_LEVEL 0
#define PIN_NUM_MOSI 35
#define PIN_NUM_CLK 36
#define PIN_NUM_CS 45
#define PIN_NUM_DC 4
#define PIN_NUM_RST 5
#define PIN_NUM_BCKL 6
#elif defined CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
#define LCD_HOST SPI2_HOST
#define PIN_NUM_MISO 2
#define PIN_NUM_MOSI 7
#define PIN_NUM_CLK 6
#define PIN_NUM_CS 10
#define PIN_NUM_DC 9
#define PIN_NUM_RST 4
#define PIN_NUM_BCKL 5
#elif defined CONFIG_IDF_TARGET_ESP32H2
#define LCD_HOST SPI2_HOST
#define PIN_NUM_MISO 0
#define PIN_NUM_MOSI 5
#define PIN_NUM_CLK 4
#define PIN_NUM_CS 1
#define PIN_NUM_DC 10
#define PIN_NUM_RST 11
#define PIN_NUM_BCKL 12
#endif
//To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use, //To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use,
//but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this. //but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this.
@ -328,7 +297,7 @@ void lcd_init(spi_device_handle_t spi)
} }
///Enable backlight ///Enable backlight
gpio_set_level(PIN_NUM_BCKL, 0); gpio_set_level(PIN_NUM_BCKL, LCD_BK_LIGHT_ON_LEVEL);
} }
/* To send a set of lines we have to send a command, 2 data bytes, another command, 2 more data bytes and another command /* To send a set of lines we have to send a command, 2 data bytes, another command, 2 more data bytes and another command

View File

@ -31,52 +31,19 @@ ready to receive/send data. This code connects this line to a GPIO interrupt whi
task waits for this semaphore to be given before queueing a transmission. task waits for this semaphore to be given before queueing a transmission.
*/ */
/* //////////////////////////////////////////////////////////////////////////////////////////////////////////
Pins in use. The SPI Master can use the GPIO mux, so feel free to change these if needed. ////////////// Please update the following configuration according to your HardWare spec /////////////////
*/ //////////////////////////////////////////////////////////////////////////////////////////////////////////
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #define GPIO_HANDSHAKE 2
#define GPIO_HANDSHAKE 2 #define GPIO_MOSI 12
#define GPIO_MOSI 12 #define GPIO_MISO 13
#define GPIO_MISO 13 #define GPIO_SCLK 15
#define GPIO_SCLK 15 #define GPIO_CS 14
#define GPIO_CS 14
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
#define GPIO_HANDSHAKE 3
#define GPIO_MOSI 7
#define GPIO_MISO 2
#define GPIO_SCLK 6
#define GPIO_CS 10
#elif CONFIG_IDF_TARGET_ESP32C6
#define GPIO_HANDSHAKE 15
#define GPIO_MOSI 19
#define GPIO_MISO 20
#define GPIO_SCLK 18
#define GPIO_CS 9
#elif CONFIG_IDF_TARGET_ESP32H2
#define GPIO_HANDSHAKE 2
#define GPIO_MOSI 5
#define GPIO_MISO 0
#define GPIO_SCLK 4
#define GPIO_CS 1
#elif CONFIG_IDF_TARGET_ESP32S3
#define GPIO_HANDSHAKE 2
#define GPIO_MOSI 11
#define GPIO_MISO 13
#define GPIO_SCLK 12
#define GPIO_CS 10
#endif //CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
#define SENDER_HOST HSPI_HOST #define SENDER_HOST HSPI_HOST
#else #else
#define SENDER_HOST SPI2_HOST #define SENDER_HOST SPI2_HOST
#endif #endif
//The semaphore indicating the slave is ready to receive stuff. //The semaphore indicating the slave is ready to receive stuff.