diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c index a8ec1513161..3b023287ce2 100644 --- a/components/esp_driver_parlio/src/parlio_rx.c +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -164,7 +164,7 @@ size_t parlio_rx_mount_transaction_buffer(parlio_rx_unit_handle_t rx_unit, parli if (rest_size >= 2 * PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) { mount_size = PARLIO_RX_MOUNT_SIZE_CALC(trans->aligned_payload.buf.body.length, body_node_num, trans->alignment); } else if (rest_size <= PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) { - mount_size = (required_node_num == 2) && (i == 0) ? PARLIO_RX_MOUNT_SIZE_CALC(rest_size, 2, trans->alignment) : rest_size; + mount_size = (required_node_num - tail_node_num == 2) && (i == 0) ? PARLIO_RX_MOUNT_SIZE_CALC(rest_size, 2, trans->alignment) : rest_size; } else { mount_size = PARLIO_RX_MOUNT_SIZE_CALC(rest_size, 2, trans->alignment); } @@ -401,7 +401,15 @@ static bool parlio_rx_default_desc_done_callback(gdma_channel_handle_t dma_chan, size_t finished_length = gdma_link_get_length(rx_unit->dma_link, rx_unit->curr_node_id); #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE esp_err_t ret = ESP_OK; - ret = esp_cache_msync(finished_buffer, finished_length, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + size_t sync_size = finished_length; + /* The sych length should be the cache line size for the un-aligned head and tail part */ + for (int i = 0; i < 2; i++) { + if (finished_buffer == rx_unit->stash_buf[i]) { + sync_size = rx_unit->dma_mem_align; + break; + } + } + ret = esp_cache_msync(finished_buffer, sync_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); if (ret != ESP_OK) { ESP_EARLY_LOGW(TAG, "failed to sync dma buffer from memory to cache"); } @@ -988,11 +996,6 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, ESP_RETURN_ON_FALSE(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG, TAG, "The payload size should greater than %"PRIu32, 2 * alignment); } -#if CONFIG_PARLIO_RX_ISR_CACHE_SAFE - ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); -#else - ESP_RETURN_ON_FALSE(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); -#endif if (recv_cfg->delimiter->eof_data_len) { ESP_RETURN_ON_FALSE(payload_size >= recv_cfg->delimiter->eof_data_len, ESP_ERR_INVALID_ARG, TAG, "payload size should be greater than eof_data_len"); diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c index b77bb8b4033..11324074ea7 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c @@ -548,6 +548,47 @@ TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]") free(payload); }; +TEST_CASE("parallel_rx_unit_receive_external_memory_test", "[parlio_rx]") +{ + parlio_rx_unit_handle_t rx_unit = NULL; + parlio_rx_delimiter_handle_t deli = NULL; + size_t payload_size = 1000; + + parlio_rx_unit_config_t config = TEST_DEFAULT_UNIT_CONFIG(PARLIO_CLK_SRC_DEFAULT, 1000000); + config.flags.free_clk = 1; + TEST_ESP_OK(parlio_new_rx_unit(&config, &rx_unit)); + + parlio_rx_soft_delimiter_config_t sft_deli_cfg = { + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .eof_data_len = payload_size, + .timeout_ticks = 0, + }; + TEST_ESP_OK(parlio_new_rx_soft_delimiter(&sft_deli_cfg, &deli)); + + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); + + parlio_receive_config_t recv_config = { + .delimiter = deli, + .flags.partial_rx_en = false, + }; + + /* Do not specify alignment, check if the driver can work correctly */ + uint8_t *payload = heap_caps_calloc_prefer(1, payload_size, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM, TEST_PARLIO_DMA_MEM_ALLOC_CAPS); + printf("payload addr: %p size: %u\n", payload, payload_size); + TEST_ASSERT(payload); + + printf("Testing the external memory receive functionality...\n"); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true)); + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, payload_size, &recv_config)); + TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false)); + + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + TEST_ESP_OK(parlio_del_rx_delimiter(deli)); + TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); + free(payload); +} + TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") { printf("init a gpio to simulate valid signal\r\n"); @@ -689,7 +730,7 @@ TEST_CASE("parallel_rx_unit_force_trigger_eof_test", "[parlio_rx]") uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); alignment = alignment < 4 ? 4 : alignment; size_t buff_size = ALIGN_UP(TEST_TASK_LARGE_TRANS_SIZE, alignment); - recv_buff = heap_caps_aligned_calloc(alignment, 1, buff_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS); + recv_buff = heap_caps_aligned_calloc(alignment, 1, buff_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA); TEST_ASSERT_NOT_NULL(recv_buff); gpio_set_intr_type(TEST_VALID_GPIO, GPIO_INTR_NEGEDGE);