drivers: spi: esp32xx: Fix word size issue
This commit fixes the word size configuration issue described in #54746 by considering the data frame size when trasmitting in case the configuration is applied. It also fixes an heap corruption problem when using SPI DMA with a buffer that is not multiple of 32 bits in lenght and GDMA instance in initialization. Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>
This commit is contained in:
parent
08d1b33d07
commit
b100ffb1df
|
@ -70,29 +70,31 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
|
|||
size_t chunk_len = spi_context_max_continuous_chunk(&data->ctx);
|
||||
size_t max_buf_sz =
|
||||
cfg->dma_enabled ? SPI_DMA_MAX_BUFFER_SIZE : SOC_SPI_MAXIMUM_BUFFER_SIZE;
|
||||
chunk_len = MIN(chunk_len, max_buf_sz);
|
||||
size_t bit_len = chunk_len << 3;
|
||||
size_t transfer_len = data->word_size ? data->dfs : MIN(chunk_len, max_buf_sz);
|
||||
size_t bit_len = transfer_len << 3;
|
||||
uint8_t *rx_temp = NULL;
|
||||
uint8_t *tx_temp = NULL;
|
||||
uint8_t dma_len_tx = data->word_size ? data->dfs : ctx->tx_len;
|
||||
uint8_t dma_len_rx = data->word_size ? data->dfs : ctx->rx_len;
|
||||
|
||||
if (cfg->dma_enabled) {
|
||||
/* bit_len needs to be at least one byte long when using DMA */
|
||||
bit_len = !bit_len ? 8 : bit_len;
|
||||
if (ctx->tx_buf && !esp_ptr_dma_capable((uint32_t *)&ctx->tx_buf[0])) {
|
||||
tx_temp = k_malloc(ctx->tx_len);
|
||||
tx_temp = k_malloc(dma_len_tx);
|
||||
if (!tx_temp) {
|
||||
LOG_ERR("Error allocating temp buffer Tx");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(tx_temp, &ctx->tx_buf[0], ctx->tx_len);
|
||||
memcpy(tx_temp, &ctx->tx_buf[0], dma_len_tx);
|
||||
}
|
||||
if (ctx->rx_buf && (!esp_ptr_dma_capable((uint32_t *)&ctx->rx_buf[0]) ||
|
||||
((int)&ctx->rx_buf[0] % 4 != 0))) {
|
||||
((int)&ctx->rx_buf[0] % 4 != 0) || (dma_len_tx % 4 != 0))) {
|
||||
/* The rx buffer need to be length of
|
||||
* multiples of 32 bits to avoid heap
|
||||
* corruption.
|
||||
*/
|
||||
rx_temp = k_calloc(((ctx->rx_len << 3) + 31) / 8, sizeof(uint8_t));
|
||||
rx_temp = k_calloc(((dma_len_rx << 3) + 31) / 8, sizeof(uint8_t));
|
||||
if (!rx_temp) {
|
||||
LOG_ERR("Error allocating temp buffer Rx");
|
||||
k_free(tx_temp);
|
||||
|
@ -118,7 +120,7 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
|
|||
|
||||
/* send data */
|
||||
spi_hal_user_start(hal);
|
||||
spi_context_update_tx(&data->ctx, data->dfs, chunk_len);
|
||||
spi_context_update_tx(&data->ctx, data->dfs, transfer_len/data->dfs);
|
||||
|
||||
while (!spi_hal_usr_is_done(hal)) {
|
||||
/* nop */
|
||||
|
@ -128,10 +130,10 @@ static int IRAM_ATTR spi_esp32_transfer(const struct device *dev)
|
|||
spi_hal_fetch_result(hal);
|
||||
|
||||
if (rx_temp) {
|
||||
memcpy(&ctx->rx_buf[0], rx_temp, chunk_len);
|
||||
memcpy(&ctx->rx_buf[0], rx_temp, transfer_len);
|
||||
}
|
||||
|
||||
spi_context_update_rx(&data->ctx, data->dfs, chunk_len);
|
||||
spi_context_update_rx(&data->ctx, data->dfs, transfer_len/data->dfs);
|
||||
|
||||
k_free(tx_temp);
|
||||
k_free(rx_temp);
|
||||
|
@ -166,7 +168,7 @@ static int spi_esp32_init_dma(const struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef SOC_GDMA_SUPPORTED
|
||||
gdma_hal_init(&data->hal_gdma, cfg->dma_host);
|
||||
gdma_hal_init(&data->hal_gdma, 0);
|
||||
gdma_ll_enable_clock(data->hal_gdma.dev, true);
|
||||
gdma_ll_tx_reset_channel(data->hal_gdma.dev, cfg->dma_host);
|
||||
gdma_ll_rx_reset_channel(data->hal_gdma.dev, cfg->dma_host);
|
||||
|
@ -324,8 +326,6 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev,
|
|||
data->trans_config.line_mode.addr_lines = 1;
|
||||
data->trans_config.line_mode.cmd_lines = 1;
|
||||
|
||||
hal_dev->cs_setup = 1;
|
||||
|
||||
/* SPI mode */
|
||||
hal_dev->mode = 0;
|
||||
if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) {
|
||||
|
@ -351,18 +351,14 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t spi_esp32_get_frame_size(const struct spi_config *spi_cfg)
|
||||
static inline uint8_t spi_esp32_get_frame_size(const struct device *dev,
|
||||
const struct spi_config *spi_cfg)
|
||||
{
|
||||
uint8_t dfs = SPI_WORD_SIZE_GET(spi_cfg->operation);
|
||||
struct spi_esp32_data *data = dev->data;
|
||||
|
||||
dfs /= 8;
|
||||
data->word_size = SPI_WORD_SIZE_GET(spi_cfg->operation);
|
||||
|
||||
if ((dfs == 0) || (dfs > 4)) {
|
||||
LOG_WRN("Unsupported dfs, 1-byte size will be used");
|
||||
dfs = 1;
|
||||
}
|
||||
|
||||
return dfs;
|
||||
return data->word_size ? data->word_size >> 3 : 1;
|
||||
}
|
||||
|
||||
static int transceive(const struct device *dev,
|
||||
|
@ -393,7 +389,7 @@ static int transceive(const struct device *dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
data->dfs = spi_esp32_get_frame_size(spi_cfg);
|
||||
data->dfs = spi_esp32_get_frame_size(dev, spi_cfg);
|
||||
|
||||
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, data->dfs);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ struct spi_esp32_data {
|
|||
int irq_line;
|
||||
lldesc_t dma_desc_tx;
|
||||
lldesc_t dma_desc_rx;
|
||||
uint8_t word_size;
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SPI_ESP32_SPIM_H_ */
|
||||
|
|
Loading…
Reference in a new issue