fix(driver_spi): support un-aligned dma transaction and psram transaction
This commit is contained in:
@@ -1727,6 +1727,7 @@ static IRAM_ATTR void test_master_iram(void)
|
||||
|
||||
spi_device_handle_t dev_handle = {0};
|
||||
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||
devcfg.cs_ena_pretrans = 1;
|
||||
devcfg.post_cb = test_master_iram_post_trans_cbk;
|
||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle));
|
||||
|
||||
@@ -1976,27 +1977,32 @@ TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]")
|
||||
|
||||
#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE
|
||||
#define TEST_EDMA_PSRAM_TRANS_NUM 5
|
||||
#define TEST_EDMA_TRANS_LEN 20480 //Use PSRAM need a 16/32/64 aligned buffer len
|
||||
#define TEST_EDMA_TRANS_LEN 20000
|
||||
#define TEST_EDMA_BUFFER_SZ (TEST_EDMA_PSRAM_TRANS_NUM * TEST_EDMA_TRANS_LEN)
|
||||
|
||||
void test_spi_psram_trans(spi_device_handle_t dev_handle, void *tx, void *rx)
|
||||
{
|
||||
spi_transaction_t trans_cfg = {
|
||||
.length = TEST_EDMA_TRANS_LEN * 8,
|
||||
.flags = SPI_TRANS_DMA_USE_PSRAM,
|
||||
.tx_buffer = tx,
|
||||
.rx_buffer = rx,
|
||||
};
|
||||
|
||||
int trans_len = TEST_EDMA_TRANS_LEN - TEST_EDMA_PSRAM_TRANS_NUM / 2;
|
||||
for (uint8_t cnt = 0; cnt < TEST_EDMA_PSRAM_TRANS_NUM; cnt ++) {
|
||||
trans_cfg.tx_buffer = tx + TEST_EDMA_TRANS_LEN * cnt;
|
||||
trans_cfg.rx_buffer = rx + TEST_EDMA_TRANS_LEN * cnt;
|
||||
trans_cfg.length = trans_len * 8;
|
||||
trans_cfg.rxlength = trans_len * 8;
|
||||
trans_cfg.flags = (cnt % 2) ? 0 : SPI_TRANS_DMA_USE_PSRAM;
|
||||
|
||||
// To use psram, hardware will pass data through MSPI and GDMA to GPSPI, which need some time
|
||||
// GPSPI bandwidth(speed * line_num) should always no more than PSRAM bandwidth
|
||||
trans_cfg.override_freq_hz = (CONFIG_SPIRAM_SPEED / 4) * 1000 * 1000;
|
||||
printf("%d TX %p RX %p len %d @%ld kHz\n", cnt, trans_cfg.tx_buffer, trans_cfg.rx_buffer, TEST_EDMA_TRANS_LEN, trans_cfg.override_freq_hz / 1000);
|
||||
printf("%d TX %p RX %p len %d @%ld kHz\n", cnt, trans_cfg.tx_buffer, trans_cfg.rx_buffer, trans_len, trans_cfg.override_freq_hz / 1000);
|
||||
TEST_ESP_OK(spi_device_transmit(dev_handle, &trans_cfg));
|
||||
TEST_ASSERT(!(trans_cfg.flags & (SPI_TRANS_DMA_RX_FAIL | SPI_TRANS_DMA_TX_FAIL)));
|
||||
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, TEST_EDMA_TRANS_LEN);
|
||||
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, trans_len);
|
||||
trans_cfg.tx_buffer += trans_len;
|
||||
trans_cfg.rx_buffer += trans_len;
|
||||
trans_len ++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2007,17 +2013,16 @@ TEST_CASE("SPI_Master: PSRAM buffer transaction via EDMA", "[spi]")
|
||||
buscfg.max_transfer_sz = TEST_EDMA_BUFFER_SZ;
|
||||
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
spi_device_handle_t dev_handle;
|
||||
spi_device_handle_t dev_handle = NULL;
|
||||
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||
devcfg.clock_speed_hz = 80 * 1000 * 1000; // Test error case on highest freq first
|
||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle));
|
||||
int real_freq_khz;
|
||||
spi_device_get_actual_freq(dev_handle, &real_freq_khz);
|
||||
|
||||
uint32_t cache_width = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
|
||||
uint8_t *internal_1 = heap_caps_aligned_calloc(cache_width, 1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_INTERNAL);
|
||||
uint8_t *external_1 = heap_caps_aligned_calloc(cache_width, 1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *external_2 = heap_caps_aligned_calloc(cache_width, 1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *internal_1 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_INTERNAL);
|
||||
uint8_t *external_1 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *external_2 = heap_caps_calloc(1, TEST_EDMA_BUFFER_SZ, MALLOC_CAP_SPIRAM);
|
||||
test_fill_random_to_buffers_dualboard(1001, internal_1, external_2, TEST_EDMA_BUFFER_SZ);
|
||||
|
||||
printf("Test error case: High freq @%d kHz\n", real_freq_khz);
|
||||
@@ -2027,31 +2032,32 @@ TEST_CASE("SPI_Master: PSRAM buffer transaction via EDMA", "[spi]")
|
||||
.rx_buffer = external_1,
|
||||
};
|
||||
|
||||
// also test on polling API, and automalloc mechanism
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
printf("\n==== %s ====\n", i ? "EDMA" : "Auto Malloc");
|
||||
trans_cfg.flags = i ? SPI_TRANS_DMA_USE_PSRAM : 0;
|
||||
uint32_t before = esp_get_free_heap_size();
|
||||
spi_device_polling_start(dev_handle, &trans_cfg, portMAX_DELAY);
|
||||
uint32_t after = esp_get_free_heap_size();
|
||||
printf("\n==== %s ====\n", i ? "EDMA" : "Auto Malloc");
|
||||
printf("before: %ld, after: %ld, diff: %ld\n", before, after, after - before);
|
||||
printf("mem_diff: %ld, trans_len: %d\n", after - before, TEST_EDMA_TRANS_LEN);
|
||||
// rx buffer still potential re-malloc from psram even if SPI_TRANS_DMA_USE_PSRAM is set
|
||||
TEST_ASSERT(i ? (before - after) < 2 * TEST_EDMA_TRANS_LEN : (before - after) > 2 * TEST_EDMA_TRANS_LEN);
|
||||
spi_device_polling_end(dev_handle, portMAX_DELAY);
|
||||
printf("RX fail: %d, TX fail: %d\n", !!(trans_cfg.flags & SPI_TRANS_DMA_RX_FAIL), !!(trans_cfg.flags & SPI_TRANS_DMA_TX_FAIL));
|
||||
TEST_ASSERT(i ? (before - after) < TEST_EDMA_TRANS_LEN : (before - after) > 2 * TEST_EDMA_TRANS_LEN);
|
||||
TEST_ASSERT((!!i) == !!(trans_cfg.flags & (SPI_TRANS_DMA_RX_FAIL | SPI_TRANS_DMA_TX_FAIL)));
|
||||
printf("TX fail: %d, RX fail: %d\n", !!(trans_cfg.flags & SPI_TRANS_DMA_TX_FAIL), !!(trans_cfg.flags & SPI_TRANS_DMA_RX_FAIL));
|
||||
TEST_ASSERT((!!i) == !!(trans_cfg.flags & (SPI_TRANS_DMA_TX_FAIL | SPI_TRANS_DMA_RX_FAIL)));
|
||||
if (!i) { // data should be correct if using auto malloc
|
||||
spitest_cmp_or_dump(trans_cfg.tx_buffer, trans_cfg.rx_buffer, TEST_EDMA_TRANS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nTest unaligned tx psram buffer\n");
|
||||
trans_cfg.tx_buffer ++;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_device_transmit(dev_handle, &trans_cfg));
|
||||
|
||||
printf("\nTest trans: internal -> psram\n");
|
||||
memset(external_1, 0, TEST_EDMA_BUFFER_SZ);
|
||||
TEST_ESP_OK(esp_cache_msync((void *)external_1, TEST_EDMA_BUFFER_SZ, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
TEST_ESP_OK(esp_cache_msync((void *)external_1, TEST_EDMA_BUFFER_SZ, (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED)));
|
||||
test_spi_psram_trans(dev_handle, internal_1, external_1);
|
||||
|
||||
printf("\nTest trans: psram -> psram\n");
|
||||
memset(external_2, 0, TEST_EDMA_BUFFER_SZ);
|
||||
TEST_ESP_OK(esp_cache_msync((void *)external_2, TEST_EDMA_BUFFER_SZ, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
TEST_ESP_OK(esp_cache_msync((void *)external_2, TEST_EDMA_BUFFER_SZ, (ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED)));
|
||||
test_spi_psram_trans(dev_handle, external_1, external_2);
|
||||
|
||||
printf("\nTest trans: psram -> internal\n");
|
||||
|
||||
@@ -312,6 +312,7 @@ static void test_slave_iram_master_normal(void)
|
||||
|
||||
spi_device_handle_t dev_handle = {0};
|
||||
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||
devcfg.cs_ena_pretrans = 1;
|
||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev_handle));
|
||||
|
||||
uint8_t *master_send = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DMA);
|
||||
|
||||
Reference in New Issue
Block a user