diff --git a/components/esp_hw_support/dma/dma2d.c b/components/esp_hw_support/dma/dma2d.c index 1e2c6ceca8..dab310d02c 100644 --- a/components/esp_hw_support/dma/dma2d.c +++ b/components/esp_hw_support/dma/dma2d.c @@ -98,8 +98,6 @@ static bool acquire_free_channels_for_trans(dma2d_group_t *dma2d_group, const dm dma2d_group->tx_chans[channel_id]->base.status.periph_sel_id = -1; if (trans_desc->channel_flags & DMA2D_CHANNEL_FUNCTION_FLAG_TX_REORDER) { dma2d_group->tx_chans[channel_id]->base.status.reorder_en = true; - } else if (trans_desc->channel_flags & DMA2D_CHANNEL_FUNCTION_FLAG_SIBLING) { - dma2d_group->tx_chans[channel_id]->base.status.has_sibling = true; } channel_handle_array[idx].chan = &dma2d_group->tx_chans[channel_id]->base; channel_handle_array[idx].dir = DMA2D_CHANNEL_DIRECTION_TX; @@ -137,8 +135,6 @@ static bool acquire_free_channels_for_trans(dma2d_group_t *dma2d_group, const dm dma2d_group->rx_chans[channel_id]->base.status.periph_sel_id = -1; if (trans_desc->channel_flags & DMA2D_CHANNEL_FUNCTION_FLAG_RX_REORDER) { dma2d_group->rx_chans[channel_id]->base.status.reorder_en = true; - } else if (trans_desc->channel_flags & DMA2D_CHANNEL_FUNCTION_FLAG_SIBLING) { - dma2d_group->rx_chans[channel_id]->base.status.has_sibling = true; } channel_handle_array[idx].chan = &dma2d_group->rx_chans[channel_id]->base; channel_handle_array[idx].dir = DMA2D_CHANNEL_DIRECTION_RX; @@ -176,6 +172,8 @@ static bool free_up_channels(dma2d_group_t *group, dma2d_rx_channel_t *rx_chan) uint32_t channel_id = rx_chan->base.channel_id; // 1. Clean up channels uint32_t bundled_tx_channel_mask = rx_chan->bundled_tx_channel_mask; + uint32_t tx_periph_sel_id_mask = 0; + uint32_t rx_periph_sel_id_mask = 0; // Disable RX channel interrupt portENTER_CRITICAL_SAFE(&rx_chan->base.spinlock); dma2d_ll_rx_enable_interrupt(group->hal.dev, channel_id, UINT32_MAX, false); @@ -186,6 +184,9 @@ static bool free_up_channels(dma2d_group_t *group, dma2d_rx_channel_t *rx_chan) dma2d_ll_rx_disconnect_from_periph(group->hal.dev, channel_id); // Clear the pointer that points to the finished transaction rx_chan->base.status.transaction = NULL; + // Record its periph_sel_id + assert(rx_chan->base.status.periph_sel_id != -1); + rx_periph_sel_id_mask |= (1 << rx_chan->base.status.periph_sel_id); portEXIT_CRITICAL_SAFE(&rx_chan->base.spinlock); // For every bundled TX channels: while (rx_chan->bundled_tx_channel_mask) { @@ -201,6 +202,9 @@ static bool free_up_channels(dma2d_group_t *group, dma2d_rx_channel_t *rx_chan) dma2d_ll_tx_disconnect_from_periph(group->hal.dev, nbit); // Clear the pointer that points to the finished transaction tx_chan->base.status.transaction = NULL; + // Record its periph_sel_id + assert(tx_chan->base.status.periph_sel_id != -1); + tx_periph_sel_id_mask |= (1 << tx_chan->base.status.periph_sel_id); portEXIT_CRITICAL_SAFE(&tx_chan->base.spinlock); } // Channel functionality flags will be reset and assigned new values inside `acquire_free_channels_for_trans` @@ -212,12 +216,12 @@ static bool free_up_channels(dma2d_group_t *group, dma2d_rx_channel_t *rx_chan) dma2d_trans_channel_info_t channel_handle_array[DMA2D_MAX_CHANNEL_NUM_PER_TRANSACTION]; portENTER_CRITICAL_SAFE(&group->spinlock); + // Release channels group->tx_channel_free_mask |= bundled_tx_channel_mask; group->rx_channel_free_mask |= (1 << channel_id); - int rx_periph_sel_id = group->rx_chans[channel_id]->base.status.periph_sel_id; - if (rx_periph_sel_id != -1 && ((1 << rx_periph_sel_id) & DMA2D_LL_CHANNEL_PERIPH_M2M_FREE_ID_MASK)) { - group->periph_m2m_free_id_mask |= (1 << rx_periph_sel_id); // release m2m periph_sel_id - } + // Release M2M periph_sel_id + group->tx_periph_m2m_free_id_mask |= (tx_periph_sel_id_mask & DMA2D_LL_TX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK); + group->rx_periph_m2m_free_id_mask |= (rx_periph_sel_id_mask & DMA2D_LL_RX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK); dma2d_trans_t *next_trans_elm = TAILQ_FIRST(&group->pending_trans_tailq); if (next_trans_elm) { @@ -295,10 +299,10 @@ 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) || - (intr_status & DMA2D_LL_EVENT_RX_ERR_EOF) || - (intr_status & DMA2D_LL_EVENT_RX_DESC_ERROR)) { - assert(dma2d_ll_rx_is_fsm_idle(group->hal.dev, channel_id)); + 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)) { + assert(dma2d_ll_rx_is_fsm_idle(group->hal.dev, channel_id)); + } need_yield |= free_up_channels(group, rx_chan); } @@ -365,7 +369,8 @@ esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handl pre_alloc_group->rx_channel_free_mask = (1 << SOC_DMA2D_RX_CHANNELS_PER_GROUP) - 1; pre_alloc_group->tx_channel_reserved_mask = dma2d_tx_channel_reserved_mask[group_id]; pre_alloc_group->rx_channel_reserved_mask = dma2d_rx_channel_reserved_mask[group_id]; - pre_alloc_group->periph_m2m_free_id_mask = DMA2D_LL_CHANNEL_PERIPH_M2M_FREE_ID_MASK; + pre_alloc_group->tx_periph_m2m_free_id_mask = DMA2D_LL_TX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK; + pre_alloc_group->rx_periph_m2m_free_id_mask = DMA2D_LL_RX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK; pre_alloc_group->intr_priority = -1; for (int i = 0; i < SOC_DMA2D_TX_CHANNELS_PER_GROUP; i++) { pre_alloc_group->tx_chans[i] = &pre_alloc_tx_channels[i]; @@ -393,8 +398,6 @@ esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handl dma2d_hal_init(&pre_alloc_group->hal, group_id); // initialize HAL context // Enable 2D-DMA module clock dma2d_ll_hw_enable(s_platform.groups[group_id]->hal.dev, true); - // Configure 2D-DMA accessible memory range - dma2d_ll_set_accessible_mem_range(s_platform.groups[group_id]->hal.dev); } else { ret = ESP_ERR_NO_MEM; free(pre_alloc_tx_channels); @@ -531,41 +534,30 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t // Find periph_sel_id for the channel int peri_sel_id = trig_periph->periph_sel_id; + uint32_t *periph_m2m_free_id_mask = NULL; + uint32_t periph_m2m_available_id_mask = 0; + if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) { + periph_m2m_free_id_mask = &group->tx_periph_m2m_free_id_mask; + periph_m2m_available_id_mask = DMA2D_LL_TX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK; + } else { + periph_m2m_free_id_mask = &group->rx_periph_m2m_free_id_mask; + periph_m2m_available_id_mask = DMA2D_LL_RX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK; + } portENTER_CRITICAL_SAFE(&group->spinlock); if (trig_periph->periph == DMA2D_TRIG_PERIPH_M2M) { - // Assign peri_sel_id to one of {4, 5, 6, 7} - assert(dma2d_chan->status.has_sibling); - // First find out the peri_sel_id of its sibling channel - int sibling_periph_sel_id = -1; - if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) { - sibling_periph_sel_id = group->rx_chans[channel_id]->base.status.periph_sel_id; - } else { - sibling_periph_sel_id = group->tx_chans[channel_id]->base.status.periph_sel_id; - } - if (peri_sel_id == -1) { // Unspecified periph_sel_id, decide by the driver - if (sibling_periph_sel_id != -1 && ((1 << sibling_periph_sel_id) & DMA2D_LL_CHANNEL_PERIPH_M2M_FREE_ID_MASK)) { - peri_sel_id = sibling_periph_sel_id; - } else { - peri_sel_id = __builtin_ctz(group->periph_m2m_free_id_mask); - } + peri_sel_id = __builtin_ctz(*periph_m2m_free_id_mask); } else { // Check whether specified periph_sel_id is valid - if (sibling_periph_sel_id != -1) { - if (sibling_periph_sel_id != peri_sel_id) { - peri_sel_id = -1; // Conflict id with its sibling channel - } - } else { - if (!((1 << peri_sel_id) & group->periph_m2m_free_id_mask & DMA2D_LL_CHANNEL_PERIPH_M2M_FREE_ID_MASK)) { - peri_sel_id = -1; // Occupied or invalid m2m peri_sel_id - } + if (!((1 << peri_sel_id) & *periph_m2m_free_id_mask & periph_m2m_available_id_mask)) { + peri_sel_id = -1; // Occupied or invalid m2m peri_sel_id } } } if (peri_sel_id >= 0) { dma2d_chan->status.periph_sel_id = peri_sel_id; - group->periph_m2m_free_id_mask &= ~(1 << peri_sel_id); // acquire m2m periph_sel_id + *periph_m2m_free_id_mask &= ~(1 << peri_sel_id); // acquire m2m periph_sel_id } portEXIT_CRITICAL_SAFE(&group->spinlock); ESP_GOTO_ON_FALSE_ISR(peri_sel_id >= 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid periph_sel_id"); @@ -608,6 +600,7 @@ esp_err_t dma2d_connect(dma2d_channel_handle_t dma2d_chan, const dma2d_trigger_t // Reset to certain settings dma2d_ll_rx_enable_owner_check(group->hal.dev, channel_id, false); + dma2d_ll_rx_set_auto_return_owner(group->hal.dev, channel_id, DMA2D_DESCRIPTOR_BUFFER_OWNER_CPU); // After auto write back, the owner field will be cleared dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, false); dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, DMA2D_DATA_BURST_LENGTH_128); dma2d_ll_rx_enable_page_bound_wrap(group->hal.dev, channel_id, true); @@ -834,12 +827,10 @@ esp_err_t dma2d_set_transfer_ability(dma2d_channel_handle_t dma2d_chan, const dm if (dma2d_chan->direction == DMA2D_CHANNEL_DIRECTION_TX) { dma2d_ll_tx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en); dma2d_ll_tx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length); - dma2d_ll_tx_enable_page_bound_wrap(group->hal.dev, channel_id, ability->data_burst_length != 1); dma2d_ll_tx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size); } else { dma2d_ll_rx_enable_descriptor_burst(group->hal.dev, channel_id, ability->desc_burst_en); dma2d_ll_rx_set_data_burst_length(group->hal.dev, channel_id, ability->data_burst_length); - dma2d_ll_rx_enable_page_bound_wrap(group->hal.dev, channel_id, ability->data_burst_length != 1); dma2d_ll_rx_set_macro_block_size(group->hal.dev, channel_id, ability->mb_size); } @@ -942,7 +933,7 @@ err: esp_err_t dma2d_force_end(dma2d_trans_t *trans, bool *need_yield) { - ESP_RETURN_ON_FALSE_ISR(trans && trans->rx_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE_ISR(trans && trans->rx_chan && need_yield, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); assert(trans->rx_chan->direction == DMA2D_CHANNEL_DIRECTION_RX); dma2d_group_t *group = trans->rx_chan->group; diff --git a/components/esp_hw_support/dma/dma2d_priv.h b/components/esp_hw_support/dma/dma2d_priv.h index 282b599eef..1e555dc730 100644 --- a/components/esp_hw_support/dma/dma2d_priv.h +++ b/components/esp_hw_support/dma/dma2d_priv.h @@ -55,7 +55,8 @@ struct dma2d_group_t { uint8_t rx_channel_free_mask; // Bit mask indicating the free RX channels at the moment uint8_t tx_channel_reserved_mask; // Bit mask indicating the being reserved TX channels uint8_t rx_channel_reserved_mask; // Bit mask indicating the being reserved RX channels - uint32_t periph_m2m_free_id_mask; // Bit mask indicating the available M2M peripheral selelction IDs at the moment + uint32_t tx_periph_m2m_free_id_mask; // Bit mask indicating the available TX M2M peripheral selelction IDs at the moment + uint32_t rx_periph_m2m_free_id_mask; // Bit mask indicating the available RX M2M peripheral selelction IDs at the moment dma2d_tx_channel_t *tx_chans[SOC_DMA2D_TX_CHANNELS_PER_GROUP]; // Handles of 2D-DMA TX channels dma2d_rx_channel_t *rx_chans[SOC_DMA2D_RX_CHANNELS_PER_GROUP]; // Handles of 2D-DMA RX channels int intr_priority; // All channels in the same group should share the same interrupt priority @@ -70,7 +71,6 @@ struct dma2d_channel_t { struct { dma2d_trans_t *transaction; // Pointer to the 2D-DMA transaction context that is currently being processed on the channel uint32_t reorder_en : 1; // This flag indicates the channel will enable reorder functionality - uint32_t has_sibling : 1; // This flag indicates its sibling channel is also in-use int periph_sel_id : (DMA2D_LL_CHANNEL_PERIPH_SEL_BIT_WIDTH + 1); // This is used to record the periph_sel_id of each channel } status; }; diff --git a/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c b/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c index 03f01e6abf..33a49d1a47 100644 --- a/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c +++ b/components/esp_hw_support/test_apps/dma2d/main/test_dma2d.c @@ -104,9 +104,9 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]") prtx[idx] = (i + idx + 0x45) & 0xFF; prrx[idx] = 0; } - // Writeback and invalidate the TX and RX buffers - esp_cache_msync((void *)prtx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - esp_cache_msync((void *)prrx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + // Writeback TX and RX buffers + esp_cache_msync((void *)prtx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -146,6 +146,11 @@ TEST_CASE("DMA2D_M2M_1D_basic", "[DMA2D]") for (int i = 0; i < M2M_TRANS_TIMES; i++) { prtx = tx_buf + i * data_size; prrx = rx_buf + i * data_size; + + // Invalidate TX and RX buffers + esp_cache_msync((void *)prtx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, data_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + for (int idx = 0; idx < data_size; idx++) { TEST_ASSERT_EQUAL(prtx[idx], prrx[idx]); TEST_ASSERT_EQUAL(prtx[idx], (i + idx + 0x45) & 0xFF); @@ -249,9 +254,9 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]") prrx[idx * 3 + 1] = 0; prrx[idx * 3 + 2] = 0; } - // Writeback and invalidate the TX and RX buffers - esp_cache_msync((void *)prtx, item_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - esp_cache_msync((void *)prrx, item_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + // Writeback TX and RX buffers + esp_cache_msync((void *)prtx, item_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, item_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -292,6 +297,11 @@ TEST_CASE("DMA2D_M2M_1D_RGB565_to_RGB888", "[DMA2D]") for (int i = 0; i < M2M_TRANS_TIMES; i++) { prtx = tx_buf + i * item_size * 2; prrx = rx_buf + i * item_size * 3; + + // Invalidate TX and RX buffers + esp_cache_msync((void *)prtx, item_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, item_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + TEST_ASSERT_EQUAL(0, rgb565_to_rgb888_and_cmp(prtx, prrx, item_size)); } @@ -349,9 +359,9 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]") prtx[idx] = (i + idx + 0x45) & 0xFF; prrx[idx] = 0; } - // Writeback and invalidate the TX and RX buffers - esp_cache_msync((void *)prtx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - esp_cache_msync((void *)prrx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + // Writeback TX and RX buffers + esp_cache_msync((void *)prtx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -391,6 +401,11 @@ TEST_CASE("DMA2D_M2M_2D_basic", "[DMA2D]") for (int i = 0; i < M2M_TRANS_TIMES; i++) { prtx = tx_buf + i * stripe_size * stripe_size; prrx = rx_buf + i * stripe_size * stripe_size; + + // Invalidate TX and RX buffers + esp_cache_msync((void *)prtx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, stripe_size * stripe_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + for (int idx = 0; idx < stripe_size * stripe_size; idx++) { TEST_ASSERT_EQUAL(prtx[idx], prrx[idx]); TEST_ASSERT_EQUAL(prtx[idx], (i + idx + 0x45) & 0xFF); @@ -494,9 +509,9 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]") prrx[idx * 2] = 0; prrx[idx * 2 + 1] = 0; } - // Writeback and invalidate the TX and RX buffers - esp_cache_msync((void *)prtx, stripe_pixel_size * stripe_pixel_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - esp_cache_msync((void *)prrx, stripe_pixel_size * stripe_pixel_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + // Writeback TX and RX buffers + esp_cache_msync((void *)prtx, stripe_pixel_size * stripe_pixel_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, stripe_pixel_size * stripe_pixel_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -537,6 +552,11 @@ TEST_CASE("DMA2D_M2M_2D_RGB888_to_RGB565", "[DMA2D]") for (int i = 0; i < M2M_TRANS_TIMES; i++) { prtx = tx_buf + i * stripe_pixel_size * stripe_pixel_size * 3; prrx = rx_buf + i * stripe_pixel_size * stripe_pixel_size * 2; + + // Invalidate TX and RX buffers + esp_cache_msync((void *)prtx, stripe_pixel_size * stripe_pixel_size * 3, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, stripe_pixel_size * stripe_pixel_size * 2, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + TEST_ASSERT_EQUAL(0, rgb888_to_rgb565_and_cmp(prtx, prrx, stripe_pixel_size * stripe_pixel_size)); } @@ -601,9 +621,9 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") prrx[idx * 2 + 1] = 0xFF; } - // Writeback and invalidate the TX and RX buffers - esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); - esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); + // Writeback TX and RX buffers + esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_C2M); // DMA description preparation dma2d_link_dscr_init((uint32_t *)tx_dsc[i], NULL, (void *)prtx, @@ -643,6 +663,11 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]") for (int i = 0; i < M2M_TRANS_TIMES; i++) { prtx = tx_buf + i * 64; prrx = rx_buf + i * va * ha * 2; + + // Invalidate TX and RX buffers + esp_cache_msync((void *)prtx, 64, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + esp_cache_msync((void *)prrx, va * ha * 2, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + printf("pic:\n"); for (int idx = 0; idx < va * ha; idx++) { printf("%02X%02X ", prrx[idx * 2], prrx[idx * 2 + 1]); diff --git a/components/hal/esp32p4/include/hal/dma2d_ll.h b/components/hal/esp32p4/include/hal/dma2d_ll.h index 2edd10a35e..56209130da 100644 --- a/components/hal/esp32p4/include/hal/dma2d_ll.h +++ b/components/hal/esp32p4/include/hal/dma2d_ll.h @@ -62,8 +62,9 @@ extern "C" { #define DMA2D_LL_RX_CHANNEL_SUPPORT_RO_MASK (0U | BIT0) // RX channels that support reorder feature #define DMA2D_LL_RX_CHANNEL_SUPPORT_CSC_MASK (0U | BIT0) // RX channels that support color space conversion feature -// Any "dummy" peripheral selection ID can be used for M2M mode {4, 5, 6, 7} -#define DMA2D_LL_CHANNEL_PERIPH_M2M_FREE_ID_MASK (0xF0) +// Any "dummy" peripheral selection ID can be used for M2M mode +#define DMA2D_LL_TX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK (0xF0) +#define DMA2D_LL_RX_CHANNEL_PERIPH_M2M_AVAILABLE_ID_MASK (0xF8) // Peripheral selection ID that disconnects 2D-DMA channel from any peripherals #define DMA2D_LL_CHANNEL_PERIPH_NO_CHOICE (7) // Peripheral selection ID register field width @@ -104,17 +105,6 @@ static inline void dma2d_ll_reset_register(int group_id) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_reset_register(__VA_ARGS__) -/** - * @brief Configure 2D-DMA accessible internal and external memory start/end address (for both buffer and descriptor) - */ -static inline void dma2d_ll_set_accessible_mem_range(dma2d_dev_t *dev) -{ - dev->intr_mem_start_addr.access_intr_mem_start_addr = SOC_DIRAM_DRAM_LOW; // L2MEM region (2D-DMA indeed is able to access TCM/LP_MEM regions, but will be restricted in IDF) - dev->intr_mem_end_addr.access_intr_mem_end_addr = SOC_DIRAM_DRAM_HIGH; - dev->extr_mem_start_addr.access_extr_mem_start_addr = SOC_EXTRAM_LOW; - dev->extr_mem_end_addr.access_extr_mem_end_addr = SOC_EXTRAM_HIGH; -} - /** * @brief Enable 2D-DMA module */ @@ -230,7 +220,7 @@ static inline void dma2d_ll_rx_set_data_burst_length(dma2d_dev_t *dev, uint32_t { uint32_t sel; switch (length) { - case DMA2D_DATA_BURST_LENGTH_1: + case DMA2D_DATA_BURST_LENGTH_8: sel = 0; break; case DMA2D_DATA_BURST_LENGTH_16: @@ -384,13 +374,13 @@ static inline void dma2d_ll_rx_restart(dma2d_dev_t *dev, uint32_t channel) } /** - * @brief Enable 2D-DMA RX to return the address of current descriptor when receives error + * @brief Configure the value of the owner field written back to the 2D-DMA RX descriptor */ __attribute__((always_inline)) -static inline void dma2d_ll_rx_enable_auto_return(dma2d_dev_t *dev, uint32_t channel, bool enable) +static inline void dma2d_ll_rx_set_auto_return_owner(dma2d_dev_t *dev, uint32_t channel, int owner) { volatile dma2d_in_link_conf_chn_reg_t *reg = (volatile dma2d_in_link_conf_chn_reg_t *)DMA2D_LL_IN_CHANNEL_GET_REG_ADDR(dev, channel, in_link_conf); - reg->inlink_auto_ret_chn = enable; + reg->inlink_auto_ret_chn = owner; } /** @@ -767,7 +757,7 @@ static inline void dma2d_ll_tx_set_data_burst_length(dma2d_dev_t *dev, uint32_t { uint32_t sel; switch (length) { - case DMA2D_DATA_BURST_LENGTH_1: + case DMA2D_DATA_BURST_LENGTH_8: sel = 0; break; case DMA2D_DATA_BURST_LENGTH_16: diff --git a/components/hal/include/hal/dma2d_types.h b/components/hal/include/hal/dma2d_types.h index 9db23ba9c1..835fcf139c 100644 --- a/components/hal/include/hal/dma2d_types.h +++ b/components/hal/include/hal/dma2d_types.h @@ -120,7 +120,7 @@ typedef enum { * @brief Enumeration of 2D-DMA data burst length options */ typedef enum { - DMA2D_DATA_BURST_LENGTH_1, /*!< 2D-DMA block size: single byte */ + DMA2D_DATA_BURST_LENGTH_8, /*!< 2D-DMA block size: 8 bytes */ DMA2D_DATA_BURST_LENGTH_16, /*!< 2D-DMA block size: 16 bytes */ DMA2D_DATA_BURST_LENGTH_32, /*!< 2D-DMA block size: 32 bytes */ DMA2D_DATA_BURST_LENGTH_64, /*!< 2D-DMA block size: 64 bytes */ diff --git a/components/soc/esp32p4/include/soc/dma2d_channel.h b/components/soc/esp32p4/include/soc/dma2d_channel.h index ababc5e2c5..f960fb1c4a 100644 --- a/components/soc/esp32p4/include/soc/dma2d_channel.h +++ b/components/soc/esp32p4/include/soc/dma2d_channel.h @@ -10,10 +10,10 @@ #define SOC_DMA2D_TRIG_PERIPH_JPEG_RX (0) #define SOC_DMA2D_TRIG_PERIPH_PPA_SR_RX (1) #define SOC_DMA2D_TRIG_PERIPH_PPA_BLEND_RX (2) -#define SOC_DMA2D_TRIG_PERIPH_M2M_RX (-1) // Any value of 3 ~ 7, but TX and RX needs the same ID for M2M +#define SOC_DMA2D_TRIG_PERIPH_M2M_RX (-1) // Any value of 3 ~ 7, TX and RX do not have to use same ID value for M2M #define SOC_DMA2D_TRIG_PERIPH_JPEG_TX (0) #define SOC_DMA2D_TRIG_PERIPH_PPA_SR_TX (1) #define SOC_DMA2D_TRIG_PERIPH_PPA_BLEND_FG_TX (2) #define SOC_DMA2D_TRIG_PERIPH_PPA_BLEND_BG_TX (3) -#define SOC_DMA2D_TRIG_PERIPH_M2M_TX (-1) // Any value of 4 ~ 7, but TX and RX needs the same ID for M2M +#define SOC_DMA2D_TRIG_PERIPH_M2M_TX (-1) // Any value of 4 ~ 7, TX and RX do not have to use same ID value for M2M diff --git a/components/soc/esp32p4/include/soc/dma2d_reg.h b/components/soc/esp32p4/include/soc/dma2d_reg.h index 8a6d06f6a9..5a9acb85ae 100644 --- a/components/soc/esp32p4/include/soc/dma2d_reg.h +++ b/components/soc/esp32p4/include/soc/dma2d_reg.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 */ @@ -63,7 +63,7 @@ extern "C" { #define DMA2D_OUT_LOOP_TEST_CH0_V 0x00000001U #define DMA2D_OUT_LOOP_TEST_CH0_S 5 /** DMA2D_OUT_MEM_BURST_LENGTH_CH0 : R/W; bitpos: [8:6]; default: 0; - * Block size of Tx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Tx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ #define DMA2D_OUT_MEM_BURST_LENGTH_CH0 0x00000007U @@ -1098,7 +1098,7 @@ extern "C" { #define DMA2D_OUT_LOOP_TEST_CH1_V 0x00000001U #define DMA2D_OUT_LOOP_TEST_CH1_S 5 /** DMA2D_OUT_MEM_BURST_LENGTH_CH1 : R/W; bitpos: [8:6]; default: 0; - * Block size of Tx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Tx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ #define DMA2D_OUT_MEM_BURST_LENGTH_CH1 0x00000007U @@ -2106,7 +2106,7 @@ extern "C" { #define DMA2D_OUT_LOOP_TEST_CH2_V 0x00000001U #define DMA2D_OUT_LOOP_TEST_CH2_S 5 /** DMA2D_OUT_MEM_BURST_LENGTH_CH2 : R/W; bitpos: [8:6]; default: 0; - * Block size of Tx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Tx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ #define DMA2D_OUT_MEM_BURST_LENGTH_CH2 0x00000007U @@ -3105,7 +3105,7 @@ extern "C" { #define DMA2D_IN_LOOP_TEST_CH0_V 0x00000001U #define DMA2D_IN_LOOP_TEST_CH0_S 5 /** DMA2D_IN_MEM_BURST_LENGTH_CH0 : R/W; bitpos: [8:6]; default: 0; - * Block size of Rx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Rx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ #define DMA2D_IN_MEM_BURST_LENGTH_CH0 0x00000007U @@ -3732,8 +3732,8 @@ extern "C" { */ #define DMA2D_IN_LINK_CONF_CH0_REG (DR_REG_DMA2D_BASE + 0x51c) /** DMA2D_INLINK_AUTO_RET_CH0 : R/W; bitpos: [20]; default: 1; - * Set this bit to return to current inlink descriptor's address, when there are some - * errors in current receiving data. + * Configure the value of the owner field written back to the inlink descriptor. + * 1: Write back 1. 0: Write back 0. */ #define DMA2D_INLINK_AUTO_RET_CH0 (BIT(20)) #define DMA2D_INLINK_AUTO_RET_CH0_M (DMA2D_INLINK_AUTO_RET_CH0_V << DMA2D_INLINK_AUTO_RET_CH0_S) @@ -4168,7 +4168,7 @@ extern "C" { #define DMA2D_IN_LOOP_TEST_CH1_V 0x00000001U #define DMA2D_IN_LOOP_TEST_CH1_S 5 /** DMA2D_IN_MEM_BURST_LENGTH_CH1 : R/W; bitpos: [8:6]; default: 0; - * Block size of Rx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Rx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ #define DMA2D_IN_MEM_BURST_LENGTH_CH1 0x00000007U @@ -4795,8 +4795,8 @@ extern "C" { */ #define DMA2D_IN_LINK_CONF_CH1_REG (DR_REG_DMA2D_BASE + 0x61c) /** DMA2D_INLINK_AUTO_RET_CH1 : R/W; bitpos: [20]; default: 1; - * Set this bit to return to current inlink descriptor's address, when there are some - * errors in current receiving data. + * Configure the value of the owner field written back to the inlink descriptor. + * 1: Write back 1. 0: Write back 0. */ #define DMA2D_INLINK_AUTO_RET_CH1 (BIT(20)) #define DMA2D_INLINK_AUTO_RET_CH1_M (DMA2D_INLINK_AUTO_RET_CH1_V << DMA2D_INLINK_AUTO_RET_CH1_S) diff --git a/components/soc/esp32p4/include/soc/dma2d_struct.h b/components/soc/esp32p4/include/soc/dma2d_struct.h index bd765b5c88..03a51a6743 100644 --- a/components/soc/esp32p4/include/soc/dma2d_struct.h +++ b/components/soc/esp32p4/include/soc/dma2d_struct.h @@ -46,7 +46,7 @@ typedef union { */ uint32_t out_loop_test_chn:1; /** out_mem_burst_length_chn : R/W; bitpos: [8:6]; default: 0; - * Block size of Tx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Tx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ uint32_t out_mem_burst_length_chn:3; @@ -762,7 +762,7 @@ typedef union { */ uint32_t in_loop_test_chn:1; /** in_mem_burst_length_chn : R/W; bitpos: [8:6]; default: 0; - * Block size of Rx channel 0. 0: single 1: 16 bytes 2: 32 bytes 3: 64 + * Block size of Rx channel 0. 0: 8 bytes 1: 16 bytes 2: 32 bytes 3: 64 * bytes 4: 128 bytes */ uint32_t in_mem_burst_length_chn:3; @@ -1179,8 +1179,8 @@ typedef union { struct { uint32_t reserved_0:20; /** inlink_auto_ret_chn : R/W; bitpos: [20]; default: 1; - * Set this bit to return to current inlink descriptor's address, when there are some - * errors in current receiving data. + * Configure the value of the owner field written back to the inlink descriptor. + * 1: Write back 1. 0: Write back 0. */ uint32_t inlink_auto_ret_chn:1; /** inlink_stop_chn : R/W/SC; bitpos: [21]; default: 0;