mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 12:14:32 +02:00
feat(parlio_rx): support to receive in isr context
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -161,7 +161,8 @@ typedef struct {
|
||||
interrupt, if the data length is set to `0`, that mean the EOF will only triggers
|
||||
when the end pulse detected, please ensure there is an end pulse for a frame and
|
||||
`parlio_rx_pulse_delimiter_config_t::has_end_pulse` flag is set */
|
||||
uint32_t timeout_ticks; /*!< The number of APB clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt */
|
||||
uint32_t timeout_ticks; /*!< The number of APB clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt
|
||||
The timeout counter starts when soft delimiter is stopped but the data is still not enough for EOF. */
|
||||
} parlio_rx_soft_delimiter_config_t;
|
||||
|
||||
/**
|
||||
@@ -270,6 +271,29 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit,
|
||||
size_t payload_size,
|
||||
const parlio_receive_config_t* recv_cfg);
|
||||
|
||||
/**
|
||||
* @brief Receive data by Parallel IO RX unit in ISR context (e.g. inside a callback function)
|
||||
* @note This function should only be called in ISR context, and the callback function should not block.
|
||||
* @note The payload buffer should be accessible in ISR context.
|
||||
* The payload buffer will be sent to the tail of the transaction queue.
|
||||
*
|
||||
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||||
* @param[in] payload The payload buffer pointer
|
||||
* @param[in] payload_size The size of the payload buffer, in bytes.
|
||||
* @param[in] recv_cfg The configuration of this receive transaction
|
||||
* @param[out] hp_task_woken Whether the high priority task is woken (Optional, set NULL if not needed)
|
||||
* @return
|
||||
* - ESP_OK: success to queue the transaction
|
||||
* - ESP_FAIL: failed to queue the transaction since the queue is full
|
||||
* - ESP_ERR_INVALID_ARG: invalid arguments, some conditions are not met
|
||||
* - ESP_ERR_INVALID_STATE: invalid state
|
||||
*/
|
||||
esp_err_t parlio_rx_unit_receive_from_isr(parlio_rx_unit_handle_t rx_unit,
|
||||
void *payload,
|
||||
size_t payload_size,
|
||||
const parlio_receive_config_t* recv_cfg,
|
||||
bool *hp_task_woken);
|
||||
|
||||
/**
|
||||
* @brief Wait for all pending RX transactions done
|
||||
* @note This function will block until all receiving transactions done or timeout.
|
||||
|
@@ -14,6 +14,7 @@ entries:
|
||||
parlio_rx: parlio_rx_default_desc_done_callback (noflash)
|
||||
parlio_rx: parlio_rx_mount_transaction_buffer (noflash)
|
||||
parlio_rx: parlio_rx_set_delimiter_config (noflash)
|
||||
parlio_rx: parlio_rx_unit_receive_from_isr (noflash)
|
||||
|
||||
[mapping:parlio_driver_gdma_link]
|
||||
archive: libesp_hw_support.a
|
||||
@@ -25,3 +26,9 @@ entries:
|
||||
|
||||
if SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION = y:
|
||||
gdma_link: gdma_link_get_buffer (noflash)
|
||||
|
||||
[mapping:parlio_driver_soc_periph]
|
||||
archive: libsoc.a
|
||||
entries:
|
||||
if PARLIO_RX_ISR_HANDLER_IN_IRAM = y:
|
||||
parlio_periph: parlio_periph_signals (noflash)
|
||||
|
@@ -73,7 +73,7 @@ typedef struct parlio_rx_unit_t {
|
||||
size_t desc_size; /*!< DMA descriptors total size */
|
||||
parlio_dma_desc_t **dma_descs; /*!< DMA descriptor array pointer */
|
||||
parlio_dma_desc_t *curr_desc; /*!< The pointer of the current descriptor */
|
||||
void *usr_recv_buf; /*!< The pointe to the user's receiving buffer */
|
||||
void *usr_recv_buf; /*!< The point to the user's receiving buffer */
|
||||
/* Infinite transaction specific */
|
||||
void *dma_buf; /*!< Additional internal DMA buffer only for infinite transactions */
|
||||
|
||||
@@ -115,7 +115,8 @@ typedef struct parlio_rx_delimiter_t {
|
||||
} flags;
|
||||
} parlio_rx_delimiter_t;
|
||||
|
||||
#define PRALIO_RX_MOUNT_SIZE_CALC(total_size, div, align) ((((total_size) / (align)) / (div)) * (align))
|
||||
#define PARLIO_RX_MOUNT_SIZE_CALC(total_size, div, align) ((((total_size) / (align)) / (div)) * (align))
|
||||
#define PARLIO_RX_CHECK_ISR(condition, err) if (!(condition)) { return err; }
|
||||
|
||||
static portMUX_TYPE s_rx_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
@@ -150,11 +151,11 @@ size_t parlio_rx_mount_transaction_buffer(parlio_rx_unit_handle_t rx_unit, parli
|
||||
size_t rest_size = trans->size - offset;
|
||||
|
||||
if (rest_size >= 2 * PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) {
|
||||
mount_size = PRALIO_RX_MOUNT_SIZE_CALC(trans->size, desc_num, alignment);
|
||||
mount_size = PARLIO_RX_MOUNT_SIZE_CALC(trans->size, desc_num, alignment);
|
||||
} else if (rest_size <= PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) {
|
||||
mount_size = (desc_num == 2) && (i == 0) ? PRALIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment) : rest_size;
|
||||
mount_size = (desc_num == 2) && (i == 0) ? PARLIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment) : rest_size;
|
||||
} else {
|
||||
mount_size = PRALIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment);
|
||||
mount_size = PARLIO_RX_MOUNT_SIZE_CALC(rest_size, 2, alignment);
|
||||
}
|
||||
p_desc[i]->buffer = (void *)((uint8_t *)trans->payload + offset);
|
||||
p_desc[i]->dw0.size = mount_size;
|
||||
@@ -716,6 +717,10 @@ esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queu
|
||||
} else if (xQueueReceive(rx_unit->trans_que, &trans, 0) == pdTRUE) {
|
||||
// The semaphore always supposed to be taken successfully
|
||||
assert(xSemaphoreTake(rx_unit->trans_sem, 0) == pdTRUE);
|
||||
if (trans.flags.indirect_mount && trans.flags.infinite && rx_unit->dma_buf == NULL) {
|
||||
rx_unit->dma_buf = heap_caps_aligned_calloc(rx_unit->base.group->dma_align, 1, trans.size, PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(rx_unit->dma_buf, ESP_ERR_NO_MEM, err, TAG, "No memory for the internal DMA buffer");
|
||||
}
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, false);
|
||||
@@ -994,6 +999,62 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit,
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t parlio_rx_unit_receive_from_isr(parlio_rx_unit_handle_t rx_unit,
|
||||
void *payload,
|
||||
size_t payload_size,
|
||||
const parlio_receive_config_t* recv_cfg,
|
||||
bool *hp_task_woken)
|
||||
{
|
||||
PARLIO_RX_CHECK_ISR(rx_unit && payload && recv_cfg, ESP_ERR_INVALID_ARG);
|
||||
PARLIO_RX_CHECK_ISR(recv_cfg->delimiter, ESP_ERR_INVALID_ARG);
|
||||
PARLIO_RX_CHECK_ISR(payload_size <= rx_unit->max_recv_size, ESP_ERR_INVALID_ARG);
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
uint32_t alignment = rx_unit->base.group->dma_align;
|
||||
PARLIO_RX_CHECK_ISR(payload_size % alignment == 0, ESP_ERR_INVALID_ARG);
|
||||
if (recv_cfg->flags.partial_rx_en) {
|
||||
PARLIO_RX_CHECK_ISR(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_PARLIO_RX_ISR_CACHE_SAFE
|
||||
PARLIO_RX_CHECK_ISR(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG);
|
||||
#else
|
||||
PARLIO_RX_CHECK_ISR(recv_cfg->flags.indirect_mount || esp_ptr_internal(payload), ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
if (recv_cfg->delimiter->eof_data_len) {
|
||||
PARLIO_RX_CHECK_ISR(payload_size >= recv_cfg->delimiter->eof_data_len, ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
if (recv_cfg->delimiter->mode != PARLIO_RX_SOFT_MODE) {
|
||||
PARLIO_RX_CHECK_ISR(rx_unit->cfg.valid_gpio_num >= 0, ESP_ERR_INVALID_ARG);
|
||||
/* Check if the valid_sig_line_id is equal or greater than data width, otherwise valid_sig_line_id is conflict with data signal.
|
||||
* Specifically, level or pulse delimiter requires one data line as valid signal, so these two delimiters can't support PARLIO_RX_UNIT_MAX_DATA_WIDTH */
|
||||
PARLIO_RX_CHECK_ISR(recv_cfg->delimiter->valid_sig_line_id >= rx_unit->cfg.data_width, ESP_ERR_INVALID_ARG);
|
||||
/* Assign the signal here to ensure iram safe */
|
||||
recv_cfg->delimiter->valid_sig = parlio_periph_signals.groups[rx_unit->base.group->group_id].
|
||||
rx_units[rx_unit->base.unit_id].
|
||||
data_sigs[recv_cfg->delimiter->valid_sig_line_id];
|
||||
}
|
||||
void *p_buffer = payload;
|
||||
|
||||
if (recv_cfg->flags.partial_rx_en && recv_cfg->flags.indirect_mount) {
|
||||
/* The internal DMA buffer should be allocated before calling this function */
|
||||
PARLIO_RX_CHECK_ISR(rx_unit->dma_buf, ESP_ERR_INVALID_STATE);
|
||||
p_buffer = rx_unit->dma_buf;
|
||||
}
|
||||
|
||||
/* Create the transaction */
|
||||
parlio_rx_transaction_t transaction = {
|
||||
.delimiter = recv_cfg->delimiter,
|
||||
.payload = p_buffer,
|
||||
.size = payload_size,
|
||||
.recv_bytes = 0,
|
||||
.flags.infinite = recv_cfg->flags.partial_rx_en,
|
||||
.flags.indirect_mount = recv_cfg->flags.indirect_mount,
|
||||
};
|
||||
rx_unit->usr_recv_buf = payload;
|
||||
|
||||
return xQueueSendFromISR(rx_unit->trans_que, &transaction, hp_task_woken) == pdTRUE ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t parlio_rx_unit_wait_all_done(parlio_rx_unit_handle_t rx_unit, int timeout_ms)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -591,3 +591,279 @@ TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]")
|
||||
TEST_ESP_OK(gpio_reset_pin(TEST_VALID_GPIO));
|
||||
free(payload);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t partial_recv_cnt;
|
||||
uint32_t recv_done_cnt;
|
||||
uint32_t timeout_cnt;
|
||||
uint32_t isr_send_cnt;
|
||||
uint32_t isr_send_success_cnt;
|
||||
parlio_rx_unit_handle_t rx_unit;
|
||||
parlio_rx_delimiter_handle_t delimiter;
|
||||
uint8_t *isr_payload;
|
||||
size_t isr_payload_size;
|
||||
bool enable_isr_send;
|
||||
} test_isr_data_t;
|
||||
|
||||
TEST_PARLIO_CALLBACK_ATTR
|
||||
static bool test_parlio_rx_isr_done_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data)
|
||||
{
|
||||
bool hp_task_woken = false;
|
||||
test_isr_data_t *test_data = (test_isr_data_t *)user_data;
|
||||
test_data->recv_done_cnt++;
|
||||
|
||||
// Call parlio_rx_unit_receive_from_isr in ISR context to queue new receive transactions
|
||||
if (test_data->enable_isr_send && test_data->isr_send_cnt < 3) {
|
||||
test_data->isr_send_cnt++;
|
||||
|
||||
parlio_receive_config_t recv_config = {
|
||||
.delimiter = test_data->delimiter,
|
||||
.flags.partial_rx_en = false,
|
||||
};
|
||||
|
||||
esp_err_t ret = parlio_rx_unit_receive_from_isr(test_data->rx_unit,
|
||||
test_data->isr_payload,
|
||||
test_data->isr_payload_size,
|
||||
&recv_config,
|
||||
&hp_task_woken);
|
||||
if (ret == ESP_OK) {
|
||||
test_data->isr_send_success_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return hp_task_woken;
|
||||
}
|
||||
|
||||
TEST_PARLIO_CALLBACK_ATTR
|
||||
static bool test_parlio_rx_isr_partial_recv_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data)
|
||||
{
|
||||
test_isr_data_t *test_data = (test_isr_data_t *)user_data;
|
||||
test_data->partial_recv_cnt++;
|
||||
return false;
|
||||
}
|
||||
|
||||
TEST_CASE("parallel_rx_unit_receive_isr_test", "[parlio_rx]")
|
||||
{
|
||||
parlio_rx_unit_handle_t rx_unit = NULL;
|
||||
parlio_rx_delimiter_handle_t deli = NULL;
|
||||
|
||||
// Create RX unit
|
||||
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));
|
||||
|
||||
// Create soft delimiter
|
||||
parlio_rx_soft_delimiter_config_t sft_deli_cfg = {
|
||||
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
|
||||
.eof_data_len = 1024, // Use smaller data length for testing convenience
|
||||
.timeout_ticks = 0,
|
||||
};
|
||||
TEST_ESP_OK(parlio_new_rx_soft_delimiter(&sft_deli_cfg, &deli));
|
||||
|
||||
// Prepare test data structure
|
||||
test_isr_data_t test_data = {
|
||||
.partial_recv_cnt = 0,
|
||||
.recv_done_cnt = 0,
|
||||
.timeout_cnt = 0,
|
||||
.isr_send_cnt = 0,
|
||||
.isr_send_success_cnt = 0,
|
||||
.rx_unit = rx_unit,
|
||||
.delimiter = deli,
|
||||
.enable_isr_send = false,
|
||||
};
|
||||
|
||||
// Allocate DMA compatible buffers
|
||||
uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
alignment = alignment < 4 ? 4 : alignment;
|
||||
size_t payload_size = ALIGN_UP(1024, alignment);
|
||||
|
||||
uint8_t *payload1 = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
uint8_t *payload2 = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
TEST_ASSERT(payload1 && payload2);
|
||||
|
||||
test_data.isr_payload = payload2;
|
||||
test_data.isr_payload_size = payload_size;
|
||||
|
||||
// Register callback functions
|
||||
parlio_rx_event_callbacks_t cbs = {
|
||||
.on_partial_receive = test_parlio_rx_isr_partial_recv_callback,
|
||||
.on_receive_done = test_parlio_rx_isr_done_callback,
|
||||
};
|
||||
TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &cbs, &test_data));
|
||||
TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true));
|
||||
|
||||
printf("Testing basic ISR receive functionality...\n");
|
||||
|
||||
// Start soft delimiter
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true));
|
||||
|
||||
// Send first transaction
|
||||
parlio_receive_config_t recv_config = {
|
||||
.delimiter = deli,
|
||||
.flags.partial_rx_en = false,
|
||||
};
|
||||
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload1, payload_size, &recv_config));
|
||||
|
||||
// Wait for first transaction to complete
|
||||
TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000));
|
||||
|
||||
// Verify first transaction completed
|
||||
TEST_ASSERT_EQUAL_UINT32(1, test_data.recv_done_cnt);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(1, test_data.partial_recv_cnt);
|
||||
|
||||
// Reset counters and enable ISR sending
|
||||
memset(&test_data, 0, sizeof(test_isr_data_t));
|
||||
test_data.rx_unit = rx_unit;
|
||||
test_data.delimiter = deli;
|
||||
test_data.isr_payload = payload2;
|
||||
test_data.isr_payload_size = payload_size;
|
||||
test_data.enable_isr_send = true;
|
||||
|
||||
printf("Testing queuing new transactions in ISR callback...\n");
|
||||
|
||||
// Send initial transaction, which will trigger ISR sending in callback
|
||||
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload1, payload_size, &recv_config));
|
||||
|
||||
// Wait for all transactions to complete (including transactions queued in ISR)
|
||||
TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 10000));
|
||||
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false));
|
||||
|
||||
printf("ISR send_cnt: %"PRIu32", success_cnt: %"PRIu32"\n",
|
||||
test_data.isr_send_cnt, test_data.isr_send_success_cnt);
|
||||
printf("recv_done_cnt: %"PRIu32", partial_recv_cnt: %"PRIu32"\n",
|
||||
test_data.recv_done_cnt, test_data.partial_recv_cnt);
|
||||
|
||||
// Verify ISR sending functionality
|
||||
TEST_ASSERT_GREATER_THAN_UINT32(0, test_data.isr_send_cnt);
|
||||
TEST_ASSERT_EQUAL_UINT32(test_data.isr_send_cnt, test_data.isr_send_success_cnt);
|
||||
|
||||
// Verify total receive done count = 1 (initial) + ISR success send count
|
||||
TEST_ASSERT_EQUAL_UINT32(1 + test_data.isr_send_success_cnt, test_data.recv_done_cnt);
|
||||
|
||||
// Verify partial receive count should be at least equal to receive done count
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(test_data.recv_done_cnt, test_data.partial_recv_cnt);
|
||||
|
||||
printf("Test completed: ISR receive functionality works\n");
|
||||
|
||||
// Clean up resources
|
||||
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(payload1);
|
||||
free(payload2);
|
||||
}
|
||||
|
||||
TEST_PARLIO_CALLBACK_ATTR
|
||||
static bool test_parlio_rx_isr_partial_recv_callback2(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data)
|
||||
{
|
||||
bool hp_task_woken = false;
|
||||
test_isr_data_t *test_data = (test_isr_data_t *)user_data;
|
||||
if (test_data->isr_send_success_cnt == 0) {
|
||||
parlio_receive_config_t recv_config = {
|
||||
.delimiter = test_data->delimiter,
|
||||
.flags.partial_rx_en = true,
|
||||
.flags.indirect_mount = true,
|
||||
};
|
||||
|
||||
esp_err_t ret = parlio_rx_unit_receive_from_isr(test_data->rx_unit,
|
||||
test_data->isr_payload,
|
||||
test_data->isr_payload_size,
|
||||
&recv_config,
|
||||
&hp_task_woken);
|
||||
if (ret == ESP_OK) {
|
||||
test_data->isr_send_success_cnt++;
|
||||
}
|
||||
}
|
||||
test_data->partial_recv_cnt++;
|
||||
return hp_task_woken;
|
||||
}
|
||||
|
||||
TEST_CASE("parallel_rx_unit_infinite_transaction_switch_test", "[parlio_rx]")
|
||||
{
|
||||
parlio_rx_unit_handle_t rx_unit = NULL;
|
||||
parlio_rx_delimiter_handle_t deli = NULL;
|
||||
|
||||
// Create RX unit
|
||||
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));
|
||||
|
||||
// Create soft delimiter
|
||||
parlio_rx_soft_delimiter_config_t sft_deli_cfg = {
|
||||
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
|
||||
.eof_data_len = 1024, // Use smaller data length for testing convenience
|
||||
.timeout_ticks = 0,
|
||||
};
|
||||
TEST_ESP_OK(parlio_new_rx_soft_delimiter(&sft_deli_cfg, &deli));
|
||||
|
||||
// Prepare test data structure
|
||||
test_isr_data_t test_data = {
|
||||
.partial_recv_cnt = 0,
|
||||
.recv_done_cnt = 0,
|
||||
.timeout_cnt = 0,
|
||||
.isr_send_cnt = 0,
|
||||
.isr_send_success_cnt = 0,
|
||||
.rx_unit = rx_unit,
|
||||
.delimiter = deli,
|
||||
.enable_isr_send = false,
|
||||
};
|
||||
|
||||
// Allocate DMA compatible buffers
|
||||
uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
alignment = alignment < 4 ? 4 : alignment;
|
||||
size_t payload_size = ALIGN_UP(1024, alignment);
|
||||
|
||||
uint8_t *payload1 = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
uint8_t *payload2 = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
TEST_ASSERT(payload1 && payload2);
|
||||
|
||||
test_data.isr_payload = payload2;
|
||||
test_data.isr_payload_size = payload_size;
|
||||
|
||||
// Register callback functions
|
||||
parlio_rx_event_callbacks_t cbs = {
|
||||
.on_partial_receive = test_parlio_rx_isr_partial_recv_callback2,
|
||||
};
|
||||
TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &cbs, &test_data));
|
||||
|
||||
TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true));
|
||||
|
||||
printf("Testing basic ISR receive functionality...\n");
|
||||
|
||||
// Start soft delimiter
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true));
|
||||
|
||||
// Send first transaction
|
||||
parlio_receive_config_t recv_config = {
|
||||
.delimiter = deli,
|
||||
.flags.partial_rx_en = true,
|
||||
.flags.indirect_mount = true,
|
||||
};
|
||||
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload1, payload_size, &recv_config));
|
||||
|
||||
// Wait for first transaction to complete
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
// Verify first transaction completed
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(1, test_data.partial_recv_cnt);
|
||||
TEST_ASSERT_EQUAL_UINT32(1, test_data.isr_send_success_cnt);
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false));
|
||||
|
||||
TEST_ESP_OK(parlio_rx_unit_disable(rx_unit));
|
||||
test_data.partial_recv_cnt = 0;
|
||||
test_data.isr_send_success_cnt = 0;
|
||||
// Do not reset queue, so the last transaction can be resumed after enable
|
||||
TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, false));
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false));
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(1, test_data.partial_recv_cnt);
|
||||
TEST_ASSERT_EQUAL_UINT32(1, test_data.isr_send_success_cnt);
|
||||
|
||||
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(payload1);
|
||||
free(payload2);
|
||||
}
|
||||
|
Reference in New Issue
Block a user