xtensa/esp32s3: Configure DMA maximum buffer size based on access to different RAM

Signed-off-by: chenwen@espressif.com <chenwen@espressif.com>
This commit is contained in:
chenwen@espressif.com 2024-02-27 19:47:17 +08:00 committed by Xiang Xiao
parent ec08031e4b
commit 53f50c8183
7 changed files with 71 additions and 22 deletions

View File

@ -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);
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)
{
dma_size = ESP32S3_DMA_BUFLEN_MAX_4B_ALIGNED;
}
for (i = 0; i < num; i++)
{
data_len = MIN(bytes, ESP32S3_DMA_BUFLEN_MAX);
data_len = MIN(bytes, dma_size);
if (!tx && (burst_en || buffer_in_psram))
{
/* Buffer length must be rounded to next alignment boundary. */
/* Buffer length must be rounded to next 32-bit 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;

View File

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

View File

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

View File

@ -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);
}
}

View File

@ -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);
}

View File

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

View File

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