mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-25 23:08:03 +03:00
fix(driver_spi): fixed spi data error on re-install other host
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_macros.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/gpio.h"
|
||||
@@ -29,12 +30,9 @@
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "hal/spi_hal.h"
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "hal/gdma_ll.h"
|
||||
#endif
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "soc/dport_reg.h"
|
||||
#include "hal/gdma_ll.h" // for GDMA_LL_AHB_BURST_SIZE_ADJUSTABLE
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
#include "esp_private/mspi_mem_barrier.h"
|
||||
#endif
|
||||
@@ -198,15 +196,6 @@ static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void connect_spi_and_dma(spi_host_device_t host, int dma_chan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//On ESP32S2, each SPI controller has its own DMA channel. So there is no need to connect them.
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t dma_burst_size, spi_dma_ctx_t *dma_ctx)
|
||||
{
|
||||
assert(is_valid_host(host_id));
|
||||
@@ -248,7 +237,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
|
||||
if (!success) {
|
||||
SPI_CHECK(false, "no available dma channel", ESP_ERR_NOT_FOUND);
|
||||
}
|
||||
connect_spi_and_dma(host_id, actual_dma_chan);
|
||||
spi_ll_dma_connect_host(host_id, actual_dma_chan);
|
||||
|
||||
spi_dma_enable_burst(dma_ctx->tx_dma_chan, true, true);
|
||||
spi_dma_enable_burst(dma_ctx->rx_dma_chan, true, true);
|
||||
@@ -526,6 +515,7 @@ esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
|
||||
assert(spi_dma_chan_enabled & BIT(dma_chan));
|
||||
|
||||
portENTER_CRITICAL(&spi_dma_spinlock);
|
||||
spi_ll_dma_disconnect_host(host_id);
|
||||
spi_dma_chan_enabled &= ~BIT(dma_chan);
|
||||
_spicommon_dma_rcc_clock_ctrl(dma_chan, false);
|
||||
portEXIT_CRITICAL(&spi_dma_spinlock);
|
||||
|
||||
@@ -803,6 +803,39 @@ TEST_CASE("SPI Master no response when switch from host1 (SPI2) to host2 (SPI3)"
|
||||
TEST_ESP_OK(spi_bus_free(host));
|
||||
}
|
||||
|
||||
#if !SOC_GDMA_SUPPORTED
|
||||
TEST_CASE("SPI DMA data error when switch between SPI2 and SPI3", "[spi]")
|
||||
{
|
||||
spi_device_handle_t dev_handle;
|
||||
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||
buscfg.miso_io_num = buscfg.mosi_io_num;
|
||||
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||
uint8_t send[13] = "hello spi x\n";
|
||||
uint8_t recv[16]; // esp32 dma rx need requirse 4 byte aligned length
|
||||
spi_transaction_t trans_cfg = {
|
||||
.length = 8 * sizeof(send),
|
||||
.tx_buffer = send,
|
||||
.rx_buffer = recv,
|
||||
};
|
||||
|
||||
for (int periph = SPI2_HOST; periph < SPI_HOST_MAX; periph ++) {
|
||||
printf("Test GPSPI%d\n", periph + 1);
|
||||
TEST_ESP_OK(spi_bus_initialize(periph, &buscfg, SPI_DMA_CH_AUTO));
|
||||
TEST_ESP_OK(spi_bus_add_device(periph, &devcfg, &dev_handle));
|
||||
|
||||
for (uint8_t cnt = 0; cnt < 2; cnt ++) {
|
||||
memset(recv, 0, sizeof(recv));
|
||||
send[10] = cnt + 'A';
|
||||
TEST_ESP_OK(spi_device_transmit(dev_handle, &trans_cfg));
|
||||
printf("%s", recv);
|
||||
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, sizeof(send));
|
||||
}
|
||||
TEST_ESP_OK(spi_bus_remove_device(dev_handle));
|
||||
TEST_ESP_OK(spi_bus_free(periph));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DRAM_ATTR static uint32_t data_dram[80] = {0};
|
||||
//force to place in code area.
|
||||
static const uint8_t data_drom[320 + 3] = {
|
||||
|
||||
@@ -1136,6 +1136,27 @@ static inline void spi_ll_dma_reset_register(spi_host_device_t host_id)
|
||||
spi_ll_dma_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Connect DMA channel for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
* @param dma_chan DMA channel ID
|
||||
*/
|
||||
static inline void spi_ll_dma_connect_host(spi_host_device_t host_id, int dma_chan)
|
||||
{
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host_id * 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect DMA channel for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
*/
|
||||
static inline void spi_ll_dma_disconnect_host(spi_host_device_t host_id)
|
||||
{
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, 0, (host_id * 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset RX DMA which stores the data received from a peripheral into RAM.
|
||||
*
|
||||
|
||||
@@ -1318,6 +1318,27 @@ static inline void spi_ll_dma_reset_register(spi_host_device_t host_id)
|
||||
spi_ll_dma_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Connect DMA channel for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
* @param dma_chan DMA channel ID
|
||||
*/
|
||||
static inline void spi_ll_dma_connect_host(spi_host_device_t host_id, int dma_chan)
|
||||
{
|
||||
//On ESP32S2, each SPI controller has its own DMA channel. So there is no need to connect them.
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect DMA channel for SPI
|
||||
*
|
||||
* @param host_id SPI host ID
|
||||
*/
|
||||
static inline void spi_ll_dma_disconnect_host(spi_host_device_t host_id)
|
||||
{
|
||||
//On ESP32S2, each SPI controller has its own DMA channel. So there is no need to disconnect them.
|
||||
}
|
||||
|
||||
//---------------------------------------------------RX-------------------------------------------------//
|
||||
/**
|
||||
* Reset RX DMA which stores the data received from a peripheral into RAM.
|
||||
|
||||
Reference in New Issue
Block a user