Skip to content

Commit

Permalink
Merge branch 'feature/esp32p4_hp_spi_slave_hd_support' into 'master'
Browse files Browse the repository at this point in the history
Feature/esp32p4 hp spi slave hd support

Closes IDF-7505

See merge request espressif/esp-idf!25974
  • Loading branch information
wanckl committed Nov 9, 2023
2 parents 3d01150 + 2e115ec commit c8c7f99
Show file tree
Hide file tree
Showing 26 changed files with 399 additions and 302 deletions.
4 changes: 3 additions & 1 deletion components/driver/spi/gpspi/spi_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
spihost[host]->max_transfer_sz = dma_desc_ct * SPI_MAX_DMA_LEN;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_get_alignment(ESP_CACHE_MALLOC_FLAG_DMA, (size_t *)&spihost[host]->internal_mem_align_size);
size_t alignment;
esp_cache_get_alignment(ESP_CACHE_MALLOC_FLAG_DMA, &alignment);
spihost[host]->internal_mem_align_size = alignment;
#else
spihost[host]->internal_mem_align_size = 4;
#endif
Expand Down
233 changes: 160 additions & 73 deletions components/driver/spi/gpspi/spi_slave_hd.c

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions components/driver/spi/include/driver/spi_slave_hd.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ extern "C"
#error The SPI peripheral does not support this feature
#endif

#define SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO (1<<0) ///< Automatically re-malloc dma buffer if user buffer doesn't meet hardware alignment or dma_capable, this process may lose some memory and performance

/// Descriptor of data to send/receive
typedef struct {
uint8_t* data; ///< Buffer to send, must be DMA capable
size_t len; ///< Len of data to send/receive. For receiving the buffer length should be multiples of 4 bytes, otherwise the extra part will be truncated.
size_t trans_len; ///< For RX direction, it indicates the data actually received. For TX direction, it is meaningless.
uint32_t flags; ///< Bitwise OR of SPI_SLAVE_HD_TRANS_* flags
void* arg; ///< Extra argument indiciating this data
} spi_slave_hd_data_t;

Expand Down
3 changes: 0 additions & 3 deletions components/driver/test_apps/.build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,6 @@ components/driver/test_apps/spi/master:
components/driver/test_apps/spi/param:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) is not supported yet # TODO: IDF-7505

components/driver/test_apps/spi/slave:
disable:
Expand Down
4 changes: 2 additions & 2 deletions components/driver/test_apps/spi/param/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
4 changes: 4 additions & 0 deletions components/driver/test_apps/spi/param/main/test_spi_param.c
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,7 @@ static void test_slave_fd_dma(void)
.tx_buffer = slave_send,
.rx_buffer = slave_recive,
.length = test_trans_len * 8,
.flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &trans_cfg, portMAX_DELAY));
Expand Down Expand Up @@ -1589,6 +1590,7 @@ static void test_slave_hd_dma(void)
spi_slave_hd_data_t *ret_trans, slave_trans = {
.data = slave_send,
.len = test_trans_len,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_trans, portMAX_DELAY));
Expand Down Expand Up @@ -1690,6 +1692,7 @@ static void test_slave_hd_no_dma(void)
spi_slave_hd_data_t *ret_trans, slave_trans = {
.data = slave_send,
.len = test_trans_len,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &slave_trans, portMAX_DELAY));
Expand Down Expand Up @@ -1826,6 +1829,7 @@ static void test_slave_sio_dma(void)
.length = TEST_STEP_LEN * 8,
.tx_buffer = slave_send,
.rx_buffer = slave_recive,
.flags = SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &trans, portMAX_DELAY));
Expand Down
4 changes: 2 additions & 2 deletions components/driver/test_apps/spi/slave_hd/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
14 changes: 3 additions & 11 deletions components/driver/test_apps/spi/slave_hd/main/test_app_main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -10,23 +10,15 @@

#define TEST_MEMORY_LEAK_THRESHOLD (200)

static size_t before_free_8bit;
static size_t before_free_32bit;

void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
unity_utils_record_free_mem();
}

void tearDown(void)
{
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
}

