refactor(driver_spi): spi driver using dma link list driver

This commit is contained in:
wanckl
2026-08-07 17:56:10 +08:00
parent 94cce227dc
commit 96e4fc85a0
13 changed files with 151 additions and 277 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,7 +15,6 @@
#include <string.h>
#include <stdlib.h> //for abs()
#include "esp_types.h"
#include "esp32/rom/lldesc.h"
#include "soc/spi_reg.h"
#include "soc/spi_struct.h"
#include "soc/dport_reg.h"
@@ -1159,7 +1158,7 @@ static inline void spi_ll_dma_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel)
* @param addr Address of the beginning DMA descriptor.
*/
__attribute__((always_inline))
static inline void spi_ll_dma_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, lldesc_t *addr)
static inline void spi_ll_dma_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, void *addr)
{
dma_in->dma_in_link.addr = (int) addr & 0xFFFFF;
dma_in->dma_in_link.start = 1;
@@ -1224,7 +1223,7 @@ static inline void spi_ll_dma_tx_reset(spi_dma_dev_t *dma_out, uint32_t channel)
* @param addr Address of the beginning DMA descriptor.
*/
__attribute__((always_inline))
static inline void spi_ll_dma_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, lldesc_t *addr)
static inline void spi_ll_dma_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, void *addr)
{
dma_out->dma_out_link.addr = (int) addr & 0xFFFFF;
dma_out->dma_out_link.start = 1;
@@ -21,7 +21,6 @@
#include "soc/spi_struct.h"
#include "soc/spi_reg.h"
#include "soc/dport_reg.h"
#include "soc/lldesc.h"
#include "soc/soc_caps.h"
#include "hal/assert.h"
#include "hal/misc.h"
@@ -1331,7 +1330,7 @@ static inline void spi_ll_dma_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel)
* @param addr Address of the beginning DMA descriptor.
*/
__attribute__((always_inline))
static inline void spi_ll_dma_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, lldesc_t *addr)
static inline void spi_ll_dma_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, void *addr)
{
dma_in->dma_in_link.addr = (int) addr & 0xFFFFF;
dma_in->dma_in_link.start = 1;
@@ -1423,7 +1422,7 @@ static inline void spi_ll_dma_tx_reset(spi_dma_dev_t *dma_out, uint32_t channel)
* @param addr Address of the beginning DMA descriptor.
*/
__attribute__((always_inline))
static inline void spi_ll_dma_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, lldesc_t *addr)
static inline void spi_ll_dma_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, void *addr)
{
dma_out->dma_out_link.addr = (int) addr & 0xFFFFF;
dma_out->dma_out_link.start = 1;
@@ -105,8 +105,6 @@ typedef struct {
/* address of the hardware */
spi_dev_t *dev; ///< Beginning address of the peripheral registers.
bool dma_enabled; ///< DMA enabled or not
bool append_mode; ///< True for DMA append mode, false for segment mode
uint32_t dma_desc_num; ///< Number of the available DMA descriptors. Calculated from ``bus_max_transfer_size``.
uint32_t current_eof_addr;
spi_slave_hd_hal_desc_append_t *tx_cur_desc; ///< Current TX DMA descriptor that could be linked (set up).
@@ -193,14 +191,6 @@ void spi_slave_hd_hal_enable_event_intr(spi_slave_hd_hal_context_t* hal, spi_eve
*/
void spi_slave_hd_hal_rxdma(spi_slave_hd_hal_context_t *hal);
/**
* @brief Get the length of total received data
*
* @param hal Context of the HAL layer
* @return The received length
*/
int spi_slave_hd_hal_rxdma_seg_get_len(spi_slave_hd_hal_context_t *hal);
/**
* @brief Prepare hardware for a new dma rx trans
*
@@ -266,64 +256,6 @@ int spi_slave_hd_hal_get_rxlen(spi_slave_hd_hal_context_t *hal);
*/
int spi_slave_hd_hal_get_last_addr(spi_slave_hd_hal_context_t *hal);
////////////////////////////////////////////////////////////////////////////////
// Append Mode
////////////////////////////////////////////////////////////////////////////////
/**
* @brief Return the finished TX transaction
*
* @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
* This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
* this API will go wrong.
*
* @param hal Context of the HAL layer
* @param out_trans Pointer to the caller-defined transaction
* @param real_buff_addr Actually data buffer head the HW used
* @return 1: Transaction is finished; 0: Transaction is not finished
*/
bool spi_slave_hd_hal_get_tx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, void **real_buff_addr);
/**
* @brief Return the finished RX transaction
*
* @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
* This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
* this API will go wrong.
*
* @param hal Context of the HAL layer
* @param out_trans Pointer to the caller-defined transaction
* @param real_buff_addr Actually data buffer head the HW used
* @param out_len Actual number of bytes of received data
* @return 1: Transaction is finished; 0: Transaction is not finished
*/
bool spi_slave_hd_hal_get_rx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, void **real_buff_addr, size_t *out_len);
/**
* @brief Load the TX DMA descriptors without stopping the DMA
*
* @param hal Context of the HAL layer
* @param data Buffer of the transaction data
* @param len Length of the data
* @param arg Pointer used by the caller to indicate the transaction. Will be returned by ``spi_slave_hd_hal_get_tx_finished_trans`` when transaction is finished
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_STATE: Function called in invalid state.
*/
esp_err_t spi_slave_hd_hal_txdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
/**
* @brief Load the RX DMA descriptors without stopping the DMA
*
* @param hal Context of the HAL layer
* @param data Buffer of the transaction data
* @param len Length of the data
* @param arg Pointer used by the caller to indicate the transaction. Will be returned by ``spi_slave_hd_hal_get_rx_finished_trans`` when transaction is finished
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_STATE: Function called in invalid state.
*/
esp_err_t spi_slave_hd_hal_rxdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
#endif //#if SOC_GPSPI_SUPPORTED
#ifdef __cplusplus
@@ -10,9 +10,7 @@
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "soc/lldesc.h"
#include "soc/soc_caps.h"
#include "soc/soc.h" //for SOC_NON_CACHEABLE_OFFSET_SRAM
#include "soc/spi_periph.h"
#include "hal/spi_slave_hd_hal.h"
#include "hal/assert.h"
@@ -21,8 +19,6 @@ void spi_slave_hd_hal_init(spi_slave_hd_hal_context_t *hal, const spi_slave_hd_h
{
spi_dev_t *hw = spi_periph_signal[hal_config->host_id].hw;
hal->dev = hw;
hal->dma_enabled = hal_config->dma_enabled;
hal->append_mode = hal_config->append_mode;
hal->tx_cur_desc = hal->dmadesc_tx;
hal->rx_cur_desc = hal->dmadesc_rx;
hal->tx_dma_head = hal->dmadesc_tx + hal->dma_desc_num - 1;
@@ -70,37 +66,6 @@ void spi_slave_hd_hal_init(spi_slave_hd_hal_context_t *hal, const spi_slave_hd_h
spi_ll_slave_set_seg_mode(hal->dev, true);
}
#if SOC_NON_CACHEABLE_OFFSET_SRAM
#include "hal/cache_ll.h"
#define ADDR_DMA_2_CPU(addr) ((typeof(addr))CACHE_LL_L2MEM_NON_CACHE_ADDR(addr))
#define ADDR_CPU_2_DMA(addr) ((typeof(addr))CACHE_LL_L2MEM_CACHE_ADDR(addr))
#else
#define ADDR_DMA_2_CPU(addr) (addr)
#define ADDR_CPU_2_DMA(addr) (addr)
#endif
static int s_desc_get_received_len_addr(spi_dma_desc_t* head, spi_dma_desc_t** out_next, void **out_buff_head)
{
spi_dma_desc_t* desc_cpu = ADDR_DMA_2_CPU(head);
int len = 0;
if (out_buff_head) {
*out_buff_head = desc_cpu->buffer;
}
while (head) {
len += desc_cpu->dw0.length;
bool eof = desc_cpu->dw0.suc_eof;
desc_cpu = ADDR_DMA_2_CPU(desc_cpu->next);
head = head->next;
if (eof) {
break;
}
}
if (out_next) {
*out_next = head;
}
return len;
}
void spi_slave_hd_hal_hw_prepare_rx(spi_slave_hd_hal_context_t *hal)
{
spi_ll_dma_rx_fifo_reset(hal->dev);
@@ -234,41 +199,3 @@ int spi_slave_hd_hal_get_rxlen(spi_slave_hd_hal_context_t *hal)
//this is by -byte
return spi_ll_slave_get_rx_byte_len(hal->dev);
}
int spi_slave_hd_hal_rxdma_seg_get_len(spi_slave_hd_hal_context_t *hal)
{
spi_dma_desc_t *desc = hal->dmadesc_rx->desc;
return s_desc_get_received_len_addr(desc, NULL, NULL);
}
bool spi_slave_hd_hal_get_tx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, void **real_buff_addr)
{
if ((uint32_t)hal->tx_dma_head->desc == hal->current_eof_addr) {
return false;
}
//find used paired desc-trans by desc addr
hal->tx_dma_head++;
if (hal->tx_dma_head >= hal->dmadesc_tx + hal->dma_desc_num) {
hal->tx_dma_head = hal->dmadesc_tx;
}
*out_trans = hal->tx_dma_head->arg;
s_desc_get_received_len_addr(hal->tx_dma_head->desc, NULL, real_buff_addr);
return true;
}
bool spi_slave_hd_hal_get_rx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, void **real_buff_addr, size_t *out_len)
{
if ((uint32_t)hal->rx_dma_head->desc == hal->current_eof_addr) {
return false;
}
//find used paired desc-trans by desc addr
hal->rx_dma_head++;
if (hal->rx_dma_head >= hal->dmadesc_rx + hal->dma_desc_num) {
hal->rx_dma_head = hal->dmadesc_rx;
}
*out_trans = hal->rx_dma_head->arg;
*out_len = s_desc_get_received_len_addr(hal->rx_dma_head->desc, NULL, real_buff_addr);
return true;
}