diff --git a/components/esp_driver_parlio/src/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c index f8358d90c8..48518ddb0c 100644 --- a/components/esp_driver_parlio/src/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.c @@ -48,6 +48,8 @@ parlio_group_t *parlio_acquire_group_handle(int group_id) } // hal layer initialize parlio_hal_init(&group->hal); + group->dma_align = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + group->dma_align = group->dma_align < 4 ? 4 : group->dma_align; } } else { // group already install group = s_platform.groups[group_id]; diff --git a/components/esp_driver_parlio/src/parlio_private.h b/components/esp_driver_parlio/src/parlio_private.h index 52ab3bec1c..d728359b09 100644 --- a/components/esp_driver_parlio/src/parlio_private.h +++ b/components/esp_driver_parlio/src/parlio_private.h @@ -30,6 +30,7 @@ #else #define PARLIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif +#define PARLIO_DMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) #if SOC_PARLIO_TX_RX_SHARE_INTERRUPT #define PARLIO_INTR_ALLOC_FLAG_SHARED ESP_INTR_FLAG_SHARED @@ -57,6 +58,12 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t; #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +#define PARLIO_MAX_ALIGNED_DMA_BUF_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED +#else +#define PARLIO_MAX_ALIGNED_DMA_BUF_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED +#endif + #ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR /* The descriptor address can be mapped by a fixed offset */ #define PARLIO_GET_NON_CACHED_DESC_ADDR(desc) (desc ? (parlio_dma_desc_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(desc)) : NULL) @@ -107,11 +114,12 @@ typedef enum { typedef struct parlio_unit_t *parlio_unit_base_handle_t; typedef struct parlio_group_t { - int group_id; // group ID, index from 0 - portMUX_TYPE spinlock; // to protect per-group register level concurrent access - parlio_hal_context_t hal; // hal layer context - parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles - parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles + int group_id; // group ID, index from 0 + portMUX_TYPE spinlock; // to protect per-group register level concurrent access + parlio_hal_context_t hal; // hal layer context + uint32_t dma_align; // DMA buffer alignment + parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles + parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles } parlio_group_t; /** diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c index 6ea8fcd038..a3390947ca 100644 --- a/components/esp_driver_parlio/src/parlio_rx.c +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,7 +33,9 @@ #include "esp_memory_utils.h" #include "esp_clk_tree.h" #include "esp_attr.h" +#include "esp_dma_utils.h" #include "esp_private/gdma.h" +#include "esp_cache.h" static const char *TAG = "parlio-rx"; @@ -81,8 +83,9 @@ typedef struct parlio_rx_unit_t { gdma_channel_handle_t dma_chan; /*!< DMA channel */ size_t max_recv_size; /*!< Maximum receive size for a normal transaction */ size_t desc_num; /*!< DMA descriptor number */ - dma_descriptor_t *dma_descs; /*!< DMA descriptor array pointer */ - dma_descriptor_t *curr_desc; /*!< The pointer of the current descriptor */ + size_t desc_size; /*!< DMA descriptors total size */ + parlio_dma_desc_t **dma_descs; /*!< DMA descriptor array pointer */ + parlio_dma_desc_t *curr_desc; /*!< The pointer of the current descriptor */ void *usr_recv_buf; /*!< The pointe to the user's receiving buffer */ /* Infinite transaction specific */ void *dma_buf; /*!< Additional internal DMA buffer only for infinite transactions */ @@ -125,19 +128,21 @@ typedef struct parlio_rx_delimiter_t { } flags; } parlio_rx_delimiter_t; +#define PRALIO_RX_MOUNT_SIZE_CALC(total_size, div, align) ((((total_size) / (align)) / (div)) * (align)) + static portMUX_TYPE s_rx_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; static IRAM_ATTR size_t s_parlio_mount_transaction_buffer(parlio_rx_unit_handle_t rx_unit, parlio_rx_transaction_t *trans) { - dma_descriptor_t *p_desc = rx_unit->dma_descs; + parlio_dma_desc_t **p_desc = rx_unit->dma_descs; /* Update the current transaction to the next one, and declare the delimiter is under using of the rx unit */ memcpy(&rx_unit->curr_trans, trans, sizeof(parlio_rx_transaction_t)); portENTER_CRITICAL_SAFE(&s_rx_spinlock); trans->delimiter->under_using = true; portEXIT_CRITICAL_SAFE(&s_rx_spinlock); - uint32_t desc_num = trans->size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; - uint32_t remain_num = trans->size % DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + uint32_t desc_num = trans->size / PARLIO_MAX_ALIGNED_DMA_BUF_SIZE; + uint32_t remain_num = trans->size % PARLIO_MAX_ALIGNED_DMA_BUF_SIZE; /* If there are still data remained, need one more descriptor */ desc_num += remain_num ? 1 : 0; if (trans->flags.infinite && desc_num < 2) { @@ -146,30 +151,40 @@ static IRAM_ATTR size_t s_parlio_mount_transaction_buffer(parlio_rx_unit_handle_ } size_t mount_size = 0; size_t offset = 0; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + uint32_t alignment = rx_unit->base.group->dma_align; +#else + uint32_t alignment = 4; +#endif /* Loop the descriptors to assign the data */ for (int i = 0; i < desc_num; i++) { size_t rest_size = trans->size - offset; - if (rest_size >= 2 * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { - mount_size = trans->size / desc_num; - } else if (rest_size <= DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { - mount_size = (desc_num == 2) && (i == 0) ? rest_size / 2 : rest_size; + + if (rest_size >= 2 * PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) { + mount_size = PRALIO_RX_MOUNT_SIZE_CALC(trans->size, desc_num, alignment); + } else if (rest_size <= PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) { + mount_size = (desc_num == 2) && (i == 0) ? PRALIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment) : rest_size; } else { - mount_size = rest_size / 2; + mount_size = PRALIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment); } - p_desc[i].buffer = (void *)((uint8_t *)trans->payload + offset); - p_desc[i].dw0.size = mount_size; - p_desc[i].dw0.length = mount_size; - p_desc[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + p_desc[i]->buffer = (void *)((uint8_t *)trans->payload + offset); + p_desc[i]->dw0.size = mount_size; + p_desc[i]->dw0.length = mount_size; + p_desc[i]->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; // Link the descriptor - if (i > 0) { - p_desc[i - 1].next = &p_desc[i]; + if (i < desc_num - 1) { + p_desc[i]->next = p_desc[i + 1]; + } else { + /* For infinite transaction, link the descriptor as a ring */ + p_desc[i]->next = trans->flags.infinite ? p_desc[0] : NULL; } offset += mount_size; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(p_desc[i], rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); +#endif } - /* For infinite transaction, link the descriptor as a ring */ - p_desc[desc_num - 1].next = trans->flags.infinite ? &p_desc[0] : NULL; /* Reset the current DMA node */ - rx_unit->curr_desc = p_desc; + rx_unit->curr_desc = p_desc[0]; return offset; } @@ -251,6 +266,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; gpio_conf.pin_bit_mask = BIT64(config->clk_in_gpio_num); ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed"); + } else { + gpio_ll_input_enable(&GPIO, config->clk_in_gpio_num); } esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num, parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_in_sig, false); @@ -275,6 +292,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons if (!config->flags.io_no_init) { gpio_conf.pin_bit_mask = BIT64(config->valid_gpio_num); ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); + } else { + gpio_ll_input_enable(&GPIO, config->valid_gpio_num); } /* Not connect the signal here, the signal is lazy connected until the delimiter takes effect */ } @@ -286,7 +305,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons if (!config->flags.io_no_init) { gpio_conf.pin_bit_mask = BIT64(config->data_gpio_nums[i]); ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO); + } else { + gpio_ll_input_enable(&GPIO, config->data_gpio_nums[i]); } esp_rom_gpio_connect_in_signal(config->data_gpio_nums[i], parlio_periph_signals.groups[group_id].rx_units[unit_id].data_sigs[i], false); @@ -330,18 +350,22 @@ static IRAM_ATTR bool s_parlio_rx_default_eof_callback(gdma_channel_handle_t dma /* The current transaction finished, try to get the next transaction from the transaction queue */ if (xQueueReceiveFromISR(rx_unit->trans_que, &next_trans, &high_task_woken) == pdTRUE) { if (rx_unit->cfg.flags.free_clk) { - parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + } } /* If the delimiter of the next transaction is not same as the current one, need to re-config the hardware */ - if (next_trans.delimiter != rx_unit->curr_trans.delimiter) { + if ((next_trans.delimiter != NULL) && (next_trans.delimiter != rx_unit->curr_trans.delimiter)) { s_parlio_set_delimiter_config(rx_unit, next_trans.delimiter); } /* Mount the new transaction buffer and start the new transaction */ s_parlio_mount_transaction_buffer(rx_unit, &next_trans); - gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->dma_descs); + gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->dma_descs[0]); if (rx_unit->cfg.flags.free_clk) { parlio_ll_rx_start(rx_unit->base.group->hal.regs, true); - parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + } } } else if (rx_unit->curr_trans.delimiter) { // Add condition in case the curr_trans has been cleared in the last timeout isr /* No more transaction pending to receive, clear the current transaction */ @@ -368,7 +392,15 @@ static IRAM_ATTR bool s_parlio_rx_default_desc_done_callback(gdma_channel_handle } /* Get the finished descriptor from the current descriptor */ - dma_descriptor_t *finished_desc = rx_unit->curr_desc; + parlio_dma_desc_t *finished_desc = rx_unit->curr_desc; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_err_t ret = ESP_OK; + ret |= esp_cache_msync((void *)finished_desc, rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + ret |= esp_cache_msync((void *)(finished_desc->buffer), finished_desc->dw0.size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + if (ret != ESP_OK) { + ESP_EARLY_LOGW(TAG, "failed to sync dma buffer from memory to cache"); + } +#endif parlio_rx_event_data_t evt_data = { .delimiter = rx_unit->curr_trans.delimiter, .data = finished_desc->buffer, @@ -399,21 +431,41 @@ static IRAM_ATTR bool s_parlio_rx_default_desc_done_callback(gdma_channel_handle static esp_err_t s_parlio_rx_create_dma_descriptors(parlio_rx_unit_handle_t rx_unit, uint32_t max_recv_size) { ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid param"); - + esp_err_t ret = ESP_OK; uint32_t desc_num = max_recv_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED + 1; /* set at least 2 descriptors */ if (desc_num < 2) { - desc_num = 4; + desc_num = 2; } rx_unit->desc_num = desc_num; /* Allocated and link the descriptor nodes */ - rx_unit->dma_descs = (dma_descriptor_t *)heap_caps_calloc(desc_num, sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); - ESP_RETURN_ON_FALSE(rx_unit->dma_descs, ESP_ERR_NO_MEM, TAG, "no memory for DMA descriptors"); + rx_unit->dma_descs = heap_caps_calloc(desc_num, sizeof(parlio_dma_desc_t *), MALLOC_CAP_DMA); + ESP_RETURN_ON_FALSE(rx_unit->dma_descs, ESP_ERR_NO_MEM, TAG, "no memory for DMA descriptor array"); + uint32_t cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + size_t alignment = MAX(cache_line_size, PARLIO_DMA_DESC_ALIGNMENT); + rx_unit->desc_size = ALIGN_UP(sizeof(parlio_dma_desc_t), alignment); + for (int i = 0; i < desc_num; i++) { + rx_unit->dma_descs[i] = heap_caps_aligned_calloc(alignment, 1, rx_unit->desc_size, PARLIO_DMA_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(rx_unit->dma_descs[i], ESP_ERR_NO_MEM, err, TAG, "no memory for DMA descriptors"); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + esp_cache_msync(rx_unit->dma_descs[i], rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); +#endif + } rx_unit->max_recv_size = max_recv_size; - return ESP_OK; + return ret; +err: + for (int i = 0; i < desc_num; i++) { + if (rx_unit->dma_descs[i]) { + free(rx_unit->dma_descs[i]); + rx_unit->dma_descs[i] = NULL; + } + } + free(rx_unit->dma_descs); + rx_unit->dma_descs = NULL; + return ret; } static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit) @@ -422,7 +474,7 @@ static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit) gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, }; - ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed"); + ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed"); gdma_connect(rx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0)); /* Set GDMA strategy */ @@ -487,8 +539,10 @@ static esp_err_t s_parlio_select_periph_clock(parlio_rx_unit_handle_t rx_unit, c #endif /* Set clock configuration */ - parlio_ll_rx_set_clock_source(hal->regs, clk_src); - parlio_ll_rx_set_clock_div(hal->regs, &clk_div); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_set_clock_source(hal->regs, clk_src); + parlio_ll_rx_set_clock_div(hal->regs, &clk_div); + } rx_unit->clk_src = clk_src; /* warning if precision lost due to division */ @@ -525,7 +579,14 @@ static esp_err_t s_parlio_destroy_rx_unit(parlio_rx_unit_handle_t rx_unit) } /* Free the DMA descriptors */ if (rx_unit->dma_descs) { + for (int i = 0; i < rx_unit->desc_num; i++) { + if (rx_unit->dma_descs[i]) { + free(rx_unit->dma_descs[i]); + rx_unit->dma_descs[i] = NULL; + } + } free(rx_unit->dma_descs); + rx_unit->dma_descs = NULL; } /* Free the internal DMA buffer */ if (rx_unit->dma_buf) { @@ -591,9 +652,13 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un /* Install DMA service */ ESP_GOTO_ON_ERROR(s_parlio_rx_unit_init_dma(unit), err, TAG, "install rx DMA failed"); /* Reset RX module */ - parlio_ll_rx_reset_clock(hal->regs); + PARLIO_RCC_ATOMIC() { + parlio_ll_rx_reset_clock(hal->regs); + } parlio_ll_rx_reset_fifo(hal->regs); - parlio_ll_rx_enable_clock(hal->regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(hal->regs, false); + } parlio_ll_rx_start(hal->regs, false); /* parlio_ll_clock_source_t and parlio_clock_source_t are binary compatible if the clock source is from internal */ ESP_GOTO_ON_ERROR(s_parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed"); @@ -651,7 +716,9 @@ esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queu if (!rx_unit->cfg.flags.free_clk) { parlio_ll_rx_reset_fifo(hal->regs); parlio_ll_rx_start(hal->regs, true); - parlio_ll_rx_enable_clock(hal->regs, true); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(hal->regs, true); + } } /* Check if we need to start a pending transaction */ @@ -663,14 +730,18 @@ esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queu // The semaphore always supposed to be taken successfully assert(xSemaphoreTake(rx_unit->trans_sem, 0) == pdTRUE); if (rx_unit->cfg.flags.free_clk) { - parlio_ll_rx_enable_clock(hal->regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(hal->regs, false); + } } s_parlio_set_delimiter_config(rx_unit, trans.delimiter); s_parlio_mount_transaction_buffer(rx_unit, &trans); gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc); if (rx_unit->cfg.flags.free_clk) { parlio_ll_rx_start(hal->regs, true); - parlio_ll_rx_enable_clock(hal->regs, true); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(hal->regs, true); + } } } err: @@ -691,7 +762,9 @@ esp_err_t parlio_rx_unit_disable(parlio_rx_unit_handle_t rx_unit) rx_unit->is_enabled = false; /* stop the RX engine */ gdma_stop(rx_unit->dma_chan); - parlio_ll_rx_enable_clock(hal->regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(hal->regs, false); + } parlio_ll_rx_start(hal->regs, false); if (rx_unit->curr_trans.delimiter) { portENTER_CRITICAL(&s_rx_spinlock); @@ -842,7 +915,9 @@ static esp_err_t s_parlio_rx_unit_do_transaction(parlio_rx_unit_handle_t rx_unit portEXIT_CRITICAL_ISR(&s_rx_spinlock); if (is_stopped) { if (rx_unit->cfg.flags.free_clk) { - parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + } } if (trans->delimiter != rx_unit->curr_trans.delimiter) { s_parlio_set_delimiter_config(rx_unit, trans->delimiter); @@ -853,7 +928,9 @@ static esp_err_t s_parlio_rx_unit_do_transaction(parlio_rx_unit_handle_t rx_unit gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc); if (rx_unit->cfg.flags.free_clk) { parlio_ll_rx_start(rx_unit->base.group->hal.regs, true); - parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + } } } else { // Otherwise send to the queue /* Send the transaction to the queue */ @@ -871,8 +948,17 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, ESP_RETURN_ON_FALSE(rx_unit && payload && recv_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(recv_cfg->delimiter, ESP_ERR_INVALID_ARG, TAG, "no delimiter specified"); ESP_RETURN_ON_FALSE(payload_size <= rx_unit->max_recv_size, ESP_ERR_INVALID_ARG, TAG, "trans length too large"); + uint32_t alignment = rx_unit->base.group->dma_align; +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + ESP_RETURN_ON_FALSE(payload_size % alignment == 0, ESP_ERR_INVALID_ARG, TAG, "The payload size should align with %"PRIu32, alignment); + if (recv_cfg->flags.partial_rx_en) { + ESP_RETURN_ON_FALSE(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG, TAG, "The payload size should greater than %"PRIu32, 2 * alignment); + } +#endif #if CONFIG_GDMA_ISR_IRAM_SAFE ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); +#else + ESP_RETURN_ON_FALSE(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); #endif if (recv_cfg->delimiter->eof_data_len) { ESP_RETURN_ON_FALSE(payload_size >= recv_cfg->delimiter->eof_data_len, ESP_ERR_INVALID_ARG, @@ -895,7 +981,7 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, if (recv_cfg->flags.partial_rx_en && recv_cfg->flags.indirect_mount) { ESP_RETURN_ON_FALSE(!rx_unit->dma_buf, ESP_ERR_INVALID_STATE, TAG, "infinite transaction is using the internal DMA buffer"); /* Allocate the internal DMA buffer to store the data temporary */ - rx_unit->dma_buf = heap_caps_calloc(1, payload_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + rx_unit->dma_buf = heap_caps_aligned_calloc(alignment, 1, payload_size, PARLIO_DMA_MEM_ALLOC_CAPS); ESP_RETURN_ON_FALSE(rx_unit->dma_buf, ESP_ERR_NO_MEM, TAG, "No memory for the internal DMA buffer"); /* Use the internal DMA buffer so that the user buffer can always be available */ p_buffer = rx_unit->dma_buf; diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index c038496754..20a0fdc4bc 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -405,7 +405,7 @@ static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_tx_unit_t *tx_unit, const #if CONFIG_IDF_TARGET_ESP32P4 // Write back to cache to synchronize the cache before DMA start - esp_cache_msync(buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif // CONFIG_IDF_TARGET_ESP32P4 } diff --git a/components/esp_driver_parlio/test_apps/.build-test-rules.yml b/components/esp_driver_parlio/test_apps/.build-test-rules.yml index bc30d2fe7b..c2c576d51f 100644 --- a/components/esp_driver_parlio/test_apps/.build-test-rules.yml +++ b/components/esp_driver_parlio/test_apps/.build-test-rules.yml @@ -4,8 +4,8 @@ components/esp_driver_parlio/test_apps/parlio: disable: - if: SOC_PARLIO_SUPPORTED != 1 disable_test: - - if: IDF_TARGET == "esp32p4" + - if: IDF_TARGET in ["esp32h2", "esp32p4"] temporary: true - reason: lack of runner + reason: IDF-9806 waiting for the fix of the bit shift issue after reset depends_components: - esp_driver_parlio diff --git a/components/esp_driver_parlio/test_apps/parlio/README.md b/components/esp_driver_parlio/test_apps/parlio/README.md index b450dc5ffa..7b822bdb0e 100644 --- a/components/esp_driver_parlio/test_apps/parlio/README.md +++ b/components/esp_driver_parlio/test_apps/parlio/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h index 81c64cbc8c..931cc957f7 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +18,7 @@ extern "C" { #define TEST_PARLIO_CALLBACK_ATTR #define TEST_PARLIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif +#define TEST_PARLIO_DMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) #if CONFIG_IDF_TARGET_ESP32C6 #define TEST_CLK_GPIO 10 @@ -42,15 +43,16 @@ extern "C" { #define TEST_DATA6_GPIO 8 #define TEST_DATA7_GPIO 9 #elif CONFIG_IDF_TARGET_ESP32P4 -#define TEST_CLK_GPIO 20 -#define TEST_DATA0_GPIO 21 -#define TEST_DATA1_GPIO 22 -#define TEST_DATA2_GPIO 34 -#define TEST_DATA3_GPIO 35 -#define TEST_DATA4_GPIO 48 -#define TEST_DATA5_GPIO 49 -#define TEST_DATA6_GPIO 10 -#define TEST_DATA7_GPIO 11 +#define TEST_CLK_GPIO 32 +#define TEST_VALID_GPIO 36 +#define TEST_DATA0_GPIO 20 +#define TEST_DATA1_GPIO 21 +#define TEST_DATA2_GPIO 22 +#define TEST_DATA3_GPIO 23 +#define TEST_DATA4_GPIO 45 +#define TEST_DATA5_GPIO 46 +#define TEST_DATA6_GPIO 47 +#define TEST_DATA7_GPIO 48 #else #error "Unsupported target" #endif diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c index c9b38bde6a..4f4dd596a2 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,16 +17,26 @@ #include "driver/spi_master.h" #include "driver/gpio.h" #include "hal/gpio_hal.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "soc/soc_caps.h" #include "soc/i2s_periph.h" #include "soc/spi_periph.h" #include "soc/parlio_periph.h" +#include "esp_dma_utils.h" #include "esp_attr.h" #include "test_board.h" #define TEST_SPI_HOST SPI2_HOST #define TEST_I2S_PORT I2S_NUM_0 #define TEST_VALID_SIG (PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1) + +#if SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT +#define TEST_OUTPUT_CLK_PIN TEST_CLK_GPIO +#else +#define TEST_OUTPUT_CLK_PIN -1 +#endif + #define TEST_DEFAULT_UNIT_CONFIG(_clk_src, _clk_freq) { \ .trans_queue_depth = 10, \ .max_recv_size = 10 * 1024, \ @@ -35,7 +45,7 @@ .ext_clk_freq_hz = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? _clk_freq : 0, \ .clk_in_gpio_num = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? TEST_CLK_GPIO : -1, \ .exp_clk_freq_hz = _clk_freq, \ - .clk_out_gpio_num = -1, \ + .clk_out_gpio_num = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? -1 : TEST_OUTPUT_CLK_PIN, \ .valid_gpio_num = TEST_VALID_GPIO, \ .data_gpio_nums = { \ [0] = TEST_DATA0_GPIO, \ @@ -56,6 +66,10 @@ typedef struct { uint32_t timeout_cnt; } test_data_t; +#ifndef ALIGN_UP +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#endif + TEST_PARLIO_CALLBACK_ATTR static bool test_parlio_rx_partial_recv_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data) { @@ -285,11 +299,15 @@ static bool test_delimiter(parlio_rx_delimiter_handle_t deli, bool free_running_ .delimiter = deli, .flags.partial_rx_en = false, }; - uint8_t recv_buff[TEST_EOF_DATA_LEN]; + uint8_t *recv_buff = NULL; + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + alignment = alignment < 4 ? 4 : alignment; + size_t buff_size = ALIGN_UP(TEST_EOF_DATA_LEN, alignment); + recv_buff = heap_caps_aligned_calloc(alignment, 1, buff_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS); bool is_success = false; // sample 5 times for (int i = 0; i < 5 && !is_success; i++) { - TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, recv_buff, TEST_EOF_DATA_LEN, &recv_config)); + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, recv_buff, buff_size, &recv_config)); TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); for (int k = 0; k < TEST_EOF_DATA_LEN; k++) { printf("%x ", recv_buff[k]); @@ -315,6 +333,7 @@ static bool test_delimiter(parlio_rx_delimiter_handle_t deli, bool free_running_ } // Delete the sender task vTaskDelete(sender_task); + free(recv_buff); TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); @@ -409,8 +428,7 @@ TEST_CASE("parallel_rx_unit_install_uninstall", "[parlio_rx]") TEST_ESP_OK(parlio_rx_unit_disable(units[0])); TEST_ESP_OK(parlio_del_rx_unit(units[0])); } - -#define TEST_PAYLOAD_SIZE 5000 +#define TEST_PAYLOAD_SIZE 5120 // This test case uses soft delimiter TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]") @@ -444,7 +462,11 @@ TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]") .delimiter = deli, .flags.partial_rx_en = false, }; - uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS); + uint8_t *payload = NULL; + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + alignment = alignment < 4 ? 4 : alignment; + size_t payload_size = ALIGN_UP(TEST_PAYLOAD_SIZE, alignment); + payload = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS); TEST_ASSERT(payload); printf("Testing one normal transaction...\n"); @@ -535,7 +557,11 @@ TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") .delimiter = timeout_deli, .flags.partial_rx_en = false, }; - uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS); + uint8_t *payload = NULL; + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + alignment = alignment < 4 ? 4 : alignment; + size_t payload_size = ALIGN_UP(TEST_PAYLOAD_SIZE, alignment); + payload = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS); TEST_ASSERT(payload); printf("Testing the timeout callback...\n"); diff --git a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py index 4f572edd20..dbb3f9d4e0 100644 --- a/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py +++ b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py @@ -1,12 +1,10 @@ # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut @pytest.mark.esp32c6 -@pytest.mark.esp32h2 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h index fe96975c2a..b7cc5558d5 100644 --- a/components/hal/esp32p4/include/hal/parlio_ll.h +++ b/components/hal/esp32p4/include/hal/parlio_ll.h @@ -213,13 +213,13 @@ static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bi * @brief Set the sub mode of the level controlled receive mode * * @param dev Parallel IO register base address - * @param active_level Level of the external enable signal, true for active high, false for active low + * @param active_low_en Level of the external enable signal, true for active low, false for active high */ __attribute__((always_inline)) -static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_level) +static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_low_en) { dev->rx_mode_cfg.rx_smp_mode_sel = 0; - dev->rx_mode_cfg.rx_ext_en_inv = !active_level; // 0: active low, 1: active high + dev->rx_mode_cfg.rx_ext_en_inv = active_low_en; } /** @@ -359,7 +359,7 @@ static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32 } /** - * @brief Wether to enable the RX clock gating + * @brief whether to enable the RX clock gating * * @param dev Parallel IO register base address * @param en True to enable, False to disable @@ -519,7 +519,7 @@ static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_ } /** - * @brief Wether to enable the TX clock gating + * @brief whether to enable the TX clock gating * * @note The MSB of TXD will be taken as the gating enable signal * @@ -589,7 +589,6 @@ static inline void parlio_ll_tx_set_bus_width(parl_io_dev_t *dev, uint32_t width { uint32_t width_sel = 0; switch (width) { - // TODO: check this field (IDF-8284) case 16: width_sel = 4; break; diff --git a/components/hal/include/hal/dma_types.h b/components/hal/include/hal/dma_types.h index 435ac5cd96..03146740aa 100644 --- a/components/hal/include/hal/dma_types.h +++ b/components/hal/include/hal/dma_types.h @@ -58,6 +58,7 @@ ESP_STATIC_ASSERT(sizeof(dma_descriptor_align8_t) == 16, "dma_descriptor_align8_ #define DMA_DESCRIPTOR_BUFFER_MAX_SIZE (4095) /*!< Maximum size of the buffer that can be attached to descriptor */ #define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED (4095-3) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 4B */ #define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_16B_ALIGNED (4095-15) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 16B */ +#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED (4095-63) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 64B */ /** * Get the number of DMA descriptors required for a given buffer size. diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index c8822246f2..7fc01d249a 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -63,6 +63,10 @@ config SOC_ETM_SUPPORTED bool default y +config SOC_PARLIO_SUPPORTED + bool + default y + config SOC_ASYNC_MEMCPY_SUPPORTED bool default y @@ -991,6 +995,10 @@ config SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH int default 16 +config SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT + bool + default y + config SOC_PARLIO_TX_SIZE_BY_DMA bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 5626e7f2b0..5679247b50 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -635,8 +635,8 @@ typedef enum { */ typedef enum { PARLIO_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ - PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */ PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ } soc_periph_parlio_clk_src_t; diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 8d3fece9ed..9c54eaaec5 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -34,7 +34,7 @@ #define SOC_MCPWM_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_ETM_SUPPORTED 1 -// #define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471 +#define SOC_PARLIO_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_EMAC_SUPPORTED 1 #define SOC_USB_OTG_SUPPORTED 1 @@ -393,6 +393,7 @@ #define SOC_PARLIO_RX_UNITS_PER_GROUP 1U /*!< number of RX units in each group */ #define SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the TX unit */ #define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the RX unit */ +#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */ #define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */ /*--------------------------- MPI CAPS ---------------------------------------*/ diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 0217624acc..3d34d63abc 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -261,9 +261,11 @@ examples/peripherals/parlio: examples/peripherals/parlio/parlio_rx: disable: - - if: SOC_PARLIO_SUPPORTED != 1 or IDF_TARGET == "esp32p4" + - if: SOC_PARLIO_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" temporary: true - reason: not support esp32p4 yet (IDF-7471) + reason: lack of runner depends_components: - esp_driver_parlio diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md b/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md index 6f91587df2..1881bdf223 100644 --- a/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | # Logic Analyzer Example diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h index 77d6b4b517..94bd1e521f 100644 --- a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,8 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" +#include "soc/soc_caps.h" +#include "hal/dma_types.h" #include "esp_heap_caps.h" #include "esp_probe.h" @@ -19,12 +21,17 @@ extern "C" { #endif #define ESP_PROBE_DEFAULT_Q_DEPTH 8 -#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * 4092) +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED) +#else +#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) +#endif #if CONFIG_PARLIO_ISR_IRAM_SAFE #define ESP_PROBE_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define ESP_PROBE_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif +#define ESP_PROBE_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA) struct esp_probe_t { uint32_t sample_width; /*!< sample width, i.e., enabled probe channel nums */ diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c index 389687f609..f317c3b39e 100644 --- a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,8 +8,11 @@ #include #include "sdkconfig.h" #include "driver/parlio_rx.h" +#include "hal/cache_hal.h" +#include "hal/cache_ll.h" #include "esp_clk_tree.h" #include "esp_heap_caps.h" +#include "esp_dma_utils.h" #include "esp_check.h" #include "esp_probe_private.h" @@ -43,7 +46,11 @@ esp_err_t esp_probe_priv_init_hardware(esp_probe_handle_t handle, esp_probe_conf esp_err_t ret = ESP_OK; s_ephi = calloc(1, sizeof(esp_probe_impl_pralio_t)); ESP_RETURN_ON_FALSE(s_ephi, ESP_ERR_NO_MEM, TAG, "no memory for the esp probe hardware implementation"); - s_ephi->payload = heap_caps_calloc(1, ESP_PROBE_DEFAULT_MAX_RECV_SIZE, ESP_PROBE_ALLOC_CAPS); + + uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + alignment = alignment < 4 ? 4 : alignment; + size_t payload_aligned_size = ESP_PROBE_DEFAULT_MAX_RECV_SIZE & ~(alignment - 1); + s_ephi->payload = heap_caps_aligned_calloc(alignment, 1, payload_aligned_size, ESP_PROBE_DMA_ALLOC_CAPS); ESP_GOTO_ON_FALSE(s_ephi->payload, ESP_ERR_NO_MEM, err, TAG, "no memory for payload"); // Get the channel number, the channel number can only be the power of 2 diff --git a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md index d995f56c6d..db62a41730 100644 --- a/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md +++ b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | # Parallel IO TX Example: Simple RGB LED Matrix