void app_main(void)
Expand Down
58 changes: 39 additions & 19 deletions components/driver/test_apps/spi/slave_hd/main/test_spi_slave_hd.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -224,13 +224,15 @@ static void test_hd_start(spi_device_handle_t *spi, int freq, const spitest_para
ctx->tx_data = (spi_slave_hd_data_t) {
.data = &ctx->slave_rddma_buf[pos],
.len = len,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ctx->tx_data, portMAX_DELAY);
TEST_ESP_OK(err);

ctx->rx_data = (spi_slave_hd_data_t) {
.data = ctx->slave_wrdma_buf,
.len = TEST_DMA_MAX_SIZE,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ctx->rx_data, portMAX_DELAY);
TEST_ESP_OK(err);
Expand Down Expand Up @@ -269,6 +271,7 @@ void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_devic
ctx->rx_data = (spi_slave_hd_data_t) {
.data = ctx->slave_wrdma_buf,
.len = TEST_DMA_MAX_SIZE,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ctx->rx_data, portMAX_DELAY);
TEST_ESP_OK(err);
Expand Down Expand Up @@ -302,6 +305,7 @@ void test_rddma(testhd_context_t* ctx, const spitest_param_set_t* cfg, spi_devic
ctx->tx_data = (spi_slave_hd_data_t) {
.data = &ctx->slave_rddma_buf[pos],
.len = len,
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
};
esp_err_t err = spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ctx->tx_data, portMAX_DELAY);
TEST_ESP_OK(err);
Expand Down Expand Up @@ -415,6 +419,14 @@ static void test_hd_loop(const void* arg1, void* arg2)
TEST_ASSERT_EQUAL_HEX8_ARRAY(&slave_mem, recv_buffer, REG_REGION_SIZE);
}

//To release the re-malloced buffer remain in slave trans queue if possible
printf("clean tx %d rx %d\n", context->tx_data.len, context->rx_data.len);
TEST_ESP_OK(essl_spi_rddma(spi, context->master_rddma_buf, context->tx_data.len, TEST_SEG_SIZE, 0));
TEST_ESP_OK(essl_spi_wrdma(spi, context->master_wrdma_buf, context->rx_data.len, TEST_SEG_SIZE, 0));
spi_slave_hd_data_t* ret_trans;
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));

master_free_device_bus(spi);
spi_slave_hd_deinit(TEST_SLAVE_HOST);
}
Expand All @@ -434,8 +446,8 @@ static const ptest_func_t hd_test_func = {
static int test_freq_hd[] = {
// 100*1000,
// 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge
// 20 * 1000 * 1000, //maximum freq MISO stable before next latch edge
40 * 1000 * 1000, //maximum freq MISO stable before next latch edge
20 * 1000 * 1000, //maximum freq MISO stable before next latch edge
// 40 * 1000 * 1000, //maximum freq MISO stable before next latch edge
0,
};

Expand Down Expand Up @@ -520,19 +532,23 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
{
.data = slave_recv_buf,
.len = (trans_len[0] + 3) & (~3),
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
},
{
.data = slave_recv_buf + send_buf_size,
.len = (trans_len[1] + 3) & (~3),
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
},
//send
{
.data = slave_send_buf,
.len = trans_len[0],
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
},
{
.data = slave_send_buf + send_buf_size,
.len = trans_len[1],
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO,
},
};

Expand Down Expand Up @@ -925,15 +941,17 @@ void slave_run_append(void)
ESP_LOG_BUFFER_HEX_LEVEL("slave exp", slave_exp, trans_len, ESP_LOG_DEBUG);
spitest_cmp_or_dump(slave_exp, ret_trans->data, trans_len);

// append one more transaction
int new_append_len = trans_len << 4;
if (new_append_len > TEST_TRANS_LEN) {
new_append_len = TEST_TRANS_LEN;
if (trans_num <= TEST_APPEND_CACHE_SIZE) {
// append one more transaction
int new_append_len = trans_len << 4;
if (new_append_len > TEST_TRANS_LEN) {
new_append_len = TEST_TRANS_LEN;
}
memset(ret_trans->data, 0, ret_trans->trans_len);
ret_trans->len = new_append_len;
ret_trans->trans_len = 0;
TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, ret_trans, portMAX_DELAY));
}
memset(ret_trans->data, 0, ret_trans->trans_len);
ret_trans->len = new_append_len;
ret_trans->trans_len = 0;
TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, ret_trans, portMAX_DELAY));
}
printf("================Master Tx Done==================\n\n");
free(slave_exp);
Expand All @@ -958,15 +976,17 @@ void slave_run_append(void)
ESP_LOGI("slave", "trasacted len: %d", ret_trans->len);
ESP_LOG_BUFFER_HEX_LEVEL("slave tx", ret_trans->data, ret_trans->len, ESP_LOG_DEBUG);

