|
|
@@ -22,6 +22,7 @@
|
|
|
#include "esp_log.h"
|
|
|
#include "esp_err.h"
|
|
|
#include "soc/soc.h"
|
|
|
+#include "soc/soc_caps.h"
|
|
|
#include "soc/dport_reg.h"
|
|
|
#include "soc/lldesc.h"
|
|
|
#include "driver/gpio.h"
|
|
|
@@ -32,6 +33,15 @@
|
|
|
#include "hal/spi_hal.h"
|
|
|
#include "esp_rom_gpio.h"
|
|
|
|
|
|
+//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
|
|
|
+#if SOC_GDMA_SUPPORTED
|
|
|
+#include "hal/gdma_ll.h"
|
|
|
+
|
|
|
+#define spi_dma_set_rx_channel_priority(gdma_chan, priority) gdma_ll_rx_set_priority(&GDMA, gdma_chan, priority);
|
|
|
+#define spi_dma_set_tx_channel_priority(gdma_chan, priority) gdma_ll_tx_set_priority(&GDMA, gdma_chan, priority);
|
|
|
+#define spi_dma_connect_rx_channel_to_periph(gdma_chan, periph_id) gdma_ll_rx_connect_to_periph(&GDMA, gdma_chan, periph_id);
|
|
|
+#define spi_dma_connect_tx_channel_to_periph(gdma_chan, periph_id) gdma_ll_tx_connect_to_periph(&GDMA, gdma_chan, periph_id);
|
|
|
+#endif
|
|
|
|
|
|
static const char *SPI_TAG = "spi";
|
|
|
|
|
|
@@ -114,7 +124,6 @@ bool spicommon_periph_free(spi_host_device_t host)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
int spicommon_irqsource_for_host(spi_host_device_t host)
|
|
|
{
|
|
|
return spi_periph_signal[host].irq;
|
|
|
@@ -143,7 +152,7 @@ static inline uint32_t get_dma_periph(int dma_chan)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-bool spicommon_dma_chan_claim (int dma_chan)
|
|
|
+bool spicommon_dma_chan_claim(int dma_chan)
|
|
|
{
|
|
|
bool ret = false;
|
|
|
assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM);
|
|
|
@@ -163,6 +172,8 @@ bool spicommon_dma_chan_claim (int dma_chan)
|
|
|
} else if (dma_chan==2) {
|
|
|
periph_module_enable(PERIPH_SPI3_DMA_MODULE);
|
|
|
}
|
|
|
+#elif SOC_GDMA_SUPPORTED
|
|
|
+ periph_module_enable(PERIPH_GDMA_MODULE);
|
|
|
#endif
|
|
|
portEXIT_CRITICAL(&spi_dma_spinlock);
|
|
|
|
|
|
@@ -171,7 +182,7 @@ bool spicommon_dma_chan_claim (int dma_chan)
|
|
|
|
|
|
bool spicommon_dma_chan_in_use(int dma_chan)
|
|
|
{
|
|
|
- assert(dma_chan==1 || dma_chan == 2);
|
|
|
+ assert(dma_chan ==1 || dma_chan == 2);
|
|
|
return spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan);
|
|
|
}
|
|
|
|
|
|
@@ -193,12 +204,39 @@ bool spicommon_dma_chan_free(int dma_chan)
|
|
|
} else if (dma_chan==2) {
|
|
|
periph_module_disable(PERIPH_SPI3_DMA_MODULE);
|
|
|
}
|
|
|
+#elif SOC_GDMA_SUPPORTED
|
|
|
+ periph_module_disable(PERIPH_GDMA_MODULE);
|
|
|
#endif
|
|
|
portEXIT_CRITICAL(&spi_dma_spinlock);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
|
|
|
+{
|
|
|
+#if CONFIG_IDF_TARGET_ESP32
|
|
|
+ DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
|
|
|
+#elif CONFIG_IDF_TARGET_ESP32S2
|
|
|
+ //On ESP32S2, each SPI controller has its own DMA channel. So there is no need to connect them.
|
|
|
+#elif SOC_GDMA_SUPPORTED
|
|
|
+ int gdma_chan, periph_id;
|
|
|
+ if (dma_chan == 1) {
|
|
|
+ gdma_chan = SOC_GDMA_SPI2_DMA_CHANNEL;
|
|
|
+ periph_id = GDMA_LL_TRIG_SRC_SPI2;
|
|
|
+ } else if (dma_chan == 2) {
|
|
|
+ gdma_chan = SOC_GDMA_SPI3_DMA_CHANNEL;
|
|
|
+ periph_id = GDMA_LL_TRIG_SRC_SPI3;
|
|
|
+ } else {
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+
|
|
|
+ spi_dma_connect_rx_channel_to_periph(gdma_chan, periph_id);
|
|
|
+ spi_dma_connect_tx_channel_to_periph(gdma_chan, periph_id);
|
|
|
+ spi_dma_set_rx_channel_priority(gdma_chan, 1);
|
|
|
+ spi_dma_set_tx_channel_priority(gdma_chan, 1);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config)
|
|
|
{
|
|
|
if (bus_config->sclk_io_num>=0 &&
|
|
|
@@ -222,7 +260,7 @@ it should be able to be initialized.
|
|
|
*/
|
|
|
esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t* flags_o)
|
|
|
{
|
|
|
- uint32_t temp_flag=0;
|
|
|
+ uint32_t temp_flag = 0;
|
|
|
|
|
|
bool miso_need_output;
|
|
|
bool mosi_need_output;
|
|
|
@@ -378,11 +416,6 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //Select DMA channel.
|
|
|
-#if CONFIG_IDF_TARGET_ESP32
|
|
|
- DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
|
|
|
-#endif
|
|
|
-
|
|
|
if (flags_o) *flags_o = temp_flag;
|
|
|
return ESP_OK;
|
|
|
}
|
|
|
@@ -481,11 +514,13 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
|
|
|
SPI_CHECK(spi_chan_claimed, "host_id already in use", ESP_ERR_INVALID_STATE);
|
|
|
|
|
|
if (dma_chan != 0) {
|
|
|
- bool dma_chan_claimed=spicommon_dma_chan_claim(dma_chan);
|
|
|
+ bool dma_chan_claimed = spicommon_dma_chan_claim(dma_chan);
|
|
|
if (!dma_chan_claimed) {
|
|
|
spicommon_periph_free(host_id);
|
|
|
SPI_CHECK(false, "dma channel already in use", ESP_ERR_INVALID_STATE);
|
|
|
}
|
|
|
+
|
|
|
+ spicommon_connect_spi_and_dma(host_id, dma_chan);
|
|
|
}
|
|
|
|
|
|
//clean and initialize the context
|