Merge branch 'fix/fix_gdma_crc_stuck_with_large_input_v6.0' into 'release/v6.0'

fix(gdma): fix crc stuck with large input (v6.0)

See merge request espressif/esp-idf!49361
This commit is contained in:
morris
2026-06-30 11:03:34 +08:00

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -33,33 +33,43 @@ static test_crc_case_t crc_test_cases[] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.expected_result = 0x1C,
.expected_result = 0x08,
},
[1] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.reverse_data_mask = true, // refin = true
.expected_result = 0xB9,
.expected_result = 0xCE,
},
// CRC16, x^16+x^12+x^5+1
[2] = {
.crc_bit_width = 16,
.init_value = 0xFFFF,
.poly_hex = 0x1021,
.expected_result = 0x7563,
.expected_result = 0x0ED7,
},
// CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
[3] = {
.crc_bit_width = 32,
.init_value = 0xFFFFFFFF,
.poly_hex = 0x04C11DB7,
.expected_result = 0x069A43E6,
.expected_result = 0x6D9BD7D5,
}
};
static bool test_gdma_crc_calculation_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;
SemaphoreHandle_t semaphore = (SemaphoreHandle_t)user_data;
if (event_data->flags.normal_eof) {
xSemaphoreGiveFromISR(semaphore, &high_task_wakeup);
}
return high_task_wakeup;
}
// CRC online: https://www.lddgo.net/en/encrypt/crc
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm)
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan, int test_num_crc_algorithm)
{
// Note, burst size should be at least 16 when accessing encrypted external memory
gdma_transfer_config_t transfer_cfg = {
@@ -67,30 +77,41 @@ static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_nu
.access_ext_mem = true,
};
TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_cfg));
TEST_ESP_OK(gdma_config_transfer(rx_chan, &transfer_cfg));
SemaphoreHandle_t semaphore = xSemaphoreCreateBinary();
uint32_t crc_result = 0;
static const char test_input_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_ALIGNMENT))) = "GDMACRC::TEST::X";
static const char test_input_string[] __attribute__((aligned(SOC_MEMSPI_ENCRYPTION_ALIGNMENT))) = "GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::GDMACRC::TEST::LONGSTRING::REPEAT::END!";
size_t input_data_size = strlen(test_input_string);
TEST_ASSERT_EQUAL((uintptr_t)test_input_string % SOC_MEMSPI_ENCRYPTION_ALIGNMENT, 0);
// this test case also test the GDMA can fetch data from MSPI Flash
TEST_ASSERT_TRUE(esp_ptr_in_drom(test_input_string));
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
uint8_t *rx_buffer = NULL;
rx_buffer = heap_caps_calloc(1, strlen(test_input_string), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(rx_buffer);
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
// get a free DMA trigger ID
uint32_t free_m2m_id_mask = 0;
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
TEST_ESP_OK(gdma_connect(rx_chan, m2m_trigger));
gdma_tx_event_callbacks_t tx_cbs = {
.on_trans_eof = test_gdma_crc_calculation_callback,
};
TEST_ESP_OK(gdma_register_tx_event_callbacks(tx_chan, &tx_cbs, semaphore));
size_t sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
size_t alignment = MAX(sram_cache_line_size, 8);
dma_descriptor_align8_t *tx_descs = heap_caps_aligned_calloc(alignment, 1, sizeof(dma_descriptor_align8_t),
MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(tx_descs);
tx_descs->buffer = (void *)test_input_string;
tx_descs->dw0.size = input_data_size + 1; // +1 for '\0'
tx_descs->dw0.length = input_data_size;
@@ -98,9 +119,18 @@ static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_nu
tx_descs->dw0.suc_eof = 1;
tx_descs->next = NULL;
dma_descriptor_align8_t *rx_descs = heap_caps_aligned_calloc(alignment, 1, sizeof(dma_descriptor_align8_t),
MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(rx_descs);
rx_descs->buffer = (void *)rx_buffer;
rx_descs->dw0.size = input_data_size;
rx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
rx_descs->next = NULL;
if (sram_cache_line_size) {
// do write-back for the buffer because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)tx_descs, sizeof(dma_descriptor_align8_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED));
TEST_ESP_OK(esp_cache_msync((void *)rx_descs, sizeof(dma_descriptor_align8_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED));
}
for (int i = 0; i < test_num_crc_algorithm; i++) {
@@ -111,34 +141,42 @@ static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_nu
.reverse_data_mask = crc_test_cases[i].reverse_data_mask,
};
TEST_ESP_OK(gdma_config_crc_calculator(tx_chan, &crc_config));
TEST_ESP_OK(gdma_reset(rx_chan));
TEST_ESP_OK(gdma_start(rx_chan, (intptr_t)rx_descs));
TEST_ESP_OK(gdma_reset(tx_chan));
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
// simply wait for the transfer done
vTaskDelay(pdMS_TO_TICKS(100));
// wait for the transfer done
xSemaphoreTake(semaphore, pdMS_TO_TICKS(100));
TEST_ESP_OK(gdma_crc_get_result(tx_chan, &crc_result));
printf("CRC Result: 0x%"PRIx32"\r\n", crc_result);
TEST_ASSERT_EQUAL(crc_test_cases[i].expected_result, crc_result);
}
free(tx_descs);
free(rx_descs);
free(rx_buffer);
vSemaphoreDelete(semaphore);
}
TEST_CASE("GDMA CRC Calculation", "[GDMA][CRC]")
{
gdma_channel_handle_t tx_chan = NULL;
gdma_channel_handle_t rx_chan = NULL;
gdma_channel_alloc_config_t tx_chan_alloc_config = {
};
#if SOC_HAS(AHB_GDMA)
printf("Test CRC calculation for AHB GDMA\r\n");
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan, NULL));
test_gdma_crc_calculation(tx_chan, 4);
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan, &rx_chan));
test_gdma_crc_calculation(tx_chan, rx_chan, 4);
TEST_ESP_OK(gdma_del_channel(tx_chan));
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_HAS(AHB_GDMA)
#if SOC_HAS(AXI_GDMA)
printf("Test CRC calculation for AXI GDMA\r\n");
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan, NULL));
test_gdma_crc_calculation(tx_chan, 3);
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan, &rx_chan));
test_gdma_crc_calculation(tx_chan, rx_chan, 3);
TEST_ESP_OK(gdma_del_channel(tx_chan));
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_HAS(AXI_GDMA)
}