Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New SPI Master transaction flag to not use DMA on DMA enabled host. (IDFGH-7501) #9069

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/driver/include/driver/spi_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ typedef struct {
#define SPI_TRANS_MULTILINE_CMD (1<<9) ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase)
#define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode
#define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase)
#define SPI_TRANS_DONT_DMA (1<<11) ///< Do Not use DMA (even if it is configured)

/**
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
Expand Down
13 changes: 8 additions & 5 deletions components/driver/spi_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_
hal_trans.cmd = trans->cmd;
hal_trans.addr = trans->addr;
hal_trans.cs_keep_active = (trans->flags & SPI_TRANS_CS_KEEP_ACTIVE) ? 1 : 0;
hal_trans.dont_dma = (trans->flags & SPI_TRANS_DONT_DMA) ? 1 : 0;

//Set up OIO/QIO/DIO if needed
hal_trans.line_mode.data_lines = (trans->flags & SPI_TRANS_MODE_DIO) ? 2 :
Expand Down Expand Up @@ -634,7 +635,7 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.

#if CONFIG_IDF_TARGET_ESP32
if (bus_attr->dma_enabled) {
if (bus_attr->dma_enabled && (host->cur_trans_buf.trans->flags & SPI_TRANS_DONT_DMA) == 0) {
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan);
}
Expand Down Expand Up @@ -695,7 +696,7 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
if (trans_found) {
spi_trans_priv_t *const cur_trans_buf = &host->cur_trans_buf;
#if CONFIG_IDF_TARGET_ESP32
if (bus_attr->dma_enabled && (cur_trans_buf->buffer_to_rcv || cur_trans_buf->buffer_to_send)) {
if (bus_attr->dma_enabled && (cur_trans_buf->buffer_to_rcv || cur_trans_buf->buffer_to_send) && (cur_trans_buf->trans->flags & SPI_TRANS_DONT_DMA) == 0) {
//mark channel as active, so that the DMA will not be reset by the slave
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_transfer_active(bus_attr->tx_dma_chan);
Expand Down Expand Up @@ -725,6 +726,8 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
//check transmission length
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_DONT_DMA)==0 || trans_desc->length <= SOC_SPI_MAXIMUM_BUFFER_SIZE*8, "txdata transfer > host maximum without DMA", ESP_ERR_INVALID_ARG);
SPI_CHECK((trans_desc->flags & SPI_TRANS_DONT_DMA)==0 || trans_desc->rxlength <= SOC_SPI_MAXIMUM_BUFFER_SIZE*8, "rxdata transfer > host maximum without DMA", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
SPI_CHECK(is_half_duplex || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);
Expand All @@ -737,7 +740,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both multi-line mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
SPI_CHECK(!is_half_duplex || !(bus_attr->dma_enabled && (trans_desc->flags & SPI_TRANS_DONT_DMA)==0) || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
#endif
#if !SOC_SPI_HD_BOTH_INOUT_SUPPORTED
//On these chips, HW doesn't support using both TX and RX phases when in halfduplex mode
Expand Down Expand Up @@ -842,7 +845,7 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
}

spi_trans_priv_t trans_buf;
ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled));
ret = setup_priv_desc(trans_desc, &trans_buf, ((host->bus_attr->dma_enabled) && (trans_desc->flags & SPI_TRANS_DONT_DMA) == 0));
if (ret != ESP_OK) return ret;

#ifdef CONFIG_PM_ENABLE
Expand Down Expand Up @@ -1000,7 +1003,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
}
if (ret != ESP_OK) return ret;

ret = setup_priv_desc(trans_desc, &host->cur_trans_buf, (host->bus_attr->dma_enabled));
ret = setup_priv_desc(trans_desc, &host->cur_trans_buf, ((host->bus_attr->dma_enabled) && (trans_desc->flags & SPI_TRANS_DONT_DMA) == 0));
if (ret!=ESP_OK) return ret;

//Polling, no interrupt is used.
Expand Down
1 change: 1 addition & 0 deletions components/hal/include/hal/spi_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct {
uint8_t *rcv_buffer; ///< Buffer to hold the receive data.
spi_line_mode_t line_mode; ///< SPI line mode of this transaction
int cs_keep_active; ///< Keep CS active after transaction
int dont_dma; ///< Keep CS active after transaction
} spi_hal_trans_config_t;

/**
Expand Down
8 changes: 4 additions & 4 deletions components/hal/spi_hal_iram.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de

//Fill DMA descriptors
if (trans->rcv_buffer) {
if (!hal->dma_enabled) {
if (!hal->dma_enabled || trans->dont_dma) {
//No need to setup anything; we'll copy the result out of the work registers directly later.
} else {
lldesc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
Expand All @@ -152,15 +152,15 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
#if CONFIG_IDF_TARGET_ESP32
else {
//DMA temporary workaround: let RX DMA work somehow to avoid the issue in ESP32 v0/v1 silicon
if (hal->dma_enabled && !dev->half_duplex) {
if (hal->dma_enabled && !dev->half_duplex && !trans->dont_dma) {
spi_ll_dma_rx_enable(hal->hw, 1);
spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, 0);
}
}
#endif

if (trans->send_buffer) {
if (!hal->dma_enabled) {
if (!hal->dma_enabled || trans->dont_dma) {
//Need to copy data to registers manually
spi_ll_write_buffer(hw, trans->send_buffer, trans->tx_bitlen);
} else {
Expand Down Expand Up @@ -197,7 +197,7 @@ void spi_hal_fetch_result(const spi_hal_context_t *hal)
{
const spi_hal_trans_config_t *trans = &hal->trans_config;

if (trans->rcv_buffer && !hal->dma_enabled) {
if (trans->rcv_buffer && (!hal->dma_enabled || trans->dont_dma)) {
//Need to copy from SPI regs to result buffer.
spi_ll_read_buffer(hal->hw, trans->rcv_buffer, trans->rx_bitlen);
}
Expand Down