risc-v/esp32c3: Add support for DMA transfers on SPI driver
This commit is contained in:
parent
132ffdd28d
commit
26a5cb2094
@ -323,6 +323,29 @@ config ESP32C3_SPI_UDCS
|
||||
|
||||
if ESP32C3_SPI2
|
||||
|
||||
config ESP32C3_SPI2_DMA
|
||||
bool "SPI2 use GDMA"
|
||||
default n
|
||||
depends on ESP32C3_DMA
|
||||
---help---
|
||||
Enable support for transfers using the GDMA engine.
|
||||
|
||||
config ESP32C3_SPI2_DMADESC_NUM
|
||||
int "SPI2 Master GDMA maximum number of descriptors"
|
||||
default 2
|
||||
depends on ESP32C3_SPI2_DMA
|
||||
---help---
|
||||
Configure the maximum number of out-link/in-link descriptors to
|
||||
be chained for a GDMA transfer.
|
||||
|
||||
config ESP32C3_SPI2_DMATHRESHOLD
|
||||
int "SPI2 GDMA threshold"
|
||||
default 64
|
||||
depends on ESP32C3_SPI2_DMA
|
||||
---help---
|
||||
When SPI GDMA is enabled, GDMA transfers whose size are below the
|
||||
defined threshold will be performed by polling logic.
|
||||
|
||||
config ESP32C3_SPI2_CSPIN
|
||||
int "SPI2 CS Pin"
|
||||
default 10
|
||||
|
@ -32,17 +32,24 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/spi/spi.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "esp32c3_spi.h"
|
||||
#include "esp32c3_irq.h"
|
||||
#include "esp32c3_gpio.h"
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
#include "esp32c3_dma.h"
|
||||
#endif
|
||||
|
||||
#include "riscv_arch.h"
|
||||
#include "hardware/esp32c3_gpio_sigmap.h"
|
||||
#include "hardware/esp32c3_pinmap.h"
|
||||
@ -62,6 +69,18 @@
|
||||
# define SPI_HAVE_SWCS FALSE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
|
||||
/* SPI DMA RX/TX number of descriptors */
|
||||
|
||||
#define SPI_DMA_DESC_NUM (CONFIG_ESP32C3_SPI2_DMADESC_NUM)
|
||||
|
||||
/* SPI DMA reset before exchange */
|
||||
|
||||
#define SPI_DMA_RESET_MASK (SPI_DMA_AFIFO_RST_M | SPI_RX_AFIFO_RST_M)
|
||||
|
||||
#endif
|
||||
|
||||
/* Verify whether SPI has been assigned IOMUX pins.
|
||||
* Otherwise, SPI signals will be routed via GPIO Matrix.
|
||||
*/
|
||||
@ -119,8 +138,16 @@ struct esp32c3_spi_config_s
|
||||
uint8_t mosi_pin; /* GPIO configuration for MOSI */
|
||||
uint8_t miso_pin; /* GPIO configuration for MISO */
|
||||
uint8_t clk_pin; /* GPIO configuration for CLK */
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
uint8_t periph; /* Peripheral ID */
|
||||
uint8_t irq; /* Interrupt ID */
|
||||
#endif
|
||||
uint32_t clk_bit; /* Clock enable bit */
|
||||
uint32_t rst_bit; /* SPI reset bit */
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
uint32_t dma_clk_bit; /* DMA clock enable bit */
|
||||
uint32_t dma_rst_bit; /* DMA reset bit */
|
||||
#endif
|
||||
uint32_t cs_insig; /* SPI CS input signal index */
|
||||
uint32_t cs_outsig; /* SPI CS output signal index */
|
||||
uint32_t mosi_insig; /* SPI MOSI input signal index */
|
||||
@ -142,6 +169,11 @@ struct esp32c3_spi_priv_s
|
||||
const struct esp32c3_spi_config_s *config;
|
||||
int refs; /* Reference count */
|
||||
sem_t exclsem; /* Held while chip is selected for mutual exclusion */
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
sem_t sem_isr; /* Interrupt wait semaphore */
|
||||
int cpuint; /* SPI interrupt ID */
|
||||
int32_t dma_channel; /* Channel assigned by the GDMA driver */
|
||||
#endif
|
||||
uint32_t frequency; /* Requested clock frequency */
|
||||
uint32_t actual; /* Actual clock frequency */
|
||||
enum spi_mode_e mode; /* Actual SPI hardware mode */
|
||||
@ -170,6 +202,19 @@ static uint32_t esp32c3_spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
|
||||
static void esp32c3_spi_exchange(FAR struct spi_dev_s *dev,
|
||||
FAR const void *txbuffer,
|
||||
FAR void *rxbuffer, size_t nwords);
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
static int esp32c3_spi_interrupt(int irq, void *context, FAR void *arg);
|
||||
static int esp32c3_spi_sem_waitdone(FAR struct esp32c3_spi_priv_s *priv);
|
||||
static void esp32c3_spi_dma_exchange(FAR struct esp32c3_spi_priv_s *priv,
|
||||
FAR const void *txbuffer,
|
||||
FAR void *rxbuffer,
|
||||
uint32_t nwords);
|
||||
#else
|
||||
static void esp32c3_spi_poll_exchange(FAR struct esp32c3_spi_priv_s *priv,
|
||||
FAR const void *txbuffer,
|
||||
FAR void *rxbuffer,
|
||||
size_t nwords);
|
||||
#endif
|
||||
#ifndef CONFIG_SPI_EXCHANGE
|
||||
static void esp32c3_spi_sndblock(FAR struct spi_dev_s *dev,
|
||||
FAR const void *txbuffer,
|
||||
@ -181,6 +226,9 @@ static void esp32c3_spi_recvblock(FAR struct spi_dev_s *dev,
|
||||
#ifdef CONFIG_SPI_TRIGGER
|
||||
static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev);
|
||||
#endif
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
static void esp32c3_spi_dma_init(FAR struct spi_dev_s *dev);
|
||||
#endif
|
||||
static void esp32c3_spi_init(FAR struct spi_dev_s *dev);
|
||||
static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev);
|
||||
|
||||
@ -198,8 +246,16 @@ static const struct esp32c3_spi_config_s esp32c3_spi2_config =
|
||||
.mosi_pin = CONFIG_ESP32C3_SPI2_MOSIPIN,
|
||||
.miso_pin = CONFIG_ESP32C3_SPI2_MISOPIN,
|
||||
.clk_pin = CONFIG_ESP32C3_SPI2_CLKPIN,
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
.periph = ESP32C3_PERIPH_SPI2,
|
||||
.irq = ESP32C3_IRQ_SPI2,
|
||||
#endif
|
||||
.clk_bit = SYSTEM_SPI2_CLK_EN,
|
||||
.rst_bit = SYSTEM_SPI2_RST,
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
.dma_clk_bit = SYSTEM_SPI2_DMA_CLK_EN,
|
||||
.dma_rst_bit = SYSTEM_SPI2_DMA_RST,
|
||||
#endif
|
||||
.cs_insig = FSPICS0_IN_IDX,
|
||||
.cs_outsig = FSPICS0_OUT_IDX,
|
||||
.mosi_insig = FSPID_IN_IDX,
|
||||
@ -243,20 +299,34 @@ static const struct spi_ops_s esp32c3_spi2_ops =
|
||||
|
||||
static struct esp32c3_spi_priv_s esp32c3_spi2_priv =
|
||||
{
|
||||
.spi_dev =
|
||||
{
|
||||
.ops = &esp32c3_spi2_ops
|
||||
},
|
||||
.config = &esp32c3_spi2_config,
|
||||
.refs = 0,
|
||||
.exclsem = SEM_INITIALIZER(0),
|
||||
.frequency = 0,
|
||||
.actual = 0,
|
||||
.mode = 0,
|
||||
.nbits = 0
|
||||
.spi_dev =
|
||||
{
|
||||
.ops = &esp32c3_spi2_ops
|
||||
},
|
||||
.config = &esp32c3_spi2_config,
|
||||
.refs = 0,
|
||||
.exclsem = SEM_INITIALIZER(0),
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
.cpuint = -ENOMEM,
|
||||
.dma_channel = -1,
|
||||
#endif
|
||||
.frequency = 0,
|
||||
.actual = 0,
|
||||
.mode = 0,
|
||||
.nbits = 0
|
||||
};
|
||||
#endif /* CONFIG_ESP32C3_SPI2 */
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
|
||||
/* SPI DMA RX/TX description */
|
||||
|
||||
static struct esp32c3_dmadesc_s dma_rxdesc[SPI_DMA_DESC_NUM];
|
||||
static struct esp32c3_dmadesc_s dma_txdesc[SPI_DMA_DESC_NUM];
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -272,7 +342,7 @@ static struct esp32c3_spi_priv_s esp32c3_spi2_priv =
|
||||
* bits - Bits to be set
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -294,7 +364,7 @@ static inline void esp32c3_spi_set_regbits(uint32_t addr, uint32_t bits)
|
||||
* bits - Bits to be cleared
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -313,10 +383,10 @@ static inline void esp32c3_spi_clr_regbits(uint32_t addr, uint32_t bits)
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* lock - true: Lock spi bus, false: unlock SPI bus
|
||||
* lock - true: Lock SPI bus, false: unlock SPI bus
|
||||
*
|
||||
* Returned Value:
|
||||
* The result of lock or unlock the SPI device
|
||||
* The result of lock or unlock the SPI device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -337,6 +407,37 @@ static int esp32c3_spi_lock(FAR struct spi_dev_s *dev, bool lock)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_sem_waitdone
|
||||
*
|
||||
* Description:
|
||||
* Wait for a transfer to complete.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - SPI private state data
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
static int esp32c3_spi_sem_waitdone(FAR struct esp32c3_spi_priv_s *priv)
|
||||
{
|
||||
int ret;
|
||||
struct timespec abstime;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
|
||||
abstime.tv_sec += 10;
|
||||
abstime.tv_nsec += 0;
|
||||
|
||||
ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_select
|
||||
*
|
||||
@ -356,7 +457,7 @@ static int esp32c3_spi_lock(FAR struct spi_dev_s *dev, bool lock)
|
||||
* selected - true: slave selected, false: slave de-selected
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -509,7 +610,7 @@ static uint32_t esp32c3_spi_setfrequency(FAR struct spi_dev_s *dev,
|
||||
* mode - The requested SPI mode
|
||||
*
|
||||
* Returned Value:
|
||||
* none
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -578,7 +679,7 @@ static void esp32c3_spi_setmode(FAR struct spi_dev_s *dev,
|
||||
* nbits - The number of bits in an SPI word.
|
||||
*
|
||||
* Returned Value:
|
||||
* none
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -617,6 +718,115 @@ static int esp32c3_spi_hwfeatures(FAR struct spi_dev_s *dev,
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_dma_exchange
|
||||
*
|
||||
* Description:
|
||||
* Exchange a block of data from SPI by DMA.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - SPI private state data
|
||||
* txbuffer - A pointer to the buffer of data to be sent
|
||||
* rxbuffer - A pointer to the buffer in which to receive data
|
||||
* nwords - the length of data that to be exchanged in units of words.
|
||||
* The wordsize is determined by the number of bits-per-word
|
||||
* selected for the SPI interface. If nbits <= 8, the data is
|
||||
* packed into uint8_t's; if nbits >8, the data is packed into
|
||||
* uint16_t's
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
static void esp32c3_spi_dma_exchange(FAR struct esp32c3_spi_priv_s *priv,
|
||||
FAR const void *txbuffer,
|
||||
FAR void *rxbuffer,
|
||||
uint32_t nwords)
|
||||
{
|
||||
const uint32_t total = nwords * (priv->nbits / 8);
|
||||
const int32_t channel = priv->dma_channel;
|
||||
uint32_t bytes = total;
|
||||
uint32_t n;
|
||||
uint8_t *tp;
|
||||
uint8_t *rp;
|
||||
|
||||
DEBUGASSERT((txbuffer != NULL) || (rxbuffer != NULL));
|
||||
|
||||
spiinfo("nwords=%" PRIu32 "\n", nwords);
|
||||
|
||||
tp = (uint8_t *)txbuffer;
|
||||
rp = (uint8_t *)rxbuffer;
|
||||
|
||||
if (tp == NULL)
|
||||
{
|
||||
tp = rp;
|
||||
}
|
||||
|
||||
esp32c3_spi_clr_regbits(SPI_DMA_INT_RAW_REG, SPI_TRANS_DONE_INT_RAW_M);
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_DMA_INT_ENA_REG, SPI_TRANS_DONE_INT_ENA_M);
|
||||
|
||||
while (bytes != 0)
|
||||
{
|
||||
/* Reset SPI DMA TX FIFO */
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_RESET_MASK);
|
||||
esp32c3_spi_clr_regbits(SPI_DMA_CONF_REG, SPI_DMA_RESET_MASK);
|
||||
|
||||
/* Enable SPI DMA TX */
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_TX_ENA_M);
|
||||
|
||||
n = esp32c3_dma_setup(channel, true, dma_txdesc, SPI_DMA_DESC_NUM,
|
||||
tp, bytes);
|
||||
esp32c3_dma_enable(channel, true);
|
||||
|
||||
putreg32((n * 8 - 1), SPI_MS_DLEN_REG);
|
||||
esp32c3_spi_set_regbits(SPI_USER_REG, SPI_USR_MOSI_M);
|
||||
|
||||
tp += n;
|
||||
|
||||
if (rp != NULL)
|
||||
{
|
||||
/* Enable SPI DMA RX */
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_RX_ENA_M);
|
||||
|
||||
esp32c3_dma_setup(channel, false, dma_rxdesc, SPI_DMA_DESC_NUM,
|
||||
rp, bytes);
|
||||
esp32c3_dma_enable(channel, false);
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_USER_REG, SPI_USR_MISO_M);
|
||||
|
||||
rp += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
esp32c3_spi_clr_regbits(SPI_USER_REG, SPI_USR_MISO_M);
|
||||
}
|
||||
|
||||
/* Trigger start of user-defined transaction for master. */
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_CMD_REG, SPI_UPDATE_M);
|
||||
|
||||
while ((getreg32(SPI_CMD_REG) & SPI_UPDATE_M) != 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
esp32c3_spi_set_regbits(SPI_CMD_REG, SPI_USR_M);
|
||||
|
||||
esp32c3_spi_sem_waitdone(priv);
|
||||
|
||||
bytes -= n;
|
||||
}
|
||||
|
||||
esp32c3_spi_clr_regbits(SPI_DMA_INT_ENA_REG, SPI_TRANS_DONE_INT_ENA_M);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_poll_send
|
||||
*
|
||||
@ -629,7 +839,7 @@ static int esp32c3_spi_hwfeatures(FAR struct spi_dev_s *dev,
|
||||
* number of bits selected for the SPI interface.
|
||||
*
|
||||
* Returned Value:
|
||||
* Received value
|
||||
* Received value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -679,7 +889,7 @@ static uint32_t esp32c3_spi_poll_send(FAR struct esp32c3_spi_priv_s *priv,
|
||||
* number of bits selected for the SPI interface.
|
||||
*
|
||||
* Returned Value:
|
||||
* Received value
|
||||
* Received value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -707,7 +917,7 @@ static uint32_t esp32c3_spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
|
||||
* uint16_t's
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -836,7 +1046,7 @@ static void esp32c3_spi_poll_exchange(FAR struct esp32c3_spi_priv_s *priv,
|
||||
* uint16_t's
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -847,7 +1057,18 @@ static void esp32c3_spi_exchange(FAR struct spi_dev_s *dev,
|
||||
{
|
||||
FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
|
||||
|
||||
esp32c3_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
size_t thld = CONFIG_ESP32C3_SPI2_DMATHRESHOLD;
|
||||
|
||||
if (nwords > thld)
|
||||
{
|
||||
esp32c3_spi_dma_exchange(priv, txbuffer, rxbuffer, nwords);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
esp32c3_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_EXCHANGE
|
||||
@ -868,7 +1089,7 @@ static void esp32c3_spi_exchange(FAR struct spi_dev_s *dev,
|
||||
* packed into uint16_t's
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -897,7 +1118,7 @@ static void esp32c3_spi_sndblock(FAR struct spi_dev_s *dev,
|
||||
* packed into uint16_t's
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -934,6 +1155,55 @@ static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_dma_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize ESP32-C3 SPI connection to GDMA engine.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
void esp32c3_spi_dma_init(FAR struct spi_dev_s *dev)
|
||||
{
|
||||
FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
|
||||
|
||||
/* Enable GDMA clock for the SPI peripheral */
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, 0, priv->config->dma_clk_bit);
|
||||
|
||||
/* Reset GDMA for the SPI peripheral */
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, priv->config->dma_rst_bit, 0);
|
||||
|
||||
/* Initialize GDMA controller */
|
||||
|
||||
esp32c3_dma_init();
|
||||
|
||||
/* Request a GDMA channel for SPI peripheral */
|
||||
|
||||
priv->dma_channel = esp32c3_dma_request(ESP32C3_DMA_PERIPH_SPI, 1, 1,
|
||||
true);
|
||||
if (priv->dma_channel < 0)
|
||||
{
|
||||
spierr("Failed to allocate GDMA channel\n");
|
||||
|
||||
DEBUGASSERT(false);
|
||||
}
|
||||
|
||||
/* Disable segment transaction mode for SPI Master */
|
||||
|
||||
putreg32((SPI_SLV_RX_SEG_TRANS_CLR_EN_M | SPI_SLV_TX_SEG_TRANS_CLR_EN_M),
|
||||
SPI_DMA_CONF_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_init
|
||||
*
|
||||
@ -944,7 +1214,7 @@ static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev)
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1015,6 +1285,13 @@ static void esp32c3_spi_init(FAR struct spi_dev_s *dev)
|
||||
putreg32(0, SPI_CTRL_REG);
|
||||
putreg32(VALUE_MASK(0, SPI_CS_HOLD_TIME), SPI_USER1_REG);
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
nxsem_init(&priv->sem_isr, 0, 0);
|
||||
nxsem_set_protocol(&priv->sem_isr, SEM_PRIO_NONE);
|
||||
|
||||
esp32c3_spi_dma_init(dev);
|
||||
#endif
|
||||
|
||||
esp32c3_spi_setfrequency(dev, config->clk_freq);
|
||||
esp32c3_spi_setbits(dev, config->width);
|
||||
esp32c3_spi_setmode(dev, config->mode);
|
||||
@ -1030,7 +1307,7 @@ static void esp32c3_spi_init(FAR struct spi_dev_s *dev)
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1038,6 +1315,10 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
|
||||
{
|
||||
FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->dma_clk_bit, 0);
|
||||
#endif
|
||||
|
||||
modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, priv->config->clk_bit);
|
||||
modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->clk_bit, 0);
|
||||
|
||||
@ -1047,6 +1328,34 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
|
||||
priv->nbits = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spi_interrupt
|
||||
*
|
||||
* Description:
|
||||
* Common SPI DMA interrupt handler.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Number of the IRQ that generated the interrupt
|
||||
* context - Interrupt register state save info
|
||||
* arg - SPI controller private data
|
||||
*
|
||||
* Returned Value:
|
||||
* Standard interrupt return value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
static int esp32c3_spi_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)arg;
|
||||
|
||||
esp32c3_spi_clr_regbits(SPI_DMA_INT_RAW_REG, SPI_TRANS_DONE_INT_RAW_M);
|
||||
nxsem_post(&priv->sem_isr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spibus_initialize
|
||||
*
|
||||
@ -1057,7 +1366,7 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
|
||||
* port - Port number (for hardware that has multiple SPI interfaces)
|
||||
*
|
||||
* Returned Value:
|
||||
* Valid SPI device structure reference on success; NULL on failure
|
||||
* Valid SPI device structure reference on success; NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1089,6 +1398,42 @@ FAR struct spi_dev_s *esp32c3_spibus_initialize(int port)
|
||||
return spi_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
if (priv->cpuint != -ENOMEM)
|
||||
{
|
||||
/* Disable the provided CPU Interrupt to configure it. */
|
||||
|
||||
up_disable_irq(priv->cpuint);
|
||||
}
|
||||
|
||||
priv->cpuint = esp32c3_request_irq(priv->config->periph,
|
||||
ESP32C3_INT_PRIO_DEF,
|
||||
ESP32C3_INT_LEVEL);
|
||||
if (priv->cpuint < 0)
|
||||
{
|
||||
/* Failed to allocate a CPU interrupt of this type. */
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (irq_attach(priv->config->irq, esp32c3_spi_interrupt, priv) != OK)
|
||||
{
|
||||
/* Failed to attach IRQ, so CPU interrupt must be freed. */
|
||||
|
||||
esp32c3_free_cpuint(priv->config->periph);
|
||||
priv->cpuint = -ENOMEM;
|
||||
leave_critical_section(flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Enable the CPU interrupt that is linked to the SPI device. */
|
||||
|
||||
up_enable_irq(priv->cpuint);
|
||||
#endif
|
||||
|
||||
esp32c3_spi_init(spi_dev);
|
||||
|
||||
priv->refs++;
|
||||
@ -1108,7 +1453,7 @@ FAR struct spi_dev_s *esp32c3_spibus_initialize(int port)
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1134,6 +1479,14 @@ int esp32c3_spibus_uninitialize(FAR struct spi_dev_s *dev)
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPI2_DMA
|
||||
up_disable_irq(priv->cpuint);
|
||||
esp32c3_free_cpuint(priv->config->periph);
|
||||
priv->cpuint = -ENOMEM;
|
||||
|
||||
nxsem_destroy(&priv->sem_isr);
|
||||
#endif
|
||||
|
||||
esp32c3_spi_deinit(dev);
|
||||
|
||||
nxsem_destroy(&priv->exclsem);
|
||||
|
Loading…
Reference in New Issue
Block a user