refactor(gdma): move buffer aligment to buffer mount config

This commit is contained in:
Chen Jichang
2025-10-14 17:24:24 +08:00
parent bc4fee11b5
commit 3d1a110f38
10 changed files with 56 additions and 36 deletions
@@ -216,7 +216,6 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *
// allocate gdma TX link
gdma_link_list_config_t tx_link_cfg = {
.buffer_alignment = 1, // CP_DMA doesn't have alignment requirement for internal memory
.item_alignment = 4, // CP_DMA requires 4 bytes alignment for each descriptor
.num_items = num_dma_nodes,
.flags = {
@@ -229,6 +228,7 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *
gdma_buffer_mount_config_t tx_buf_mount_config[1] = {
[0] = {
.buffer = src,
.buffer_alignment = 1, // CP_DMA doesn't have alignment requirement for internal memory
.length = n,
.flags = {
.mark_eof = true, // mark the last item as EOF, so the RX channel can also received an EOF list item
@@ -240,7 +240,6 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *
// allocate gdma RX link
gdma_link_list_config_t rx_link_cfg = {
.buffer_alignment = 1, // CP_DMA doesn't have alignment requirement for internal memory
.item_alignment = 4, // CP_DMA requires 4 bytes alignment for each descriptor
.num_items = num_dma_nodes,
.flags = {
@@ -253,6 +252,7 @@ static esp_err_t mcp_cpdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *
gdma_buffer_mount_config_t rx_buf_mount_config[1] = {
[0] = {
.buffer = dst,
.buffer_alignment = 1, // CP_DMA doesn't have alignment requirement for internal memory
.length = n,
.flags = {
.mark_eof = false, // EOF is set by TX side
@@ -348,7 +348,6 @@ static esp_err_t mcp_gdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *s
buffer_alignment = esp_ptr_internal(src) ? mcp_gdma->tx_int_mem_alignment : mcp_gdma->tx_ext_mem_alignment;
num_dma_nodes = esp_dma_calculate_node_count(n, buffer_alignment, MCP_DMA_DESCRIPTOR_BUFFER_MAX_SIZE);
gdma_link_list_config_t tx_link_cfg = {
.buffer_alignment = buffer_alignment,
.item_alignment = dma_link_item_alignment,
.num_items = num_dma_nodes,
.flags = {
@@ -361,6 +360,7 @@ static esp_err_t mcp_gdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *s
gdma_buffer_mount_config_t tx_buf_mount_config[1] = {
[0] = {
.buffer = src,
.buffer_alignment = buffer_alignment,
.length = n,
.flags = {
.mark_eof = true, // mark the last item as EOF, so the RX channel can also received an EOF list item
@@ -388,7 +388,6 @@ static esp_err_t mcp_gdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *s
buffer_alignment = esp_ptr_internal(dst) ? mcp_gdma->rx_int_mem_alignment : mcp_gdma->rx_ext_mem_alignment;
num_dma_nodes = esp_dma_calculate_node_count(n, buffer_alignment, MCP_DMA_DESCRIPTOR_BUFFER_MAX_SIZE);
gdma_link_list_config_t rx_link_cfg = {
.buffer_alignment = buffer_alignment,
.item_alignment = dma_link_item_alignment,
.num_items = num_dma_nodes + 3, // add 3 extra items for the cache aligned buffers
.flags = {
@@ -405,6 +404,7 @@ static esp_err_t mcp_gdma_memcpy(async_memcpy_context_t *ctx, void *dst, void *s
gdma_buffer_mount_config_t rx_buf_mount_config[3] = {0};
for (int i = 0; i < 3; i++) {
rx_buf_mount_config[i].buffer = trans->rx_buf_array.aligned_buffer[i].aligned_buffer;
rx_buf_mount_config[i].buffer_alignment = buffer_alignment;
rx_buf_mount_config[i].length = trans->rx_buf_array.aligned_buffer[i].length;
}
gdma_link_mount_buffers(trans->rx_link_list, 0, rx_buf_mount_config, 3, NULL);
+28 -16
View File
@@ -51,7 +51,6 @@ struct gdma_link_list_item_t {
typedef struct gdma_link_list_t {
uint32_t num_items; // number of items in the link list
size_t item_size; // size of each item
size_t buffer_alignment; // Alignment of each buffer
uint8_t *items; // pointer to the link list items
uint8_t *items_nc; // pointer to the link list items, non-cached
struct {
@@ -66,11 +65,6 @@ esp_err_t gdma_new_link_list(const gdma_link_list_config_t *config, gdma_link_li
gdma_link_list_t *list = NULL;
ESP_RETURN_ON_FALSE(config && ret_list, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(config->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid number of items");
size_t buffer_alignment = config->buffer_alignment;
if (buffer_alignment == 0) {
buffer_alignment = 1;
}
ESP_RETURN_ON_FALSE((buffer_alignment & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "invalid buffer alignment: %zu", buffer_alignment);
// the link list container is allocated from internal memory
list = heap_caps_calloc(1, sizeof(gdma_link_list_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -109,7 +103,6 @@ esp_err_t gdma_new_link_list(const gdma_link_list_config_t *config, gdma_link_li
list->items = items;
// calculate the non-cached address
list->items_nc = GDMA_CACHE_ADDR_TO_NON_CACHE_ADDR(items);
list->buffer_alignment = buffer_alignment;
list->flags.check_owner = config->flags.check_owner;
ESP_LOGD(TAG, "new link list @%p, items @%p", list, items);
@@ -137,13 +130,13 @@ esp_err_t gdma_del_link_list(gdma_link_list_handle_t list)
esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_index, const gdma_buffer_mount_config_t *buf_config_array, size_t num_buf, int *end_item_index)
{
ESP_RETURN_ON_FALSE(list && buf_config_array && num_buf, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
size_t buffer_alignment = list->buffer_alignment;
if(!list || !buf_config_array || !num_buf) {
return ESP_ERR_INVALID_ARG;
}
size_t item_size = list->item_size;
uint32_t list_item_capacity = list->num_items;
// ensure the start_item_index is between 0 and `list_item_capacity - 1`
start_item_index = (start_item_index % list_item_capacity + list_item_capacity) % list_item_capacity;
size_t max_buffer_mount_length = ALIGN_DOWN(GDMA_MAX_BUFFER_SIZE_PER_LINK_ITEM, buffer_alignment);
uint32_t begin_item_idx = start_item_index;
gdma_link_list_item_t *lli_nc = NULL;
@@ -165,13 +158,19 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_i
const gdma_buffer_mount_config_t *config = &buf_config_array[bi];
uint8_t *buf = (uint8_t *)config->buffer;
size_t len = config->length;
size_t buffer_alignment = config->buffer_alignment;
if (buffer_alignment == 0) {
buffer_alignment = 1;
}
// check the buffer alignment
ESP_RETURN_ON_FALSE_ISR((buffer_alignment & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "invalid buffer alignment: %"PRIu32"", buffer_alignment);
size_t max_buffer_mount_length = ALIGN_DOWN(GDMA_MAX_BUFFER_SIZE_PER_LINK_ITEM, buffer_alignment);
if (!config->flags.bypass_buffer_align_check) {
ESP_RETURN_ON_FALSE(((uintptr_t)buf & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer not aligned to %zu", buffer_alignment);
ESP_RETURN_ON_FALSE_ISR(((uintptr_t)buf & (buffer_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer not aligned to %"PRIu32"", buffer_alignment);
}
uint32_t num_items_need = (len + max_buffer_mount_length - 1) / max_buffer_mount_length;
// check if there are enough link list items
ESP_RETURN_ON_FALSE((begin_item_idx + num_items_need) <= (start_item_index + num_items_avail), ESP_ERR_INVALID_ARG, TAG, "no more space for buffer mounting");
ESP_RETURN_ON_FALSE_ISR((begin_item_idx + num_items_need) <= (start_item_index + num_items_avail), ESP_ERR_INVALID_ARG, TAG, "no more space for buffer mounting");
begin_item_idx += num_items_need;
}
@@ -184,6 +183,11 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_i
const gdma_buffer_mount_config_t *config = &buf_config_array[bi];
uint8_t *buf = (uint8_t *)config->buffer;
size_t len = config->length;
size_t buffer_alignment = config->buffer_alignment;
if (buffer_alignment == 0) {
buffer_alignment = 1;
}
size_t max_buffer_mount_length = ALIGN_DOWN(GDMA_MAX_BUFFER_SIZE_PER_LINK_ITEM, buffer_alignment);
// skip zero-length buffer
if (len == 0 || buf == NULL) {
continue;
@@ -221,13 +225,17 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_i
uintptr_t gdma_link_get_head_addr(gdma_link_list_handle_t list)
{
ESP_RETURN_ON_FALSE(list, 0, TAG, "invalid argument");
if (!list) {
return 0;
}
return (uintptr_t)(list->items);
}
esp_err_t gdma_link_concat(gdma_link_list_handle_t first_link, int first_link_item_index, gdma_link_list_handle_t second_link, int second_link_item_index)
{
ESP_RETURN_ON_FALSE(first_link && second_link, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
if(!(first_link && second_link)) {
return ESP_ERR_INVALID_ARG;
}
gdma_link_list_item_t *lli_nc = NULL;
// ensure the first_link_item_index is between 0 and `num_items - 1`
int num_items = first_link->num_items;
@@ -243,7 +251,9 @@ esp_err_t gdma_link_concat(gdma_link_list_handle_t first_link, int first_link_it
esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t owner)
{
ESP_RETURN_ON_FALSE_ISR(list, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
if (!list) {
return ESP_ERR_INVALID_ARG;
}
int num_items = list->num_items;
// ensure the item_index is between 0 and `num_items - 1`
item_index = (item_index % num_items + num_items) % num_items;
@@ -254,7 +264,9 @@ esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma
esp_err_t gdma_link_get_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t *owner)
{
ESP_RETURN_ON_FALSE_ISR(list && owner, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
if(!list || !owner) {
return ESP_ERR_INVALID_ARG;
}
int num_items = list->num_items;
// ensure the item_index is between 0 and `num_items - 1`
item_index = (item_index % num_items + num_items) % num_items;
@@ -24,7 +24,6 @@ typedef struct gdma_link_list_t *gdma_link_list_handle_t;
typedef struct {
uint32_t num_items; //!< Number of nodes in the link list
size_t item_alignment; //!< Alignment of each list item required by the DMA. By default, it's 4 bytes alignment.
size_t buffer_alignment; //!< Alignment of each buffer required by the DMA. By default, it's 1 byte alignment.
struct gdma_link_list_flags {
uint32_t items_in_ext_mem: 1; //!< Whether the link list items are allocated from external memory
uint32_t check_owner: 1; //!< Whether the link list is responsible for checking the ownership when mount data buffers
@@ -62,6 +61,7 @@ esp_err_t gdma_del_link_list(gdma_link_list_handle_t list);
*/
typedef struct {
void *buffer; //!< Buffer to be mounted to the DMA link list
size_t buffer_alignment; //!< Alignment of the buffer. By default, it's 1 byte alignment.
size_t length; //!< Number of bytes that are expected to be transferred
struct gdma_buffer_mount_flags {
uint32_t mark_eof: 1; /*!< Whether to mark the list item as the "EOF" item.
@@ -152,7 +152,7 @@ TEST_CASE("GDMA channel allocation", "[GDMA]")
}
static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan,
gdma_link_list_handle_t *tx_link_list, gdma_link_list_handle_t *rx_link_list, size_t sram_alignment, bool dma_link_in_ext_mem)
gdma_link_list_handle_t *tx_link_list, gdma_link_list_handle_t *rx_link_list, bool dma_link_in_ext_mem)
{
gdma_strategy_config_t strategy = {
@@ -172,7 +172,6 @@ static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_chann
// create DMA link list for TX channel (a singly link with 3 nodes)
gdma_link_list_config_t tx_link_list_config = {
.buffer_alignment = 1,
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
.num_items = 3,
.flags = {
@@ -183,7 +182,6 @@ static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_chann
TEST_ESP_OK(gdma_new_link_list(&tx_link_list_config, tx_link_list));
// create DMA link list for RX channel
gdma_link_list_config_t rx_link_list_config = {
.buffer_alignment = sram_alignment, // RX buffer should be aligned to the cache line size, because we will do cache invalidate later
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
.num_items = 5,
.flags = {
@@ -214,7 +212,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
gdma_link_list_handle_t tx_link_list = NULL;
gdma_link_list_handle_t rx_link_list = NULL;
test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, sram_alignment, dma_link_in_ext_mem);
test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, dma_link_in_ext_mem);
// allocate the source buffer from SRAM
uint8_t *src_data = heap_caps_calloc(1, 128, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -249,10 +247,12 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
gdma_buffer_mount_config_t tx_buf_mount_config[] = {
[0] = {
.buffer = src_data,
.buffer_alignment = 1,
.length = 64,
},
[1] = {
.buffer = src_data + 64,
.buffer_alignment = 1,
.length = 64,
#if !SOC_DMA_CAN_ACCESS_FLASH
.flags = {
@@ -264,6 +264,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
#if SOC_DMA_CAN_ACCESS_FLASH
[2] = {
.buffer = (void *)src_string,
.buffer_alignment = 1,
.length = src_string_len,
.flags = {
.mark_eof = true,
@@ -276,6 +277,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
gdma_buffer_mount_config_t rx_buf_mount_config = {
.buffer = dst_data,
.buffer_alignment = sram_alignment, // RX buffer should be aligned to the cache line size, because we will do cache invalidate later
.length = 256,
};
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL));
@@ -394,7 +396,7 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_
gdma_link_list_handle_t tx_link_list = NULL;
gdma_link_list_handle_t rx_link_list = NULL;
test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, sram_alignment, false);
test_gdma_config_link_list(tx_chan, rx_chan, &tx_link_list, &rx_link_list, false);
// prepare the source data
for (int i = 0; i < data_length; i++) {
@@ -408,6 +410,7 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_
gdma_buffer_mount_config_t tx_buf_mount_config[] = {
[0] = {
.buffer = src_data,
.buffer_alignment = 1,
.length = data_length,
.flags = {
.mark_eof = true,
@@ -423,6 +426,7 @@ static void test_gdma_m2m_unaligned_buffer_test(uint8_t *dst_data, uint8_t *src_
TEST_ESP_OK(esp_dma_split_rx_buffer_to_cache_aligned(dst_data + offset_len, data_length, &align_array, &stash_buffer));
for (int i = 0; i < 3; i++) {
rx_aligned_buf_mount_config[i].buffer = align_array.aligned_buffer[i].aligned_buffer;
rx_aligned_buf_mount_config[i].buffer_alignment = sram_alignment;
rx_aligned_buf_mount_config[i].length = align_array.aligned_buffer[i].length;
}
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, rx_aligned_buf_mount_config, 3, NULL));