fix(dma2d): dma2d_force_end should not crash when rx channel is idle

This commit is contained in:
Song Ruo Jing
2025-02-25 20:22:14 +08:00
parent 3f69abdb7e
commit 9004e5009a

View File

@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -298,7 +298,7 @@ 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 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)) { 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_ERR_EOF)) { if (!(intr_status & DMA2D_LL_EVENT_RX_ERR_EOF)) {
assert(dma2d_ll_rx_is_fsm_idle(group->hal.dev, channel_id)); assert(dma2d_ll_rx_is_fsm_idle(group->hal.dev, channel_id));
@@ -957,12 +957,14 @@ esp_err_t dma2d_force_end(dma2d_trans_t *trans, bool *need_yield)
dma2d_group_t *group = trans->rx_chan->group; dma2d_group_t *group = trans->rx_chan->group;
bool in_flight = false; bool in_flight = false;
// We judge whether the transaction is in-flight by checking the RX channel it uses is in-use or free // We judge whether the transaction is in-flight by checking the RX channel it uses is being occupied or free
portENTER_CRITICAL_SAFE(&group->spinlock); portENTER_CRITICAL_SAFE(&group->spinlock);
if (!(group->rx_channel_free_mask & (1 << trans->rx_chan->channel_id))) { if (!(group->rx_channel_free_mask & (1 << trans->rx_chan->channel_id))) {
in_flight = true; in_flight = true;
dma2d_ll_rx_enable_interrupt(group->hal.dev, trans->rx_chan->channel_id, UINT32_MAX, false); dma2d_ll_rx_enable_interrupt(group->hal.dev, trans->rx_chan->channel_id, UINT32_MAX, false);
assert(!dma2d_ll_rx_is_fsm_idle(group->hal.dev, trans->rx_chan->channel_id)); // DMA consumer could generate an error in both cases:
// 1. when TX or RX is transferring data (channel not in idle state)
// 2. TX successfully passed data to the module, but module cannot process the data, so RX has no data to delivery (RX channel in idle state)
} }
portEXIT_CRITICAL_SAFE(&group->spinlock); portEXIT_CRITICAL_SAFE(&group->spinlock);
ESP_RETURN_ON_FALSE_ISR(in_flight, ESP_ERR_INVALID_STATE, TAG, "transaction not in-flight"); ESP_RETURN_ON_FALSE_ISR(in_flight, ESP_ERR_INVALID_STATE, TAG, "transaction not in-flight");