mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
refactor(driver_spi): spi driver using dma link list driver
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_ll.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "esp_private/spi_common_internal.h"
|
||||
#include "esp_private/adc_dma.h"
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_private/spi_dma.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_private/gdma_link.h"
|
||||
#include "esp_private/spi_share_hw_ctrl.h"
|
||||
#if SOC_PAU_SUPPORTED
|
||||
#include "soc/regdma.h"
|
||||
@@ -37,14 +38,6 @@ typedef dma_descriptor_align8_t spi_dma_desc_t;
|
||||
typedef dma_descriptor_align4_t spi_dma_desc_t;
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
// Status of a spi bus
|
||||
typedef enum {
|
||||
@@ -82,6 +75,8 @@ typedef struct {
|
||||
int dma_desc_num; ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
|
||||
spi_dma_desc_t *dmadesc_tx; ///< DMA descriptor array for TX
|
||||
spi_dma_desc_t *dmadesc_rx; ///< DMA descriptor array for RX
|
||||
gdma_link_list_handle_t tx_link_handle; ///< DMA tx link list for GDMA and SPIDMA
|
||||
gdma_link_list_handle_t rx_link_handle; ///< DMA rx link list for GDMA and SPIDMA
|
||||
} spi_dma_ctx_t;
|
||||
|
||||
#if SOC_PAU_SUPPORTED
|
||||
@@ -145,12 +140,13 @@ esp_err_t spicommon_dma_desc_alloc(spi_host_device_t host_id, int cfg_max_sz, in
|
||||
/**
|
||||
* Setupt/Configure dma descriptor link list
|
||||
*
|
||||
* @param dmadesc start of dma descriptor memory
|
||||
* @param dma_ctx DMA context pointer
|
||||
* @param offset offset of the item in the link list
|
||||
* @param data start of data buffer to be configured in
|
||||
* @param len length of data buffer, in byte
|
||||
* @param is_rx if descriptor is for rx/receive direction
|
||||
*/
|
||||
void spicommon_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx);
|
||||
void spicommon_dma_desc_setup_link(const spi_dma_ctx_t *dma_ctx, int offset, const void *data, int len, bool is_rx);
|
||||
|
||||
/**
|
||||
* @brief Setup private buffer for DMA transfer
|
||||
|
||||
@@ -5,3 +5,12 @@ entries:
|
||||
spi_hal_iram (noflash)
|
||||
if SPI_SLAVE_ISR_IN_IRAM = y:
|
||||
spi_slave_hal_iram (noflash)
|
||||
|
||||
[mapping:gpspi_driver_gdma_link]
|
||||
archive: libesp_driver_dma.a
|
||||
entries:
|
||||
if SPI_MASTER_ISR_IN_IRAM = y || SPI_SLAVE_ISR_IN_IRAM = y:
|
||||
gdma_link: gdma_link_mount_buffers (noflash)
|
||||
gdma_link: gdma_link_count_buffer_size_till_eof (noflash)
|
||||
gdma_link: gdma_link_get_buffer (noflash)
|
||||
gdma_link: gdma_link_get_length (noflash)
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
#include "esp_private/spi_common_internal.h"
|
||||
#include "esp_private/spi_share_hw_ctrl.h"
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
#include "esp_private/esp_dma_utils.h"
|
||||
#include "esp_private/gdma_link.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "hal/spi_hal.h"
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "hal/gdma_ll.h"
|
||||
@@ -312,7 +313,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
|
||||
#endif
|
||||
gdma_transfer_config_t trans_cfg = {
|
||||
.max_data_burst_size = burst_size,
|
||||
#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE
|
||||
#if SOC_PSRAM_DMA_CAPABLE || SOC_DMA_CAN_ACCESS_FLASH
|
||||
.access_ext_mem = true, // allow to transfer data from/to external memory directly by DMA
|
||||
#endif
|
||||
};
|
||||
@@ -355,69 +356,79 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t spicommon_dma_desc_alloc(spi_host_device_t host_id, int cfg_max_sz, int *actual_max_sz)
|
||||
static void spicommon_dma_link_free(spi_host_device_t host_id)
|
||||
{
|
||||
int dma_desc_ct = (cfg_max_sz + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
if (dma_desc_ct == 0) {
|
||||
dma_desc_ct = 1; //default to 4k when max is not given
|
||||
}
|
||||
|
||||
spi_dma_ctx_t *dma_ctx = spi_bus_get_dma_ctx(host_id);
|
||||
if (!dma_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
return;
|
||||
}
|
||||
dma_ctx->dmadesc_tx = heap_caps_aligned_calloc(DMA_DESC_MEM_ALIGN_SIZE, 1, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
dma_ctx->dmadesc_rx = heap_caps_aligned_calloc(DMA_DESC_MEM_ALIGN_SIZE, 1, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
if (dma_ctx->dmadesc_tx == NULL || dma_ctx->dmadesc_rx == NULL) {
|
||||
if (dma_ctx->dmadesc_tx) {
|
||||
free(dma_ctx->dmadesc_tx);
|
||||
dma_ctx->dmadesc_tx = NULL;
|
||||
}
|
||||
if (dma_ctx->dmadesc_rx) {
|
||||
free(dma_ctx->dmadesc_rx);
|
||||
dma_ctx->dmadesc_rx = NULL;
|
||||
}
|
||||
return ESP_ERR_NO_MEM;
|
||||
if (dma_ctx->tx_link_handle) {
|
||||
gdma_del_link_list(dma_ctx->tx_link_handle);
|
||||
dma_ctx->tx_link_handle = NULL;
|
||||
}
|
||||
if (dma_ctx->rx_link_handle) {
|
||||
gdma_del_link_list(dma_ctx->rx_link_handle);
|
||||
dma_ctx->rx_link_handle = NULL;
|
||||
}
|
||||
// cache sync using align_up length thanks to heap alloc already consider the cache alignment requirement
|
||||
size_t aligned_len = ESP_ALIGN_UP(sizeof(spi_dma_desc_t) * dma_desc_ct, bus_ctx[host_id]->bus_attr.cache_align_int);
|
||||
// write back and then invalidate the cache, because later we will read/write the link list items by non-cached address
|
||||
esp_err_t ret = esp_cache_msync(dma_ctx->dmadesc_tx, aligned_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
|
||||
ESP_RETURN_ON_FALSE_ISR((ret == ESP_OK) || (ret == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_ARG, SPI_TAG, "dma desc sync failed");
|
||||
ret = esp_cache_msync(dma_ctx->dmadesc_rx, aligned_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
|
||||
ESP_RETURN_ON_FALSE_ISR((ret == ESP_OK) || (ret == ESP_ERR_NOT_SUPPORTED), ESP_ERR_INVALID_ARG, SPI_TAG, "dma desc sync failed");
|
||||
|
||||
dma_ctx->dma_desc_num = dma_desc_ct;
|
||||
*actual_max_sz = dma_desc_ct * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void SPI_COMMON_ISR_ATTR spicommon_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
|
||||
esp_err_t spicommon_dma_desc_alloc(spi_host_device_t host_id, int cfg_max_sz, int *actual_max_sz)
|
||||
{
|
||||
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);
|
||||
} 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 = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
dmadesc[n].next = ADDR_CPU_2_DMA(&dmadesc[n + 1]);
|
||||
len -= dmachunklen;
|
||||
data += dmachunklen;
|
||||
n++;
|
||||
esp_err_t ret = ESP_OK;
|
||||
spi_dma_ctx_t *dma_ctx = spi_bus_get_dma_ctx(host_id);
|
||||
ESP_RETURN_ON_FALSE(dma_ctx, ESP_ERR_INVALID_STATE, SPI_TAG, "dma context not initialized");
|
||||
size_t tx_buffer_alignment = dma_ctx->dma_align_tx_int ? dma_ctx->dma_align_tx_int : 1;
|
||||
size_t rx_buffer_alignment = dma_ctx->dma_align_rx_int ? dma_ctx->dma_align_rx_int : 1;
|
||||
if (dma_ctx->dma_align_tx_ext < BIT(31)) {
|
||||
tx_buffer_alignment = MAX(tx_buffer_alignment, dma_ctx->dma_align_tx_ext);
|
||||
}
|
||||
dmadesc[n - 1].dw0.suc_eof = 1; //Mark last DMA desc as end of stream.
|
||||
dmadesc[n - 1].next = NULL;
|
||||
if (dma_ctx->dma_align_rx_ext < BIT(31)) {
|
||||
rx_buffer_alignment = MAX(rx_buffer_alignment, dma_ctx->dma_align_rx_ext);
|
||||
}
|
||||
|
||||
size_t tx_item_num = esp_dma_calculate_node_count(cfg_max_sz, tx_buffer_alignment, DMA_DESCRIPTOR_BUFFER_MAX_SIZE);
|
||||
size_t rx_item_num = esp_dma_calculate_node_count(cfg_max_sz, rx_buffer_alignment, DMA_DESCRIPTOR_BUFFER_MAX_SIZE);
|
||||
gdma_link_list_config_t link_cfg = {
|
||||
.num_items = MAX(MAX(tx_item_num, rx_item_num), 1), //default to 1 when 'cfg_max_sz' is not given
|
||||
.item_alignment = DMA_DESC_MEM_ALIGN_SIZE,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(gdma_new_link_list(&link_cfg, &dma_ctx->tx_link_handle), SPI_TAG, "failed to allocate tx dma link");
|
||||
ESP_GOTO_ON_ERROR(gdma_new_link_list(&link_cfg, &dma_ctx->rx_link_handle), cleanup, SPI_TAG, "failed to allocate rx dma link");
|
||||
|
||||
// save link info
|
||||
dma_ctx->dma_desc_num = link_cfg.num_items;
|
||||
dma_ctx->dmadesc_tx = (spi_dma_desc_t *)gdma_link_get_head_addr(dma_ctx->tx_link_handle);
|
||||
dma_ctx->dmadesc_rx = (spi_dma_desc_t *)gdma_link_get_head_addr(dma_ctx->rx_link_handle);
|
||||
*actual_max_sz = dma_ctx->dma_desc_num * ESP_ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, rx_buffer_alignment);
|
||||
return ESP_OK;
|
||||
|
||||
cleanup:
|
||||
spicommon_dma_link_free(host_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SPI_COMMON_ISR_ATTR spicommon_dma_desc_setup_link(const spi_dma_ctx_t *dma_ctx, int offset, const void *data, int len, bool is_rx)
|
||||
{
|
||||
size_t buffer_alignment;
|
||||
if (esp_ptr_internal(data)) {
|
||||
buffer_alignment = is_rx ? dma_ctx->dma_align_rx_int : dma_ctx->dma_align_tx_int;
|
||||
} else {
|
||||
buffer_alignment = is_rx ? dma_ctx->dma_align_rx_ext : dma_ctx->dma_align_tx_ext;
|
||||
}
|
||||
|
||||
gdma_buffer_mount_config_t mount_config = {
|
||||
.buffer = (void *)data,
|
||||
.buffer_alignment = buffer_alignment,
|
||||
.length = is_rx ? ESP_ALIGN_UP(len, 4) : len, // dma rx hardware requires 4 bytes alignment
|
||||
.flags = {
|
||||
.mark_eof = true,
|
||||
.mark_final = GDMA_FINAL_LINK_TO_NULL,
|
||||
.bypass_buffer_align_check = true, // 'setup_priv_buffer' already do the check
|
||||
}
|
||||
};
|
||||
esp_err_t ret = gdma_link_mount_buffers(is_rx ? dma_ctx->rx_link_handle : dma_ctx->tx_link_handle, offset, &mount_config, 1, NULL);
|
||||
assert(ret == ESP_OK);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
esp_err_t SPI_COMMON_ISR_ATTR spicommon_dma_setup_priv_buffer(spi_host_device_t host_id, uint32_t *buffer, uint32_t len, bool is_tx, bool psram_prefer, bool auto_malloc, uint32_t **ret_buffer)
|
||||
@@ -508,13 +519,7 @@ esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
|
||||
gdma_del_channel(dma_ctx->tx_dma_chan);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dma_ctx->dmadesc_tx) {
|
||||
free(dma_ctx->dmadesc_tx);
|
||||
}
|
||||
if (dma_ctx->dmadesc_rx) {
|
||||
free(dma_ctx->dmadesc_rx);
|
||||
}
|
||||
spicommon_dma_link_free(host_id);
|
||||
free(dma_ctx);
|
||||
spi_dma_ctx[host_id] = NULL;
|
||||
return ESP_OK;
|
||||
|
||||
@@ -79,8 +79,8 @@ void SPI_DMA_ISR_ATTR spi_dma_start(spi_dma_chan_handle_t chan_handle, void *add
|
||||
spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id);
|
||||
|
||||
if (chan_handle.dir == DMA_CHANNEL_DIRECTION_TX) {
|
||||
spi_ll_dma_tx_start(spi_dma, chan_handle.chan_id, (lldesc_t *)addr);
|
||||
spi_ll_dma_tx_start(spi_dma, chan_handle.chan_id, addr);
|
||||
} else {
|
||||
spi_ll_dma_rx_start(spi_dma, chan_handle.chan_id, (lldesc_t *)addr);
|
||||
spi_ll_dma_rx_start(spi_dma, chan_handle.chan_id, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +737,7 @@ static void SPI_MASTER_ISR_ATTR s_spi_dma_prepare_data(spi_host_t *host, spi_hal
|
||||
const spi_dma_ctx_t *dma_ctx = host->dma_ctx;
|
||||
|
||||
if (trans->rcv_buffer) {
|
||||
spicommon_dma_desc_setup_link(dma_ctx->dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
|
||||
spicommon_dma_desc_setup_link(dma_ctx, 0, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
|
||||
|
||||
spi_dma_reset(dma_ctx->rx_dma_chan);
|
||||
spi_hal_hw_prepare_rx(hal->hw);
|
||||
@@ -751,7 +751,7 @@ static void SPI_MASTER_ISR_ATTR s_spi_dma_prepare_data(spi_host_t *host, spi_hal
|
||||
}
|
||||
#endif
|
||||
if (trans->send_buffer) {
|
||||
spicommon_dma_desc_setup_link(dma_ctx->dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
|
||||
spicommon_dma_desc_setup_link(dma_ctx, 0, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
|
||||
|
||||
spi_dma_reset(dma_ctx->tx_dma_chan);
|
||||
spi_hal_hw_prepare_tx(hal->hw);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "esp_cache.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
@@ -602,14 +601,14 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_transmit(spi_host_device_t host, spi_slave_tr
|
||||
static void SPI_SLAVE_ISR_ATTR s_spi_slave_dma_prepare_data(spi_dma_ctx_t *dma_ctx, spi_slave_hal_context_t *hal)
|
||||
{
|
||||
if (hal->rx_buffer) {
|
||||
spicommon_dma_desc_setup_link(dma_ctx->dmadesc_rx, hal->rx_buffer, (hal->rx_bitlen + 7) / 8, true);
|
||||
spicommon_dma_desc_setup_link(dma_ctx, 0, hal->rx_buffer, (hal->rx_bitlen + 7) / 8, true);
|
||||
|
||||
spi_dma_reset(dma_ctx->rx_dma_chan);
|
||||
spi_slave_hal_hw_prepare_rx(hal->hw);
|
||||
spi_dma_start(dma_ctx->rx_dma_chan, dma_ctx->dmadesc_rx);
|
||||
}
|
||||
if (hal->tx_buffer) {
|
||||
spicommon_dma_desc_setup_link(dma_ctx->dmadesc_tx, hal->tx_buffer, (hal->tx_bitlen + 7) / 8, false);
|
||||
spicommon_dma_desc_setup_link(dma_ctx, 0, hal->tx_buffer, (hal->tx_bitlen + 7) / 8, false);
|
||||
|
||||
spi_dma_reset(dma_ctx->tx_dma_chan);
|
||||
spi_slave_hal_hw_prepare_tx(hal->hw);
|
||||
|
||||
@@ -488,7 +488,7 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
|
||||
spicommon_dma_rx_mb(host->host_id, host->rx_curr_trans.aligned_buffer);
|
||||
spi_slave_hd_rx_dma_error_check(host, host->rx_curr_trans);
|
||||
bool ret_queue = true;
|
||||
host->rx_curr_trans.trans->trans_len = spi_slave_hd_hal_rxdma_seg_get_len(hal);
|
||||
host->rx_curr_trans.trans->trans_len = gdma_link_count_buffer_size_till_eof(host->dma_ctx->rx_link_handle, 0);
|
||||
if (callback->cb_recv) {
|
||||
spi_slave_hd_event_t ev = {
|
||||
.event = SPI_EV_RECV,
|
||||
@@ -511,7 +511,7 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
|
||||
if (!host->tx_curr_trans.trans) {
|
||||
ret = xQueueReceiveFromISR(host->tx_trans_queue, &host->tx_curr_trans, &awoken);
|
||||
if ((ret == pdTRUE) && host->tx_curr_trans.trans) {
|
||||
spicommon_dma_desc_setup_link(hal->dmadesc_tx->desc, host->tx_curr_trans.aligned_buffer, host->tx_curr_trans.trans->len, false);
|
||||
spicommon_dma_desc_setup_link(host->dma_ctx, 0, host->tx_curr_trans.aligned_buffer, host->tx_curr_trans.trans->len, false);
|
||||
spi_dma_reset(host->dma_ctx->tx_dma_chan);
|
||||
spi_slave_hd_hal_txdma(hal);
|
||||
spi_dma_start(host->dma_ctx->tx_dma_chan, host->dma_ctx->dmadesc_tx);
|
||||
@@ -530,7 +530,7 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
|
||||
if (!host->rx_curr_trans.trans) {
|
||||
ret = xQueueReceiveFromISR(host->rx_trans_queue, &host->rx_curr_trans, &awoken);
|
||||
if ((ret == pdTRUE) && host->rx_curr_trans.trans) {
|
||||
spicommon_dma_desc_setup_link(hal->dmadesc_rx->desc, host->rx_curr_trans.aligned_buffer, host->rx_curr_trans.trans->len, true);
|
||||
spicommon_dma_desc_setup_link(host->dma_ctx, 0, host->rx_curr_trans.aligned_buffer, host->rx_curr_trans.trans->len, true);
|
||||
spi_dma_reset(host->dma_ctx->rx_dma_chan);
|
||||
spi_slave_hd_hal_rxdma(hal);
|
||||
spi_dma_start(host->dma_ctx->rx_dma_chan, host->dma_ctx->dmadesc_rx);
|
||||
@@ -561,6 +561,15 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
static inline SPI_SLAVE_ISR_ATTR void slave_hd_append_desc_walk(spi_slave_hd_hal_desc_append_t *desc_head, uint32_t desc_num, spi_slave_hd_hal_desc_append_t **p_desc, uint32_t steps)
|
||||
{
|
||||
steps %= desc_num;
|
||||
*p_desc += steps;
|
||||
if (*p_desc >= (desc_head + desc_num)) {
|
||||
*p_desc -= desc_num;
|
||||
}
|
||||
}
|
||||
|
||||
static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_tx_isr(void *arg)
|
||||
{
|
||||
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t*)arg;
|
||||
@@ -569,13 +578,14 @@ static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_tx_isr(void *arg)
|
||||
BaseType_t awoken = pdFALSE;
|
||||
BaseType_t ret __attribute__((unused));
|
||||
|
||||
spi_slave_hd_trans_priv_t ret_priv_trans = {};
|
||||
while (1) {
|
||||
bool trans_finish = false;
|
||||
trans_finish = spi_slave_hd_hal_get_tx_finished_trans(hal, (void **)&ret_priv_trans.trans, &ret_priv_trans.aligned_buffer);
|
||||
if (!trans_finish) {
|
||||
break;
|
||||
}
|
||||
while ((uint32_t)hal->tx_dma_head->desc != hal->current_eof_addr) {
|
||||
slave_hd_append_desc_walk(hal->dmadesc_tx, hal->dma_desc_num, &hal->tx_dma_head, 1);
|
||||
int offset = hal->tx_dma_head - hal->dmadesc_tx;
|
||||
spi_slave_hd_trans_priv_t ret_priv_trans = {
|
||||
.trans = hal->tx_dma_head->arg,
|
||||
.aligned_buffer = gdma_link_get_buffer(host->dma_ctx->tx_link_handle, offset),
|
||||
};
|
||||
|
||||
portENTER_CRITICAL_ISR(&host->int_spinlock);
|
||||
hal->tx_used_desc_cnt--;
|
||||
portEXIT_CRITICAL_ISR(&host->int_spinlock);
|
||||
@@ -613,18 +623,18 @@ static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_rx_isr(void *arg)
|
||||
BaseType_t awoken = pdFALSE;
|
||||
BaseType_t ret __attribute__((unused));
|
||||
|
||||
spi_slave_hd_trans_priv_t ret_priv_trans = {};
|
||||
size_t trans_len;
|
||||
while (1) {
|
||||
bool trans_finish = false;
|
||||
trans_finish = spi_slave_hd_hal_get_rx_finished_trans(hal, (void **)&ret_priv_trans.trans, &ret_priv_trans.aligned_buffer, &trans_len);
|
||||
if (!trans_finish) {
|
||||
break;
|
||||
}
|
||||
while ((uint32_t)hal->rx_dma_head->desc != hal->current_eof_addr) {
|
||||
slave_hd_append_desc_walk(hal->dmadesc_rx, hal->dma_desc_num, &hal->rx_dma_head, 1);
|
||||
int offset = hal->rx_dma_head - hal->dmadesc_rx;
|
||||
spi_slave_hd_trans_priv_t ret_priv_trans = {
|
||||
.trans = hal->rx_dma_head->arg,
|
||||
.aligned_buffer = gdma_link_get_buffer(host->dma_ctx->rx_link_handle, offset),
|
||||
};
|
||||
ret_priv_trans.trans->trans_len = gdma_link_get_length(host->dma_ctx->rx_link_handle, offset);
|
||||
|
||||
portENTER_CRITICAL_ISR(&host->int_spinlock);
|
||||
hal->rx_used_desc_cnt--;
|
||||
portEXIT_CRITICAL_ISR(&host->int_spinlock);
|
||||
ret_priv_trans.trans->trans_len = trans_len;
|
||||
|
||||
bool ret_queue = true;
|
||||
spicommon_dma_rx_mb(host->host_id, ret_priv_trans.aligned_buffer);
|
||||
@@ -745,13 +755,16 @@ esp_err_t s_spi_slave_hd_append_txdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
spi_slave_hd_hal_context_t *hal = &host->hal;
|
||||
|
||||
//Check if there are enough available DMA descriptors for software to use
|
||||
int num_required = (len + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
int buf_align = esp_ptr_internal(data) ? host->dma_ctx->dma_align_tx_int : host->dma_ctx->dma_align_tx_ext;
|
||||
// unsupported buffer which lead invalid buf_align should already checked by 'setup_priv_trans'
|
||||
int num_required = howmany(len, ESP_ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, buf_align));
|
||||
int available_desc_num = hal->dma_desc_num - hal->tx_used_desc_cnt;
|
||||
if (num_required > available_desc_num) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
spicommon_dma_desc_setup_link(hal->tx_cur_desc->desc, data, len, false);
|
||||
int offset = hal->tx_cur_desc - hal->dmadesc_tx;
|
||||
spicommon_dma_desc_setup_link(host->dma_ctx, offset, data, len, false);
|
||||
hal->tx_cur_desc->arg = arg;
|
||||
|
||||
if (!hal->tx_used_desc_cnt) {
|
||||
@@ -762,7 +775,8 @@ esp_err_t s_spi_slave_hd_append_txdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
spi_dma_start(host->dma_ctx->tx_dma_chan, hal->tx_cur_desc->desc);
|
||||
} else {
|
||||
//there is already a consecutive link
|
||||
ADDR_DMA_2_CPU(hal->tx_dma_tail->desc)->next = hal->tx_cur_desc->desc;
|
||||
gdma_link_list_handle_t link_handle = host->dma_ctx->tx_link_handle;
|
||||
gdma_link_concat(link_handle, offset - 1, link_handle, offset);
|
||||
hal->tx_dma_tail = hal->tx_cur_desc;
|
||||
spi_dma_append(host->dma_ctx->tx_dma_chan);
|
||||
}
|
||||
@@ -771,12 +785,7 @@ esp_err_t s_spi_slave_hd_append_txdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
portENTER_CRITICAL(&host->int_spinlock);
|
||||
hal->tx_used_desc_cnt += num_required;
|
||||
portEXIT_CRITICAL(&host->int_spinlock);
|
||||
for (int i = 0; i < num_required; i++) {
|
||||
hal->tx_cur_desc++;
|
||||
if (hal->tx_cur_desc == hal->dmadesc_tx + hal->dma_desc_num) {
|
||||
hal->tx_cur_desc = hal->dmadesc_tx;
|
||||
}
|
||||
}
|
||||
slave_hd_append_desc_walk(hal->dmadesc_tx, hal->dma_desc_num, &hal->tx_cur_desc, num_required);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -786,13 +795,15 @@ esp_err_t s_spi_slave_hd_append_rxdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
spi_slave_hd_hal_context_t *hal = &host->hal;
|
||||
|
||||
//Check if there are enough available dma descriptors for software to use
|
||||
int num_required = (len + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
int buf_align = esp_ptr_internal(data) ? host->dma_ctx->dma_align_rx_int : host->dma_ctx->dma_align_rx_ext;
|
||||
int num_required = howmany(len, ESP_ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, buf_align));
|
||||
int available_desc_num = hal->dma_desc_num - hal->rx_used_desc_cnt;
|
||||
if (num_required > available_desc_num) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
spicommon_dma_desc_setup_link(hal->rx_cur_desc->desc, data, len, true);
|
||||
int offset = hal->rx_cur_desc - hal->dmadesc_rx;
|
||||
spicommon_dma_desc_setup_link(host->dma_ctx, offset, data, len, true);
|
||||
hal->rx_cur_desc->arg = arg;
|
||||
|
||||
if (!hal->rx_used_desc_cnt) {
|
||||
@@ -803,7 +814,8 @@ esp_err_t s_spi_slave_hd_append_rxdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
spi_dma_start(host->dma_ctx->rx_dma_chan, hal->rx_cur_desc->desc);
|
||||
} else {
|
||||
//there is already a consecutive link
|
||||
ADDR_DMA_2_CPU(hal->rx_dma_tail->desc)->next = hal->rx_cur_desc->desc;
|
||||
gdma_link_list_handle_t link_handle = host->dma_ctx->rx_link_handle;
|
||||
gdma_link_concat(link_handle, offset - 1, link_handle, offset);
|
||||
hal->rx_dma_tail = hal->rx_cur_desc;
|
||||
spi_dma_append(host->dma_ctx->rx_dma_chan);
|
||||
}
|
||||
@@ -812,12 +824,7 @@ esp_err_t s_spi_slave_hd_append_rxdma(spi_slave_hd_slot_t *host, uint8_t *data,
|
||||
portENTER_CRITICAL(&host->int_spinlock);
|
||||
hal->rx_used_desc_cnt += num_required;
|
||||
portEXIT_CRITICAL(&host->int_spinlock);
|
||||
for (int i = 0; i < num_required; i++) {
|
||||
hal->rx_cur_desc++;
|
||||
if (hal->rx_cur_desc == hal->dmadesc_rx + hal->dma_desc_num) {
|
||||
hal->rx_cur_desc = hal->dmadesc_rx;
|
||||
}
|
||||
}
|
||||
slave_hd_append_desc_walk(hal->dmadesc_rx, hal->dma_desc_num, &hal->rx_cur_desc, num_required);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 16*1000*1000
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 15
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 20
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 15
|
||||
#if !CONFIG_FREERTOS_SMP // IDF-5826
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 34 // TODO: IDF-5180
|
||||
@@ -29,27 +29,27 @@
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 40*1000*1000
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 17
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 20
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 15
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 32
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 34
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 30
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 40*1000*1000
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 23
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 28
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 18
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 47
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 52
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 42
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 40*1000*1000
|
||||
#if !CONFIG_FREERTOS_SMP // IDF-5826
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 17
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 21
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 15
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 35
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 37
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 30
|
||||
#else
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 17
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 21
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 17
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 60
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 60
|
||||
@@ -57,16 +57,16 @@
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 26666*1000
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 37 //TODO: IDF-9551, check perform
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 19
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 38 //TODO: IDF-9551, check perform
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 22
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 32
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 15
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define IDF_TARGET_MAX_SPI_CLK_FREQ 24*1000*1000
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 32
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_DMA 35
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_POLL_CPU 25
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 61
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_DMA 64
|
||||
#define IDF_TARGET_MAX_TRANS_TIME_INTR_CPU 54
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user