From 8bacd5aab3ee6944034e48e4f6ee88314709ae86 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 14 Mar 2024 18:35:25 +0800 Subject: [PATCH] feat(parlio_tx): support non-blocking transaction queue --- .../driver/parlio/include/driver/parlio_tx.h | 5 +++- components/driver/parlio/parlio_common.c | 8 ++--- components/driver/parlio/parlio_private.h | 6 ++-- components/driver/parlio/parlio_tx.c | 30 +++++++++++-------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/components/driver/parlio/include/driver/parlio_tx.h b/components/driver/parlio/include/driver/parlio_tx.h index 43b606ba42..060aa6f636 100644 --- a/components/driver/parlio/include/driver/parlio_tx.h +++ b/components/driver/parlio/include/driver/parlio_tx.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 */ @@ -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/driver/parlio/parlio_common.c b/components/driver/parlio/parlio_common.c index f3450ff79d..09cdad4c18 100644 --- a/components/driver/parlio/parlio_common.c +++ b/components/driver/parlio/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 */ @@ -43,8 +43,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; // enable APB access PARLIO registers periph_module_enable(parlio_periph_signals.groups[group_id].module); periph_module_reset(parlio_periph_signals.groups[group_id].module); @@ -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; @@ -79,11 +79,11 @@ void parlio_release_group_handle(parlio_group_t *group) // hal layer deinitialize parlio_hal_deinit(&group->hal); periph_module_disable(parlio_periph_signals.groups[group_id].module); - free(group); } _lock_release(&s_platform.mutex); if (do_deinitialize) { + free(group); ESP_LOGD(TAG, "del group(%d)", group_id); } } diff --git a/components/driver/parlio/parlio_private.h b/components/driver/parlio/parlio_private.h index 1eabbe81cc..619ba5d8d8 100644 --- a/components/driver/parlio/parlio_private.h +++ b/components/driver/parlio/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 */ @@ -38,12 +38,12 @@ 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_TX_FSM_INIT_WAIT, diff --git a/components/driver/parlio/parlio_tx.c b/components/driver/parlio/parlio_tx.c index ee7c3cbefe..194f7f1be1 100644 --- a/components/driver/parlio/parlio_tx.c +++ b/components/driver/parlio/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 */ @@ -271,22 +271,22 @@ 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 @@ -539,10 +539,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--; } }