diff --git a/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c index 1fe81e11cb..b69b8e8405 100644 --- a/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c @@ -237,7 +237,7 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s .length = length_bytes_in, .flags = { .mark_eof = true, - .mark_final = true, + .mark_final = GDMA_FINAL_LINK_TO_NULL, } }; gdma_link_mount_buffers(bsl->tx_link_list, 0, &in_buf_mount_config, 1, NULL); @@ -247,7 +247,7 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s .length = length_bytes_out, .flags = { .mark_eof = false, - .mark_final = true, + .mark_final = GDMA_FINAL_LINK_TO_NULL, } }; gdma_link_mount_buffers(bsl->rx_link_list, 0, &out_buf_mount_config, 1, NULL); diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index baf1d295c7..86d6c22afb 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -481,7 +481,7 @@ static void parlio_mount_buffer(parlio_tx_unit_t *tx_unit, parlio_tx_trans_desc_ .flags = { // if transmission is loop, we don't need to generate the EOF for 1-bit data width, DIG-559 .mark_eof = tx_unit->data_width == 1 ? !t->flags.loop_transmission : true, - .mark_final = !t->flags.loop_transmission, + .mark_final = !t->flags.loop_transmission ? GDMA_FINAL_LINK_TO_NULL : GDMA_FINAL_LINK_TO_DEFAULT, } }; diff --git a/components/esp_driver_uart/src/uhci.c b/components/esp_driver_uart/src/uhci.c index b0a40a6a23..e390d047c9 100644 --- a/components/esp_driver_uart/src/uhci.c +++ b/components/esp_driver_uart/src/uhci.c @@ -269,7 +269,7 @@ static void uhci_do_transmit(uhci_controller_handle_t uhci_ctrl, uhci_transactio .length = trans->buffer_size, .flags = { .mark_eof = true, - .mark_final = true, + .mark_final = GDMA_FINAL_LINK_TO_NULL, } }; @@ -332,7 +332,7 @@ esp_err_t uhci_receive(uhci_controller_handle_t uhci_ctrl, uint8_t *read_buffer, .buffer_alignment = buffer_alignment, .length = uhci_ctrl->rx_dir.buffer_size_per_desc_node[i], .flags = { - .mark_final = false, + .mark_final = GDMA_FINAL_LINK_TO_DEFAULT, } }; ESP_LOGD(TAG, "The DMA node %d has %d byte", i, uhci_ctrl->rx_dir.buffer_size_per_desc_node[i]); diff --git a/components/esp_hw_support/dma/async_memcpy_cp_dma.c b/components/esp_hw_support/dma/async_memcpy_cp_dma.c index add2cec2e5..3e36e6b997 100644 --- a/components/esp_hw_support/dma/async_memcpy_cp_dma.c +++ b/components/esp_hw_support/dma/async_memcpy_cp_dma.c @@ -232,7 +232,7 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void * .length = n, .flags = { .mark_eof = true, // mark the last item as EOF, so the RX channel can also received an EOF list item - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } } }; @@ -256,7 +256,7 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void * .length = n, .flags = { .mark_eof = false, // EOF is set by TX side - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } } }; diff --git a/components/esp_hw_support/dma/async_memcpy_gdma.c b/components/esp_hw_support/dma/async_memcpy_gdma.c index a6e1047dd4..f53b0aaf48 100644 --- a/components/esp_hw_support/dma/async_memcpy_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_gdma.c @@ -365,7 +365,7 @@ static esp_err_t mcp_gdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *s .length = n, .flags = { .mark_eof = true, // mark the last item as EOF, so the RX channel can also received an EOF list item - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } } }; diff --git a/components/esp_hw_support/dma/gdma_link.c b/components/esp_hw_support/dma/gdma_link.c index 1011abb224..41b29a16e4 100644 --- a/components/esp_hw_support/dma/gdma_link.c +++ b/components/esp_hw_support/dma/gdma_link.c @@ -204,10 +204,19 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_i // mark the EOF node lli_nc->dw0.suc_eof = (config->flags.mark_eof == 1) && (i == num_items_need - 1); // mark the final node - if ((config->flags.mark_final == 1) && (i == num_items_need - 1)) { - lli_nc->next = NULL; - } else { - lli_nc->next = (gdma_link_list_item_t *)(list->items + (i + begin_item_idx + 1) % list_item_capacity * item_size); + switch (config->flags.mark_final) { + case GDMA_FINAL_LINK_TO_NULL: + lli_nc->next = NULL; + break; + case GDMA_FINAL_LINK_TO_HEAD: + lli_nc->next = (gdma_link_list_item_t *)(list->items); + break; + case GDMA_FINAL_LINK_TO_START: + lli_nc->next = (gdma_link_list_item_t *)(list->items + begin_item_idx * item_size); + break; + default: + lli_nc->next = (gdma_link_list_item_t *)(list->items + (i + begin_item_idx + 1) % list_item_capacity * item_size); + break; } lli_nc->dw0.owner = GDMA_LLI_OWNER_DMA; buf += max_buffer_mount_length; diff --git a/components/esp_hw_support/dma/include/esp_private/gdma_link.h b/components/esp_hw_support/dma/include/esp_private/gdma_link.h index 6bccb4c802..3e3d4be22c 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma_link.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma_link.h @@ -56,6 +56,17 @@ esp_err_t gdma_new_link_list(const gdma_link_list_config_t *config, gdma_link_li */ esp_err_t gdma_del_link_list(gdma_link_list_handle_t list); +/** + * @brief Types for the next node of the final item in the DMA link list + * + */ +typedef enum { + GDMA_FINAL_LINK_TO_DEFAULT = 0, /*!< The next node is linked to the default next item in the link list */ + GDMA_FINAL_LINK_TO_NULL = 1, /*!< The next node is linked to the final item in the link list */ + GDMA_FINAL_LINK_TO_HEAD = 2, /*!< The next node is linked to the head item in the link list */ + GDMA_FINAL_LINK_TO_START = 3, /*!< The next node is linked to the start item in the link list */ +} gdma_final_node_link_type_t; + /** * @brief DMA buffer mount configurations */ @@ -68,10 +79,7 @@ typedef struct { Note, an "EOF" descriptor can be interrupted differently by peripheral. But it doesn't mean to terminate a DMA link (use `mark_final` instead). EOF link list item can also trigger an interrupt. */ - uint32_t mark_final: 1; /*!< Whether to terminate the DMA link list at this item. - Note, DMA engine will stop at this item and trigger an interrupt. - If `mark_final` is not set, this list item will point to the next item, and - wrap around to the head item if it's the last one in the list. */ + gdma_final_node_link_type_t mark_final: 2; /*!< The next node of the final item in the link list */ uint32_t bypass_buffer_align_check: 1; /*!< Whether to bypass the buffer alignment check. Only enable it when you know what you are doing. */ } flags; //!< Flags for buffer mount configurations diff --git a/components/esp_hw_support/test_apps/dma/main/test_gdma.c b/components/esp_hw_support/test_apps/dma/main/test_gdma.c index ce97d0a0b4..bb487b2a2b 100644 --- a/components/esp_hw_support/test_apps/dma/main/test_gdma.c +++ b/components/esp_hw_support/test_apps/dma/main/test_gdma.c @@ -278,7 +278,7 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe #if !SOC_DMA_CAN_ACCESS_FLASH .flags = { .mark_eof = true, - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } #endif }, @@ -289,7 +289,7 @@ static void test_gdma_m2m_transaction(gdma_channel_handle_t tx_chan, gdma_channe .length = src_string_len, .flags = { .mark_eof = true, - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } }, #endif @@ -448,7 +448,7 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_ .length = data_length, .flags = { .mark_eof = true, - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } } }; @@ -609,7 +609,7 @@ TEST_CASE("GDMA M2M Unaligned RX Buffer Test", "[GDMA][M2M]") .length = COPY_SIZE, .flags = { .mark_eof = true, - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } }; TEST_ESP_OK(gdma_link_mount_buffers(tx_link_list, 0, &tx_buf_mount_config, 1, NULL)); @@ -619,7 +619,7 @@ TEST_CASE("GDMA M2M Unaligned RX Buffer Test", "[GDMA][M2M]") .buffer_alignment = 32, .length = COPY_SIZE, .flags = { - .mark_final = true, // using singly list, so terminate the link here + .mark_final = GDMA_FINAL_LINK_TO_NULL, // using singly list, so terminate the link here } }; TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL)); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c index bfd15c0d29..83c6918075 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c @@ -523,7 +523,7 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons gdma_buffer_mount_config_t mount_config = { .flags = { .mark_eof = true, - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; @@ -599,7 +599,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons gdma_buffer_mount_config_t mount_config = { .flags = { .mark_eof = true, - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; @@ -724,7 +724,7 @@ static void i2s_lcd_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus) .length = 4, .flags = { .mark_eof = true, // mark the "EOF" flag to trigger I2S EOF interrupt - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL); @@ -811,7 +811,7 @@ static IRAM_ATTR void i2s_lcd_default_isr_handler(void *args) .length = trans_desc->data_length, .flags = { .mark_eof = true, - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index f0ffb1b1a4..1977f6ab0f 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -500,7 +500,7 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons .length = trans_desc->data_length, .flags = { .mark_eof = true, - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL); @@ -821,7 +821,7 @@ IRAM_ATTR static void i80_lcd_default_isr_handler(void *args) .length = trans_desc->data_length, .flags = { .mark_eof = true, - .mark_final = true, // singly link list, mark final descriptor + .mark_final = GDMA_FINAL_LINK_TO_NULL, // singly link list, mark final descriptor } }; gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL); diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 9fd7e91e31..6d3ed816b4 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -1013,7 +1013,7 @@ static esp_err_t lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *rgb_panel) mount_cfgs[i].buffer = rgb_panel->bounce_buffer[i]; mount_cfgs[i].buffer_alignment = buffer_alignment; mount_cfgs[i].length = rgb_panel->bb_size; - mount_cfgs[i].flags.mark_eof = true; // we use the DMA EOF interrupt to copy the frame buffer (partially) to the bounce buffer + mount_cfgs[i].flags.mark_eof = GDMA_FINAL_LINK_TO_NULL; // we use the DMA EOF interrupt to copy the frame buffer (partially) to the bounce buffer } ESP_RETURN_ON_ERROR(gdma_link_mount_buffers(rgb_panel->dma_bb_link, 0, mount_cfgs, RGB_LCD_PANEL_BOUNCE_BUF_NUM, NULL), TAG, "mount DMA bounce buffers failed"); @@ -1052,7 +1052,7 @@ static esp_err_t lcd_rgb_panel_init_trans_link(esp_rgb_panel_t *rgb_panel) gdma_buffer_mount_config_t mount_cfg = { .length = rgb_panel->fb_size, .flags = { - .mark_final = rgb_panel->flags.stream_mode ? false : true, + .mark_final = rgb_panel->flags.stream_mode ? GDMA_FINAL_LINK_TO_DEFAULT : GDMA_FINAL_LINK_TO_NULL, .mark_eof = true, }, };