// append one more transaction
int new_append_len = 16 << (trans_num + 4);
if (new_append_len > TEST_TRANS_LEN) {
new_append_len = TEST_TRANS_LEN;
if (trans_num <= TEST_APPEND_CACHE_SIZE) {
// append one more transaction
int new_append_len = 16 << (trans_num + 4);
if (new_append_len > TEST_TRANS_LEN) {
new_append_len = TEST_TRANS_LEN;
}
ret_trans->len = new_append_len;
ret_trans->trans_len = 0;
prepare_data(ret_trans->data, ret_trans->len, -3);
TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, ret_trans, portMAX_DELAY));
}
ret_trans->len = new_append_len;
ret_trans->trans_len = 0;
prepare_data(ret_trans->data, ret_trans->len, -3);
TEST_ESP_OK(spi_slave_hd_append_trans(TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, ret_trans, portMAX_DELAY));
}
printf("================Master Rx Done==================\n");
for (int i = 0; i < TEST_APPEND_CACHE_SIZE; i++) free(slave_tx_trans[i].data);
Expand Down
42 changes: 19 additions & 23 deletions components/hal/include/hal/spi_slave_hd_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
#include "esp_types.h"
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "soc/gdma_channel.h"
#include "hal/spi_types.h"
#include "hal/dma_types.h"
#if SOC_GPSPI_SUPPORTED
#include "hal/spi_ll.h"
#endif
Expand All @@ -57,13 +59,24 @@ extern "C" {

#if SOC_GPSPI_SUPPORTED

//NOTE!! If both A and B are not defined, '#if (A==B)' is true, because GCC use 0 stand for undefined symbol
#if !defined(SOC_GDMA_TRIG_PERIPH_SPI2_BUS)
typedef dma_descriptor_align4_t spi_dma_desc_t;
#else
#if defined(SOC_GDMA_BUS_AXI) && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AXI)
typedef dma_descriptor_align8_t spi_dma_desc_t;
#elif defined(SOC_GDMA_BUS_AHB) && (SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB)
typedef dma_descriptor_align4_t spi_dma_desc_t;
#endif
#endif

/**
* @brief Type of dma descriptor with appended members
* this structure inherits DMA descriptor, with a pointer to the transaction descriptor passed from users.
*/
typedef struct {
lldesc_t desc; ///< DMA descriptor
void *arg; ///< This points to the transaction descriptor user passed in
spi_dma_desc_t *desc; ///< DMA descriptor
void *arg; ///< This points to the transaction descriptor user passed in
} spi_slave_hd_hal_desc_append_t;

/// Configuration of the HAL
Expand Down Expand Up @@ -105,13 +118,11 @@ typedef struct {
spi_slave_hd_hal_desc_append_t *tx_cur_desc; ///< Current TX DMA descriptor that could be linked (set up).
spi_slave_hd_hal_desc_append_t *tx_dma_head; ///< Head of the linked TX DMA descriptors which are not used by hardware
spi_slave_hd_hal_desc_append_t *tx_dma_tail; ///< Tail of the linked TX DMA descriptors which are not used by hardware
spi_slave_hd_hal_desc_append_t tx_dummy_head; ///< Dummy descriptor for ``tx_dma_head`` to start
uint32_t tx_used_desc_cnt; ///< Number of the TX descriptors that have been setup
uint32_t tx_recycled_desc_cnt; ///< Number of the TX descriptors that could be recycled
spi_slave_hd_hal_desc_append_t *rx_cur_desc; ///< Current RX DMA descriptor that could be linked (set up).
spi_slave_hd_hal_desc_append_t *rx_dma_head; ///< Head of the linked RX DMA descriptors which are not used by hardware
spi_slave_hd_hal_desc_append_t *rx_dma_tail; ///< Tail of the linked RX DMA descriptors which are not used by hardware
spi_slave_hd_hal_desc_append_t rx_dummy_head; ///< Dummy descriptor for ``rx_dma_head`` to start
uint32_t rx_used_desc_cnt; ///< Number of the RX descriptors that have been setup
uint32_t rx_recycled_desc_cnt; ///< Number of the RX descriptors that could be recycled

Expand All @@ -129,23 +140,6 @@ typedef struct {
*/
void spi_slave_hd_hal_init(spi_slave_hd_hal_context_t *hal, const spi_slave_hd_hal_config_t *hal_config);

/**
* @brief Get the size of one DMA descriptor
*
* @param hal Context of the HAL layer
* @param bus_size SPI bus maximum transfer size, in bytes.
* @return Total size needed for all the DMA descriptors
*/
uint32_t spi_slave_hd_hal_get_total_desc_size(spi_slave_hd_hal_context_t *hal, uint32_t bus_size);

/**
* @brief Get the actual bus size
*
* @param hal Context of the HAL layer
* @return Actual bus transaction size
*/
uint32_t spi_salve_hd_hal_get_max_bus_size(spi_slave_hd_hal_context_t *hal);

/**
* @brief Check and clear signal of one event
*
Expand Down Expand Up @@ -272,9 +266,10 @@ int spi_slave_hd_hal_get_last_addr(spi_slave_hd_hal_context_t *hal);
*
* @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);
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
Expand All @@ -285,10 +280,11 @@ bool spi_slave_hd_hal_get_tx_finished_trans(spi_slave_hd_hal_context_t *hal, voi
*
* @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, size_t *out_len);
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
Expand Down
Loading

0 comments on commit c8c7f99

Please sign in to comment.