feat(spi_master): p4 add master driver supported

This commit is contained in:
wanlei
2023-08-31 19:17:40 +08:00
parent 5306b3308f
commit 00fcdce725
29 changed files with 1728 additions and 540 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

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

@ -54,12 +54,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:
@ -145,10 +139,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:
@ -224,10 +214,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;
@ -282,8 +268,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

@ -370,16 +370,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
@ -377,29 +377,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

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