mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
refactor(spi_master): replace dma_ll in spi hal layer (part 2.1)
This commit is contained in:
@@ -12,37 +12,6 @@
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
//This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#if (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB) && (SOC_AHB_GDMA_VERSION == 1)
|
||||
#include "soc/gdma_struct.h"
|
||||
#include "hal/gdma_ll.h"
|
||||
#define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan)
|
||||
#define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan);
|
||||
#define spi_dma_ll_rx_start(dev, chan, addr) do {\
|
||||
gdma_ll_rx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
|
||||
gdma_ll_rx_start(&GDMA, chan);\
|
||||
} while (0)
|
||||
#define spi_dma_ll_tx_start(dev, chan, addr) do {\
|
||||
gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
|
||||
gdma_ll_tx_start(&GDMA, chan);\
|
||||
} while (0)
|
||||
|
||||
#elif (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI) //TODO: IDF-6152, refactor spi hal layer
|
||||
#include "hal/axi_dma_ll.h"
|
||||
#define spi_dma_ll_rx_reset(dev, chan) axi_dma_ll_rx_reset_channel(&AXI_DMA, chan)
|
||||
#define spi_dma_ll_tx_reset(dev, chan) axi_dma_ll_tx_reset_channel(&AXI_DMA, chan);
|
||||
#define spi_dma_ll_rx_start(dev, chan, addr) do {\
|
||||
axi_dma_ll_rx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
|
||||
axi_dma_ll_rx_start(&AXI_DMA, chan);\
|
||||
} while (0)
|
||||
#define spi_dma_ll_tx_start(dev, chan, addr) do {\
|
||||
axi_dma_ll_tx_set_desc_addr(&AXI_DMA, chan, (uint32_t)addr);\
|
||||
axi_dma_ll_tx_start(&AXI_DMA, chan);\
|
||||
} while (0)
|
||||
#endif
|
||||
#endif //SOC_GDMA_SUPPORTED
|
||||
|
||||
void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev)
|
||||
{
|
||||
//Configure clock settings
|
||||
@@ -145,94 +114,24 @@ void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev
|
||||
memcpy(&hal->trans_config, trans, sizeof(spi_hal_trans_config_t));
|
||||
}
|
||||
|
||||
#if SOC_NON_CACHEABLE_OFFSET
|
||||
#define ADDR_DMA_2_CPU(addr) ((typeof(addr))((uint32_t)(addr) + SOC_NON_CACHEABLE_OFFSET))
|
||||
#define ADDR_CPU_2_DMA(addr) ((typeof(addr))((uint32_t)(addr) - SOC_NON_CACHEABLE_OFFSET))
|
||||
#else
|
||||
#define ADDR_DMA_2_CPU(addr) (addr)
|
||||
#define ADDR_CPU_2_DMA(addr) (addr)
|
||||
#endif
|
||||
//TODO: IDF-6152, refactor spi hal layer
|
||||
static void s_spi_hal_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
|
||||
void spi_hal_enable_data_line(spi_dev_t *hw, bool mosi_ena, bool miso_ena)
|
||||
{
|
||||
dmadesc = ADDR_DMA_2_CPU(dmadesc);
|
||||
int n = 0;
|
||||
while (len) {
|
||||
int dmachunklen = len;
|
||||
if (dmachunklen > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) {
|
||||
dmachunklen = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
}
|
||||
if (is_rx) {
|
||||
//Receive needs DMA length rounded to next 32-bit boundary
|
||||
dmadesc[n].dw0.size = (dmachunklen + 3) & (~3);
|
||||
dmadesc[n].dw0.length = (dmachunklen + 3) & (~3);
|
||||
} else {
|
||||
dmadesc[n].dw0.size = dmachunklen;
|
||||
dmadesc[n].dw0.length = dmachunklen;
|
||||
}
|
||||
dmadesc[n].buffer = (uint8_t *)data;
|
||||
dmadesc[n].dw0.suc_eof = 0;
|
||||
dmadesc[n].dw0.owner = 1;
|
||||
dmadesc[n].next = ADDR_CPU_2_DMA(&dmadesc[n + 1]);
|
||||
len -= dmachunklen;
|
||||
data += dmachunklen;
|
||||
n++;
|
||||
}
|
||||
dmadesc[n - 1].dw0.suc_eof = 1; //Mark last DMA desc as end of stream.
|
||||
dmadesc[n - 1].next = NULL;
|
||||
spi_ll_enable_mosi(hw, mosi_ena);
|
||||
spi_ll_enable_miso(hw, miso_ena);
|
||||
}
|
||||
|
||||
void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev, const spi_hal_trans_config_t *trans)
|
||||
void spi_hal_hw_prepare_rx(spi_dev_t *hw)
|
||||
{
|
||||
spi_dev_t *hw = hal->hw;
|
||||
spi_ll_dma_rx_fifo_reset(hw);
|
||||
spi_ll_infifo_full_clr(hw);
|
||||
spi_ll_dma_rx_enable(hw, 1);
|
||||
}
|
||||
|
||||
//Fill DMA descriptors
|
||||
if (trans->rcv_buffer) {
|
||||
if (!hal->dma_enabled) {
|
||||
//No need to setup anything; we'll copy the result out of the work registers directly later.
|
||||
} else {
|
||||
s_spi_hal_dma_desc_setup_link(hal->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
|
||||
|
||||
spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
|
||||
spi_ll_dma_rx_fifo_reset(hal->hw);
|
||||
spi_ll_infifo_full_clr(hal->hw);
|
||||
spi_ll_dma_rx_enable(hal->hw, 1);
|
||||
spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, (lldesc_t *)hal->dmadesc_rx);
|
||||
}
|
||||
|
||||
}
|
||||
#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) {
|
||||
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) {
|
||||
//Need to copy data to registers manually
|
||||
spi_ll_write_buffer(hw, trans->send_buffer, trans->tx_bitlen);
|
||||
} else {
|
||||
s_spi_hal_dma_desc_setup_link(hal->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
|
||||
|
||||
spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
|
||||
spi_ll_dma_tx_fifo_reset(hal->hw);
|
||||
spi_ll_outfifo_empty_clr(hal->hw);
|
||||
spi_ll_dma_tx_enable(hal->hw, 1);
|
||||
spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (lldesc_t *)hal->dmadesc_tx);
|
||||
}
|
||||
}
|
||||
|
||||
//in ESP32 these registers should be configured after the DMA is set
|
||||
if ((!dev->half_duplex && trans->rcv_buffer) || trans->send_buffer) {
|
||||
spi_ll_enable_mosi(hw, 1);
|
||||
} else {
|
||||
spi_ll_enable_mosi(hw, 0);
|
||||
}
|
||||
spi_ll_enable_miso(hw, (trans->rcv_buffer) ? 1 : 0);
|
||||
void spi_hal_hw_prepare_tx(spi_dev_t *hw)
|
||||
{
|
||||
spi_ll_dma_tx_fifo_reset(hw);
|
||||
spi_ll_outfifo_empty_clr(hw);
|
||||
spi_ll_dma_tx_enable(hw, 1);
|
||||
}
|
||||
|
||||
void spi_hal_user_start(const spi_hal_context_t *hal)
|
||||
@@ -246,11 +145,19 @@ bool spi_hal_usr_is_done(const spi_hal_context_t *hal)
|
||||
return spi_ll_usr_is_done(hal->hw);
|
||||
}
|
||||
|
||||
void spi_hal_push_tx_buffer(const spi_hal_context_t *hal, const spi_hal_trans_config_t *hal_trans)
|
||||
{
|
||||
if (hal_trans->send_buffer) {
|
||||
spi_ll_write_buffer(hal->hw, hal_trans->send_buffer, hal_trans->tx_bitlen);
|
||||
}
|
||||
//No need to setup anything for RX, we'll copy the result out of the work registers directly later.
|
||||
}
|
||||
|
||||
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) {
|
||||
//Need to copy from SPI regs to result buffer.
|
||||
spi_ll_read_buffer(hal->hw, trans->rcv_buffer, trans->rx_bitlen);
|
||||
}
|
||||
|
Reference in New Issue
Block a user