From ce041640ca300618ee34a4a113c0731de1b09cd2 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 14 Mar 2024 18:35:25 +0800 Subject: [PATCH] change(parlio_tx): plenty of driver clean up --- components/esp_driver_parlio/CMakeLists.txt | 2 +- .../include/driver/parlio_tx.h | 3 + .../esp_driver_parlio/src/parlio_common.c | 25 ++-- .../esp_driver_parlio/src/parlio_private.h | 29 +++-- components/esp_driver_parlio/src/parlio_tx.c | 107 +++++++++++------- .../hal/esp32p4/include/hal/parlio_ll.h | 67 +++++------ .../soc/esp32p4/include/soc/clk_tree_defs.h | 4 - 7 files changed, 129 insertions(+), 108 deletions(-) diff --git a/components/esp_driver_parlio/CMakeLists.txt b/components/esp_driver_parlio/CMakeLists.txt index 2b70fac211..92a7904903 100644 --- a/components/esp_driver_parlio/CMakeLists.txt +++ b/components/esp_driver_parlio/CMakeLists.txt @@ -8,5 +8,5 @@ endif() idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${public_include} - PRIV_REQUIRES "esp_pm" "esp_driver_gpio" + PRIV_REQUIRES "esp_pm" "esp_driver_gpio" "esp_mm" ) diff --git a/components/esp_driver_parlio/include/driver/parlio_tx.h b/components/esp_driver_parlio/include/driver/parlio_tx.h index 43b606ba42..cb85cf327e 100644 --- a/components/esp_driver_parlio/include/driver/parlio_tx.h +++ b/components/esp_driver_parlio/include/driver/parlio_tx.h @@ -150,6 +150,9 @@ esp_err_t parlio_tx_unit_register_event_callbacks(parlio_tx_unit_handle_t tx_uni */ typedef struct { uint32_t idle_value; /*!< The value on the data line when the parallel IO is in idle state */ + struct { + uint32_t queue_nonblocking : 1; /*!< If set, when the transaction queue is full, driver will not block the thread but return directly */ + } flags; /*!< Transmit specific config flags */ } parlio_transmit_config_t; /** diff --git a/components/esp_driver_parlio/src/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c index cd5a7aeb70..f8358d90c8 100644 --- a/components/esp_driver_parlio/src/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.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 */ @@ -42,8 +42,6 @@ parlio_group_t *parlio_acquire_group_handle(int group_id) if (group) { new_group = true; s_platform.groups[group_id] = group; - group->group_id = group_id; - group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; PARLIO_RCC_ATOMIC() { parlio_ll_enable_bus_clock(group_id, true); parlio_ll_reset_register(group_id); @@ -61,6 +59,8 @@ parlio_group_t *parlio_acquire_group_handle(int group_id) _lock_release(&s_platform.mutex); if (new_group) { + portMUX_INITIALIZE(&group->spinlock); + group->group_id = group_id; ESP_LOGD(TAG, "new group(%d) at %p", group_id, group); } return group; @@ -81,11 +81,11 @@ void parlio_release_group_handle(parlio_group_t *group) PARLIO_RCC_ATOMIC() { parlio_ll_enable_bus_clock(group_id, false); } - free(group); } _lock_release(&s_platform.mutex); if (do_deinitialize) { + free(group); ESP_LOGD(TAG, "del group(%d)", group_id); } } @@ -96,23 +96,20 @@ esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit) int unit_id = -1; for (int i = 0; i < SOC_PARLIO_GROUPS; i++) { group = parlio_acquire_group_handle(i); - parlio_unit_base_handle_t *group_unit = NULL; ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no memory for group (%d)", i); portENTER_CRITICAL(&group->spinlock); if (unit->dir == PARLIO_DIR_TX) { for (int j = 0; j < SOC_PARLIO_TX_UNITS_PER_GROUP; j++) { - group_unit = &group->tx_units[j]; - if (*group_unit == NULL) { - *group_unit = unit; + if (!group->tx_units[j]) { + group->tx_units[j] = unit; unit_id = j; break; } } } else { for (int j = 0; j < SOC_PARLIO_RX_UNITS_PER_GROUP; j++) { - group_unit = &group->rx_units[j]; - if (*group_unit == NULL) { - *group_unit = unit; + if (!group->rx_units[j]) { + group->rx_units[j] = unit; unit_id = j; break; } @@ -122,7 +119,6 @@ esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit) if (unit_id < 0) { /* didn't find a free unit slot in the group */ parlio_release_group_handle(group); - group = NULL; } else { unit->unit_id = unit_id; unit->group = group; @@ -138,11 +134,12 @@ void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit) { assert(unit); parlio_group_t *group = unit->group; + int unit_id = unit->unit_id; portENTER_CRITICAL(&group->spinlock); if (unit->dir == PARLIO_DIR_TX) { - group->tx_units[unit->unit_id] = NULL; + group->tx_units[unit_id] = NULL; } else { - group->rx_units[unit->unit_id] = NULL; + group->rx_units[unit_id] = NULL; } portEXIT_CRITICAL(&group->spinlock); /* the parlio unit has a reference of the group, release it now */ diff --git a/components/esp_driver_parlio/src/parlio_private.h b/components/esp_driver_parlio/src/parlio_private.h index 1a88979734..52ab3bec1c 100644 --- a/components/esp_driver_parlio/src/parlio_private.h +++ b/components/esp_driver_parlio/src/parlio_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "freertos/FreeRTOS.h" #include "soc/soc_caps.h" #include "soc/gdma_channel.h" +#include "soc/io_mux_reg.h" #include "hal/parlio_types.h" #include "hal/parlio_hal.h" #include "hal/parlio_ll.h" @@ -19,7 +20,10 @@ #include "rom/cache.h" #include "esp_heap_caps.h" #include "driver/parlio_types.h" +#include "esp_cache.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_gpio_reserve.h" +#include "esp_private/gpio.h" #if CONFIG_PARLIO_ISR_IRAM_SAFE #define PARLIO_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) @@ -51,6 +55,8 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t; #endif #endif // defined(SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS) +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + #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) @@ -77,12 +83,12 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t; extern "C" { #endif -enum { +typedef enum { PARLIO_TX_QUEUE_READY, PARLIO_TX_QUEUE_PROGRESS, PARLIO_TX_QUEUE_COMPLETE, PARLIO_TX_QUEUE_MAX, -}; +} parlio_tx_queue_status_t; typedef enum { PARLIO_DIR_TX, @@ -101,21 +107,20 @@ 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 for each group - 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 + 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; /** * @brief The common field of rx and tx unit structure - * */ struct parlio_unit_t { - int unit_id; // unit id - parlio_dir_t dir; - parlio_group_t *group; // group handle + int unit_id; // unit id + parlio_dir_t dir; // direction + parlio_group_t *group; // group handle }; /** diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index 3ec006ab5c..c038496754 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.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 */ @@ -28,7 +28,6 @@ #include "esp_pm.h" #include "soc/parlio_periph.h" #include "hal/parlio_ll.h" -#include "hal/gpio_hal.h" #include "driver/gpio.h" #include "driver/parlio_tx.h" #include "parlio_private.h" @@ -50,6 +49,9 @@ typedef struct parlio_tx_unit_t { intr_handle_t intr; // allocated interrupt handle esp_pm_lock_handle_t pm_lock; // power management lock gdma_channel_handle_t dma_chan; // DMA channel + parlio_dma_desc_t *dma_nodes; // DMA descriptor nodes + parlio_dma_desc_t *dma_nodes_nc;// non-cached DMA descriptor nodes + size_t dma_nodes_num; // number of DMA descriptor nodes #if CONFIG_PM_ENABLE char pm_lock_name[PARLIO_PM_LOCK_NAME_LEN_MAX]; // pm lock name #endif @@ -64,7 +66,6 @@ typedef struct parlio_tx_unit_t { _Atomic parlio_tx_fsm_t fsm; // Driver FSM state parlio_tx_done_callback_t on_trans_done; // callback function when the transmission is done void *user_data; // user data passed to the callback function - parlio_dma_desc_t *dma_nodes; // DMA descriptor nodes parlio_tx_trans_desc_t trans_desc_pool[]; // transaction descriptor pool } parlio_tx_unit_t; @@ -122,7 +123,9 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit) // de-register from group parlio_unregister_unit_from_group(&tx_unit->base); } - free(tx_unit->dma_nodes); + if (tx_unit->dma_nodes) { + free(tx_unit->dma_nodes); + } free(tx_unit); return ESP_OK; } @@ -145,8 +148,7 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); esp_rom_gpio_connect_out_signal(config->data_gpio_nums[i], parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[i], false, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO); - + gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO); } } // Note: the valid signal will override TXD[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG] @@ -156,14 +158,14 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const esp_rom_gpio_connect_out_signal(config->valid_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG], false, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->valid_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(config->valid_gpio_num, PIN_FUNC_GPIO); } if (config->clk_out_gpio_num >= 0) { gpio_conf.pin_bit_mask = BIT64(config->clk_out_gpio_num); ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk out GPIO failed"); esp_rom_gpio_connect_out_signal(config->clk_out_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_out_sig, false, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->clk_out_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(config->clk_out_gpio_num, PIN_FUNC_GPIO); } if (config->clk_in_gpio_num >= 0) { gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; @@ -171,7 +173,7 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed"); esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num, parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_in_sig, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->clk_in_gpio_num], PIN_FUNC_GPIO); + gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO); } return ESP_OK; } @@ -188,6 +190,12 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit) .owner_check = true, }; gdma_apply_strategy(tx_unit->dma_chan, &gdma_strategy_conf); + + // Link the descriptors + size_t dma_nodes_num = tx_unit->dma_nodes_num; + for (int i = 0; i < dma_nodes_num; i++) { + tx_unit->dma_nodes_nc[i].next = (i == dma_nodes_num - 1) ? NULL : &(tx_unit->dma_nodes[i + 1]); + } return ESP_OK; } @@ -247,36 +255,51 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un #endif esp_err_t ret = ESP_OK; parlio_tx_unit_t *unit = NULL; - ESP_GOTO_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); size_t data_width = config->data_width; // data_width must be power of 2 and less than or equal to SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH - ESP_GOTO_ON_FALSE(data_width && (data_width <= SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH) && ((data_width & (data_width - 1)) == 0), - ESP_ERR_INVALID_ARG, err, TAG, "invalid data width"); + ESP_RETURN_ON_FALSE(data_width && (data_width <= SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH) && ((data_width & (data_width - 1)) == 0), + ESP_ERR_INVALID_ARG, TAG, "invalid data width"); // data_width must not conflict with the valid signal - ESP_GOTO_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG), - ESP_ERR_INVALID_ARG, err, TAG, "valid signal conflicts with data signal"); - ESP_GOTO_ON_FALSE(config->max_transfer_size && config->max_transfer_size <= PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8, - ESP_ERR_INVALID_ARG, err, TAG, "invalid max transfer size"); + ESP_RETURN_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG), + ESP_ERR_INVALID_ARG, TAG, "valid signal conflicts with data signal"); + ESP_RETURN_ON_FALSE(config->max_transfer_size && config->max_transfer_size <= PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8, + ESP_ERR_INVALID_ARG, TAG, "invalid max transfer size"); #if SOC_PARLIO_TX_CLK_SUPPORT_GATING // clock gating is controlled by either the MSB bit of data bus or the valid signal - ESP_GOTO_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE), - ESP_ERR_INVALID_ARG, err, TAG, "no gpio can control the clock gating"); + ESP_RETURN_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE), + ESP_ERR_INVALID_ARG, TAG, "no gpio can control the clock gating"); #else - ESP_GOTO_ON_FALSE(config->flags.clk_gate_en == 0, ESP_ERR_NOT_SUPPORTED, err, TAG, "clock gating is not supported"); + ESP_RETURN_ON_FALSE(config->flags.clk_gate_en == 0, ESP_ERR_NOT_SUPPORTED, TAG, "clock gating is not supported"); #endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING // malloc unit memory - unit = heap_caps_calloc(1, sizeof(parlio_tx_unit_t) + sizeof(parlio_tx_trans_desc_t) * config->trans_queue_depth, PARLIO_MEM_ALLOC_CAPS); + uint32_t mem_caps = PARLIO_MEM_ALLOC_CAPS; + unit = heap_caps_calloc(1, sizeof(parlio_tx_unit_t) + sizeof(parlio_tx_trans_desc_t) * config->trans_queue_depth, mem_caps); ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no memory for tx unit"); - size_t dma_nodes_num = config->max_transfer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; - // DMA descriptors must be placed in internal SRAM - unit->dma_nodes = heap_caps_aligned_calloc(PARLIO_DMA_DESC_ALIGNMENT, dma_nodes_num, sizeof(parlio_dma_desc_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); - ESP_GOTO_ON_FALSE(unit->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes"); - // Link the descriptors - for (int i = 0; i < dma_nodes_num; i++) { - unit->dma_nodes[i].next = (i == dma_nodes_num - 1) ? NULL : &(unit->dma_nodes[i + 1]); + // create DMA descriptors + // DMA descriptors must be placed in internal SRAM + mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; + size_t dma_nodes_num = config->max_transfer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + // the alignment should meet both the DMA and cache requirement + size_t alignment = MAX(data_cache_line_size, PARLIO_DMA_DESC_ALIGNMENT); + size_t dma_nodes_mem_size = ALIGN_UP(dma_nodes_num * sizeof(parlio_dma_desc_t), alignment); + parlio_dma_desc_t *dma_nodes = heap_caps_aligned_calloc(alignment, 1, dma_nodes_mem_size, mem_caps); + ESP_GOTO_ON_FALSE(dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes"); + unit->dma_nodes = dma_nodes; + unit->dma_nodes_num = dma_nodes_num; + + // write back and then invalidate the cached dma_nodes, we will skip the cache (by non-cacheable address) when access the dma_nodes + if (data_cache_line_size) { + ESP_GOTO_ON_ERROR(esp_cache_msync(dma_nodes, dma_nodes_mem_size, + ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE), + err, TAG, "cache sync failed"); } + // we will use the non-cached address to manipulate the DMA descriptor, for simplicity + unit->dma_nodes_nc = PARLIO_GET_NON_CACHED_DESC_ADDR(dma_nodes); + unit->max_transfer_bits = config->max_transfer_size * 8; unit->base.dir = PARLIO_DIR_TX; unit->data_width = data_width; @@ -362,27 +385,27 @@ esp_err_t parlio_del_tx_unit(parlio_tx_unit_handle_t unit) return parlio_destroy_tx_unit(unit); } -static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_dma_desc_t *desc_head, const void *buffer, size_t len) +static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_tx_unit_t *tx_unit, const void *buffer, size_t len) { size_t prepared_length = 0; uint8_t *data = (uint8_t *)buffer; - parlio_dma_desc_t *desc = desc_head; + parlio_dma_desc_t *desc_nc = tx_unit->dma_nodes_nc; while (len) { - parlio_dma_desc_t *non_cache_desc = PARLIO_GET_NON_CACHED_DESC_ADDR(desc); uint32_t mount_bytes = len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE ? DMA_DESCRIPTOR_BUFFER_MAX_SIZE : len; len -= mount_bytes; - non_cache_desc->dw0.suc_eof = len == 0; // whether the last frame - non_cache_desc->dw0.size = mount_bytes; - non_cache_desc->dw0.length = mount_bytes; - non_cache_desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - non_cache_desc->buffer = &data[prepared_length]; - desc = desc->next; // move to next descriptor + desc_nc->dw0.suc_eof = (len == 0); // whether the last frame + desc_nc->dw0.size = mount_bytes; + desc_nc->dw0.length = mount_bytes; + desc_nc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + desc_nc->buffer = &data[prepared_length]; + desc_nc = PARLIO_GET_NON_CACHED_DESC_ADDR(desc_nc->next); prepared_length += mount_bytes; } + #if CONFIG_IDF_TARGET_ESP32P4 // Write back to cache to synchronize the cache before DMA start - Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)buffer, len); + esp_cache_msync(buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); #endif // CONFIG_IDF_TARGET_ESP32P4 } @@ -428,7 +451,7 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio tx_unit->cur_trans = t; // DMA transfer data based on bytes not bits, so convert the bit length to bytes, round up - parlio_tx_mount_dma_data(tx_unit->dma_nodes, t->payload, (t->payload_bits + 7) / 8); + parlio_tx_mount_dma_data(tx_unit, t->payload, (t->payload_bits + 7) / 8); parlio_ll_tx_reset_fifo(hal->regs); PARLIO_RCC_ATOMIC() { @@ -529,10 +552,14 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p ESP_RETURN_ON_FALSE((payload_bits % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "payload bit length must be multiple of 8"); #endif // !SOC_PARLIO_TRANS_BIT_ALIGN - // acquire one transaction description from ready queue or complete queue + TickType_t queue_wait_ticks = portMAX_DELAY; + if (config->flags.queue_nonblocking) { + queue_wait_ticks = 0; + } parlio_tx_trans_desc_t *t = NULL; + // acquire one transaction description from ready queue or complete queue if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &t, 0) != pdTRUE) { - if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, 0) == pdTRUE) { + if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, queue_wait_ticks) == pdTRUE) { tx_unit->num_trans_inflight--; } } diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h index cc070cf95b..fe96975c2a 100644 --- a/components/hal/esp32p4/include/hal/parlio_ll.h +++ b/components/hal/esp32p4/include/hal/parlio_ll.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 */ @@ -16,7 +16,6 @@ #include "hal/hal_utils.h" #include "soc/hp_sys_clkrst_struct.h" #include "soc/parl_io_struct.h" -#include "soc/hp_sys_clkrst_struct.h" #define PARLIO_LL_RX_MAX_BYTES_PER_FRAME 0xFFFF #define PARLIO_LL_RX_MAX_CLK_INT_DIV 0x100 @@ -40,13 +39,6 @@ extern "C" { #endif -typedef enum { - PARLIO_LL_CLK_SRC_XTAL = PARLIO_CLK_SRC_XTAL, - PARLIO_LL_CLK_SRC_PLL_F160M = PARLIO_CLK_SRC_PLL_F160M, - PARLIO_LL_CLK_SRC_RC_FAST = PARLIO_CLK_SRC_RC_FAST, - PARLIO_LL_CLK_SRC_PAD = PARLIO_CLK_SRC_EXTERNAL, // clock source from GPIO pad -} parlio_ll_clock_source_t; - typedef enum { PARLIO_LL_RX_EOF_COND_RX_FULL, /*!< RX unit generates EOF event when it receives enough data */ PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ @@ -63,22 +55,23 @@ typedef enum { * @param group_id The group id of the parlio module * @param enable Set true to enable, false to disable */ -static inline void parlio_ll_enable_bus_clock(int group_id, bool enable) +static inline void _parlio_ll_enable_bus_clock(int group_id, bool enable) { (void)group_id; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_parlio_sys_clk_en = enable; HP_SYS_CLKRST.soc_clk_ctrl2.reg_parlio_apb_clk_en = enable; } /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_enable_bus_clock(__VA_ARGS__) +#define parlio_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the parlio module * * @param group_id The group id of the parlio module */ -static inline void parlio_ll_reset_register(int group_id) +static inline void _parlio_ll_reset_register(int group_id) { (void)group_id; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio = 1; @@ -87,7 +80,7 @@ static inline void parlio_ll_reset_register(int group_id) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_reset_register(__VA_ARGS__) +#define parlio_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_reset_register(__VA_ARGS__) ///////////////////////////////////////RX Unit/////////////////////////////////////// @@ -97,21 +90,21 @@ static inline void parlio_ll_reset_register(int group_id) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void _parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_RC_FAST: + case PARLIO_CLK_SRC_RC_FAST: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PLL_F160M: + case PARLIO_CLK_SRC_PLL_F160M: clk_sel = 2; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; @@ -124,7 +117,7 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_source(__VA_ARGS__) +#define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_set_clock_source(__VA_ARGS__) /** * @brief Set the clock divider for the RX unit @@ -132,7 +125,7 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @param dev Parallel IO register base address * @param clk_div Clock division with integral and decimal part */ -static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) +static inline void _parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); @@ -143,14 +136,14 @@ static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_util /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_rx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_div(__VA_ARGS__) +#define parlio_ll_rx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_set_clock_div(__VA_ARGS__) /** * @brief Reset the RX unit Core clock domain * * @param dev Parallel IO register base address */ -static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) +static inline void _parlio_ll_rx_reset_clock(parl_io_dev_t *dev) { (void)dev; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_rx = 1; @@ -159,7 +152,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_rx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_reset_clock(__VA_ARGS__) +#define parlio_ll_rx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_reset_clock(__VA_ARGS__) /** * @brief Enable the RX unit Core clock domain @@ -168,7 +161,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) * @param en True to enable, False to disable */ __attribute__((always_inline)) -static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) +static inline void _parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) { (void)dev; HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_en = en; @@ -176,7 +169,7 @@ static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_rx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_enable_clock(__VA_ARGS__) +#define parlio_ll_rx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_enable_clock(__VA_ARGS__) /** * @brief Set the condition to generate the RX EOF event @@ -420,21 +413,21 @@ static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void _parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_RC_FAST: + case PARLIO_CLK_SRC_RC_FAST: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PLL_F160M: + case PARLIO_CLK_SRC_PLL_F160M: clk_sel = 2; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; @@ -447,7 +440,7 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__) +#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_set_clock_source(__VA_ARGS__) /** * @brief Set the clock divider for the TX unit @@ -455,7 +448,7 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c * @param dev Parallel IO register base address * @param clk_div Clock division with integral and decimal part */ -static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) +static inline void _parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div) { (void)dev; HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV); @@ -466,7 +459,7 @@ static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_util /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__) +#define parlio_ll_tx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_set_clock_div(__VA_ARGS__) /** * @brief Reset the TX unit Core clock domain @@ -474,7 +467,7 @@ static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_util * @param dev Parallel IO register base address */ __attribute__((always_inline)) -static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev) +static inline void _parlio_ll_tx_reset_clock(parl_io_dev_t *dev) { (void)dev; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_tx = 1; @@ -483,7 +476,7 @@ static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_tx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_reset_clock(__VA_ARGS__) +#define parlio_ll_tx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_reset_clock(__VA_ARGS__) /** * @brief Enable the TX unit Core clock domain @@ -492,7 +485,7 @@ static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev) * @param en True to enable, False to disable */ __attribute__((always_inline)) -static inline void parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en) +static inline void _parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en) { (void)dev; HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_en = en; @@ -500,7 +493,7 @@ static inline void parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define parlio_ll_tx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_enable_clock(__VA_ARGS__) +#define parlio_ll_tx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_enable_clock(__VA_ARGS__) /** * @brief Set the data length to be transmitted diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index be4a6486e5..3157a0ace3 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -593,11 +593,7 @@ typedef enum { 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_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */ -#if SOC_CLK_TREE_SUPPORTED PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */ -#else - PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default clock choice */ -#endif } soc_periph_parlio_clk_src_t; //////////////////////////////////////////////////SDMMC///////////////////////////////////////////////////////////////