From 3ae39a039c11b7a4525c914e3dd18d8785fb51c4 Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Wed, 12 Mar 2025 11:46:12 +0800 Subject: [PATCH] feat(dma2d): Add a rx empty event callback --- components/esp_hw_support/dma/dma2d.c | 16 +++++++++++++--- components/esp_hw_support/dma/dma2d_priv.h | 1 + .../dma/include/esp_private/dma2d.h | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/components/esp_hw_support/dma/dma2d.c b/components/esp_hw_support/dma/dma2d.c index bd6f0a4dbb..6c91656094 100644 --- a/components/esp_hw_support/dma/dma2d.c +++ b/components/esp_hw_support/dma/dma2d.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -298,8 +298,14 @@ static NOINLINE_ATTR bool _dma2d_default_rx_isr(dma2d_group_t *group, int channe } } - // If last transcation completes (regardless success or not), free the channels - if (intr_status & (DMA2D_LL_EVENT_RX_SUC_EOF | DMA2D_LL_EVENT_RX_ERR_EOF | DMA2D_LL_EVENT_RX_DESC_ERROR)) { + if (intr_status & DMA2D_LL_EVENT_RX_DESC_EMPTY) { + if (rx_chan->on_desc_empty) { + need_yield |= rx_chan->on_desc_empty(&rx_chan->base, &edata, user_data); + } + } + + // If last transaction completes (regardless success or not), free the channels + if (intr_status & (DMA2D_LL_EVENT_RX_SUC_EOF | DMA2D_LL_EVENT_RX_ERR_EOF | DMA2D_LL_EVENT_RX_DESC_ERROR | DMA2D_LL_EVENT_RX_DESC_EMPTY)) { if (!(intr_status & DMA2D_LL_EVENT_RX_ERR_EOF)) { assert(dma2d_ll_rx_is_fsm_idle(group->hal.dev, channel_id)); } @@ -688,6 +694,10 @@ esp_err_t dma2d_register_rx_event_callbacks(dma2d_channel_handle_t dma2d_chan, d rx_chan->on_desc_done = cbs->on_desc_done; mask |= DMA2D_LL_EVENT_RX_DONE; } + if (cbs->on_desc_empty) { + rx_chan->on_desc_empty = cbs->on_desc_empty; + mask |= DMA2D_LL_EVENT_RX_DESC_EMPTY; + } rx_chan->user_data = user_data; dma2d_ll_rx_enable_interrupt(group->hal.dev, rx_chan->base.channel_id, mask, true); diff --git a/components/esp_hw_support/dma/dma2d_priv.h b/components/esp_hw_support/dma/dma2d_priv.h index 1e555dc730..dcf46bf328 100644 --- a/components/esp_hw_support/dma/dma2d_priv.h +++ b/components/esp_hw_support/dma/dma2d_priv.h @@ -86,6 +86,7 @@ struct dma2d_rx_channel_t { void *user_data; // User registered DMA event data dma2d_event_callback_t on_recv_eof; // RX EOF event callback dma2d_event_callback_t on_desc_done; // RX DONE event callback + dma2d_event_callback_t on_desc_empty; // RX desc empty callback, trigger when buffer on dma is not sufficient. uint32_t bundled_tx_channel_mask; // Bit mask indicating the TX channels together with the RX channel to do the transaction }; diff --git a/components/esp_hw_support/dma/include/esp_private/dma2d.h b/components/esp_hw_support/dma/include/esp_private/dma2d.h index 4524ca95c6..10c964d210 100644 --- a/components/esp_hw_support/dma/include/esp_private/dma2d.h +++ b/components/esp_hw_support/dma/include/esp_private/dma2d.h @@ -344,6 +344,8 @@ typedef struct { to be still in the middle of a complete transaction (partially done), you are allowed to configure 2D-DMA channel hardware/descriptor in this callback, and let the channels start running again */ + dma2d_event_callback_t on_desc_empty; /*!< Invoked when the buffer size pointed to by the received linked list + descriptor is less than the length of the data to be received */ } dma2d_rx_event_callbacks_t; /**