feat(gdma_link): support to select final node link type

This commit is contained in:
laokaiyao
2025-07-22 14:39:32 +08:00
parent 7d8d166f83
commit ce84d734ef
11 changed files with 46 additions and 29 deletions
@@ -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);
+1 -1
View File
@@ -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,
}
};
+2 -2
View File
@@ -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]);
@@ -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
}
}
};
@@ -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
}
}
};
+13 -4
View File
@@ -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;
@@ -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
@@ -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));
@@ -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);
@@ -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);
+2 -2
View File
@@ -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,
},
};