This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 53f50c8183 xtensa/esp32s3: Configure DMA maximum buffer size based on
access to different RAM
53f50c8183 is described below
commit 53f50c818372de344b983e9f584cfc30358f7826
Author: [email protected] <[email protected]>
AuthorDate: Tue Feb 27 19:47:17 2024 +0800
xtensa/esp32s3: Configure DMA maximum buffer size based on access to
different RAM
Signed-off-by: [email protected] <[email protected]>
---
arch/xtensa/src/esp32s3/esp32s3_dma.c | 52 ++++++++++++++++++++++++++---
arch/xtensa/src/esp32s3/esp32s3_dma.h | 13 +++++---
arch/xtensa/src/esp32s3/esp32s3_i2s.c | 12 ++++---
arch/xtensa/src/esp32s3/esp32s3_lcd.c | 4 +--
arch/xtensa/src/esp32s3/esp32s3_qspi.c | 4 +--
arch/xtensa/src/esp32s3/esp32s3_spi.c | 4 +--
arch/xtensa/src/esp32s3/esp32s3_spi_slave.c | 4 +--
7 files changed, 71 insertions(+), 22 deletions(-)
diff --git a/arch/xtensa/src/esp32s3/esp32s3_dma.c
b/arch/xtensa/src/esp32s3/esp32s3_dma.c
index 5c21f371c4..c786d4945d 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_dma.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_dma.c
@@ -53,6 +53,7 @@
#endif
#define DMA_INVALID_PERIPH_ID (0x3F)
+#define GDMA_CH_REG_ADDR(_r, _ch) ((_r) + (_ch) * GDMA_REG_OFFSET)
/****************************************************************************
* Private Data
@@ -230,6 +231,7 @@ void esp32s3_dma_release(int chan)
* pbuf - RX/TX buffer pointer
* len - RX/TX buffer length
* tx - true: TX mode (transmitter); false: RX mode (receiver)
+ * chan - DMA channel of the receiver/transmitter
*
* Returned Value:
* Bound pbuf data bytes
@@ -237,7 +239,7 @@ void esp32s3_dma_release(int chan)
****************************************************************************/
uint32_t esp32s3_dma_setup(struct esp32s3_dmadesc_s *dmadesc, uint32_t num,
- uint8_t *pbuf, uint32_t len, bool tx)
+ uint8_t *pbuf, uint32_t len, bool tx, int chan)
{
int i;
uint32_t regval;
@@ -245,19 +247,59 @@ uint32_t esp32s3_dma_setup(struct esp32s3_dmadesc_s
*dmadesc, uint32_t num,
uint8_t *pdata = pbuf;
uint32_t data_len;
uint32_t buf_len;
+ int alignment = 4;
+ int dma_size = ESP32S3_DMA_BUFFER_MAX_SIZE;
+ bool buffer_in_psram = esp32s3_ptr_extram(pdata);
+ int block_size_index = 0;
+ uint32_t addr = GDMA_CH_REG_ADDR(DMA_IN_CONF0_CH0_REG, chan);
+ bool burst_en = REG_GET_FIELD(addr, DMA_IN_DATA_BURST_EN_CH0);
DEBUGASSERT(dmadesc != NULL);
DEBUGASSERT(num > 0);
DEBUGASSERT(pbuf != NULL);
DEBUGASSERT(len > 0);
+ DEBUGASSERT(chan >= 0 && chan < ESP32S3_DMA_CHAN_MAX);
- for (i = 0; i < num; i++)
+ if (!tx && buffer_in_psram)
+ {
+ addr = GDMA_CH_REG_ADDR(DMA_IN_CONF1_CH0_REG, chan);
+ block_size_index = REG_GET_FIELD(addr, DMA_IN_EXT_MEM_BK_SIZE_CH0);
+ switch (block_size_index)
+ {
+ case ESP32S3_DMA_EXT_MEMBLK_64B:
+ alignment = 64;
+ break;
+
+ case ESP32S3_DMA_EXT_MEMBLK_32B:
+ alignment = 32;
+ break;
+
+ case ESP32S3_DMA_EXT_MEMBLK_16B:
+ default:
+ alignment = 16;
+ break;
+ }
+
+ dma_size = 0x1000 - alignment;
+ }
+ else if(!tx && burst_en)
{
- data_len = MIN(bytes, ESP32S3_DMA_BUFLEN_MAX);
+ dma_size = ESP32S3_DMA_BUFLEN_MAX_4B_ALIGNED;
+ }
- /* Buffer length must be rounded to next 32-bit boundary. */
+ for (i = 0; i < num; i++)
+ {
+ data_len = MIN(bytes, dma_size);
+ if (!tx && (burst_en || buffer_in_psram))
+ {
+ /* Buffer length must be rounded to next alignment boundary. */
- buf_len = ALIGN_UP(data_len, sizeof(uintptr_t));
+ buf_len = ALIGN_UP(data_len, alignment);
+ }
+ else
+ {
+ buf_len = data_len;
+ }
dmadesc[i].ctrl = ESP32S3_DMA_CTRL_OWN;
diff --git a/arch/xtensa/src/esp32s3/esp32s3_dma.h
b/arch/xtensa/src/esp32s3/esp32s3_dma.h
index bb9c762ec5..29427d4f14 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_dma.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_dma.h
@@ -54,13 +54,17 @@ extern "C"
#define SET_GDMA_CH_BITS(_r, _ch, _b) modifyreg32((_r) + (_ch) *
GDMA_REG_OFFSET, 0, (_b))
#define CLR_GDMA_CH_BITS(_r, _ch, _b) modifyreg32((_r) + (_ch) *
GDMA_REG_OFFSET, (_b), 0)
-/* DMA max data length */
+/* Maximum size of the buffer that can be attached to DMA descriptor */
-#define ESP32S3_DMA_DATALEN_MAX (0x1000 - 4)
+#define ESP32S3_DMA_BUFFER_MAX_SIZE (0x1000 - 1)
+
+/* DMA max data length, and aligned to 4Bytes */
+
+#define ESP32S3_DMA_BUFLEN_MAX_4B_ALIGNED (0x1000 - 4)
/* DMA max buffer length */
-#define ESP32S3_DMA_BUFLEN_MAX ESP32S3_DMA_DATALEN_MAX
+#define ESP32S3_DMA_BUFLEN_MAX ESP32S3_DMA_BUFFER_MAX_SIZE
/* DMA channel number */
@@ -174,6 +178,7 @@ void esp32s3_dma_release(int chan);
* pbuf - RX/TX buffer pointer
* len - RX/TX buffer length
* tx - true: TX mode (transmitter); false: RX mode (receiver)
+ * chan - DMA channel of the receiver/transmitter
*
* Returned Value:
* Bound pbuf data bytes
@@ -181,7 +186,7 @@ void esp32s3_dma_release(int chan);
****************************************************************************/
uint32_t esp32s3_dma_setup(struct esp32s3_dmadesc_s *dmadesc, uint32_t num,
- uint8_t *pbuf, uint32_t len, bool tx);
+ uint8_t *pbuf, uint32_t len, bool tx, int chan);
/****************************************************************************
* Name: esp32s3_dma_load
diff --git a/arch/xtensa/src/esp32s3/esp32s3_i2s.c
b/arch/xtensa/src/esp32s3/esp32s3_i2s.c
index 34bda4b3c1..06ee0116c2 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_i2s.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_i2s.c
@@ -895,7 +895,8 @@ static IRAM_ATTR int i2s_txdma_setup(struct esp32s3_i2s_s
*priv,
bytes_queued = esp32s3_dma_setup(outlink, I2S_DMADESC_NUM,
bfcontainer->buf,
- bfcontainer->nbytes, I2S_TX);
+ bfcontainer->nbytes, I2S_TX,
+ priv->dma_channel);
if (bytes_queued != bfcontainer->nbytes)
{
@@ -956,7 +957,8 @@ static int i2s_rxdma_setup(struct esp32s3_i2s_s *priv,
bytes_queued = esp32s3_dma_setup(inlink, I2S_DMADESC_NUM,
bfcontainer->apb->samp,
- bfcontainer->nbytes, I2S_RX);
+ bfcontainer->nbytes, I2S_RX,
+ priv->dma_channel);
if (bytes_queued != bfcontainer->nbytes)
{
@@ -2772,12 +2774,12 @@ static int i2s_send(struct i2s_dev_s *dev, struct
ap_buffer_s *apb,
nbytes -= (nbytes % (priv->data_width / 8));
- if (nbytes > (ESP32S3_DMA_DATALEN_MAX * I2S_DMADESC_NUM))
+ if (nbytes > (ESP32S3_DMA_BUFLEN_MAX * I2S_DMADESC_NUM))
{
i2serr("Required buffer size can't fit into DMA outlink "
"(exceeds in %" PRIu32 " bytes). Try to increase the "
"number of the DMA descriptors (CONFIG_I2S_DMADESC_NUM).",
- nbytes - (ESP32S3_DMA_DATALEN_MAX * I2S_DMADESC_NUM));
+ nbytes - (ESP32S3_DMA_BUFLEN_MAX * I2S_DMADESC_NUM));
return -EFBIG;
}
@@ -2880,7 +2882,7 @@ static int i2s_receive(struct i2s_dev_s *dev, struct
ap_buffer_s *apb,
nbytes -= (nbytes % (priv->data_width / 8));
- nbytes = MIN(nbytes, ESP32S3_DMA_DATALEN_MAX);
+ nbytes = MIN(nbytes, ESP32S3_DMA_BUFLEN_MAX);
/* Allocate a buffer container in advance */
diff --git a/arch/xtensa/src/esp32s3/esp32s3_lcd.c
b/arch/xtensa/src/esp32s3/esp32s3_lcd.c
index 1615fcb1b6..7d3db754c5 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_lcd.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_lcd.c
@@ -135,7 +135,7 @@
ESP32S3_LCD_DATA_WIDTH)
#define ESP32S3_LCD_DMADESC_NUM (ESP32S3_LCD_FB_SIZE / \
- ESP32S3_DMA_DATALEN_MAX + 1)
+ ESP32S3_DMA_BUFLEN_MAX + 1)
#define ESP32S3_LCD_LAYERS CONFIG_ESP32S3_LCD_BUFFER_LAYERS
@@ -666,7 +666,7 @@ static void esp32s3_lcd_dmasetup(void)
ESP32S3_LCD_DMADESC_NUM,
layer->framebuffer,
ESP32S3_LCD_FB_SIZE,
- true);
+ true, priv->dma_channel);
}
}
diff --git a/arch/xtensa/src/esp32s3/esp32s3_qspi.c
b/arch/xtensa/src/esp32s3/esp32s3_qspi.c
index 544dfc4607..15b1df582f 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_qspi.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_qspi.c
@@ -992,7 +992,7 @@ static int esp32s3_qspi_memory(struct qspi_dev_s *dev,
QSPI_DMA_DESC_NUM,
(uint8_t *)meminfo->buffer,
meminfo->buflen,
- true);
+ true, priv->dma_channel);
esp32s3_dma_load(priv->dma_desc, priv->dma_channel, true);
esp32s3_dma_enable(priv->dma_channel, true);
}
@@ -1008,7 +1008,7 @@ static int esp32s3_qspi_memory(struct qspi_dev_s *dev,
QSPI_DMA_DESC_NUM,
(uint8_t *)meminfo->buffer,
meminfo->buflen,
- false);
+ false, priv->dma_channel);
esp32s3_dma_load(priv->dma_desc, priv->dma_channel, false);
esp32s3_dma_enable(priv->dma_channel, false);
}
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spi.c
b/arch/xtensa/src/esp32s3/esp32s3_spi.c
index 54b1238b2a..03f7f2b460 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spi.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_spi.c
@@ -909,7 +909,7 @@ static void esp32s3_spi_dma_exchange(struct
esp32s3_spi_priv_s *priv,
SPI_DMA_TX_ENA_M);
n = esp32s3_dma_setup(priv->dma_txdesc, SPI_DMA_DESC_NUM,
- tp, bytes, true);
+ tp, bytes, true, priv->dma_channel);
esp32s3_dma_load(priv->dma_txdesc, channel, true);
esp32s3_dma_enable(channel, true);
@@ -935,7 +935,7 @@ static void esp32s3_spi_dma_exchange(struct
esp32s3_spi_priv_s *priv,
SPI_DMA_RX_ENA_M);
esp32s3_dma_setup(priv->dma_rxdesc, SPI_DMA_DESC_NUM,
- rp, bytes, false);
+ rp, bytes, false, priv->dma_channel);
esp32s3_dma_load(priv->dma_rxdesc, channel, false);
esp32s3_dma_enable(channel, false);
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spi_slave.c
b/arch/xtensa/src/esp32s3/esp32s3_spi_slave.c
index a763563a3b..b193123031 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spi_slave.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_spi_slave.c
@@ -904,7 +904,7 @@ static void spislave_setup_rx_dma(struct spislave_priv_s
*priv)
SPI_DMA_DESC_NUM,
priv->rx_buffer + priv->rx_length,
length,
- false);
+ false, priv->dma_channel);
esp32s3_dma_load(priv->dma_rxdesc, priv->dma_channel, false);
priv->rx_dma_offset = priv->rx_length;
@@ -948,7 +948,7 @@ static void spislave_setup_tx_dma(struct spislave_priv_s
*priv)
SPI_DMA_DESC_NUM,
priv->tx_buffer,
SPI_SLAVE_BUFSIZE,
- true);
+ true, priv->dma_channel);
esp32s3_dma_load(priv->dma_txdesc, priv->dma_channel, true);
spislave_dma_tx_fifo_reset(priv);