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:
parent
ec08031e4b
commit
53f50c8183
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user