mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-19 14:26:01 -04:00
Merge branch 'feature/parlio_rx_driver_p4_v5.3' into 'release/v5.3'
feat(parlio_rx): supported parlio rx on p4 (v5.3) See merge request espressif/esp-idf!31096
This commit is contained in:
commit
41515a9086
@ -48,6 +48,8 @@ parlio_group_t *parlio_acquire_group_handle(int group_id)
|
||||
}
|
||||
// hal layer initialize
|
||||
parlio_hal_init(&group->hal);
|
||||
group->dma_align = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
group->dma_align = group->dma_align < 4 ? 4 : group->dma_align;
|
||||
}
|
||||
} else { // group already install
|
||||
group = s_platform.groups[group_id];
|
||||
|
@ -30,6 +30,7 @@
|
||||
#else
|
||||
#define PARLIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
#define PARLIO_DMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
|
||||
|
||||
#if SOC_PARLIO_TX_RX_SHARE_INTERRUPT
|
||||
#define PARLIO_INTR_ALLOC_FLAG_SHARED ESP_INTR_FLAG_SHARED
|
||||
@ -57,6 +58,12 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t;
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define PARLIO_MAX_ALIGNED_DMA_BUF_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED
|
||||
#else
|
||||
#define PARLIO_MAX_ALIGNED_DMA_BUF_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED
|
||||
#endif
|
||||
|
||||
#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR
|
||||
/* The descriptor address can be mapped by a fixed offset */
|
||||
#define PARLIO_GET_NON_CACHED_DESC_ADDR(desc) (desc ? (parlio_dma_desc_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(desc)) : NULL)
|
||||
@ -110,6 +117,7 @@ typedef struct parlio_group_t {
|
||||
int group_id; // group ID, index from 0
|
||||
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
|
||||
parlio_hal_context_t hal; // hal layer context
|
||||
uint32_t dma_align; // DMA buffer alignment
|
||||
parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles
|
||||
parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles
|
||||
} parlio_group_t;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -33,7 +33,9 @@
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_cache.h"
|
||||
|
||||
static const char *TAG = "parlio-rx";
|
||||
|
||||
@ -81,8 +83,9 @@ typedef struct parlio_rx_unit_t {
|
||||
gdma_channel_handle_t dma_chan; /*!< DMA channel */
|
||||
size_t max_recv_size; /*!< Maximum receive size for a normal transaction */
|
||||
size_t desc_num; /*!< DMA descriptor number */
|
||||
dma_descriptor_t *dma_descs; /*!< DMA descriptor array pointer */
|
||||
dma_descriptor_t *curr_desc; /*!< The pointer of the current descriptor */
|
||||
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 */
|
||||
/* Infinite transaction specific */
|
||||
void *dma_buf; /*!< Additional internal DMA buffer only for infinite transactions */
|
||||
@ -125,19 +128,21 @@ 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))
|
||||
|
||||
static portMUX_TYPE s_rx_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static IRAM_ATTR size_t s_parlio_mount_transaction_buffer(parlio_rx_unit_handle_t rx_unit, parlio_rx_transaction_t *trans)
|
||||
{
|
||||
dma_descriptor_t *p_desc = rx_unit->dma_descs;
|
||||
parlio_dma_desc_t **p_desc = rx_unit->dma_descs;
|
||||
/* Update the current transaction to the next one, and declare the delimiter is under using of the rx unit */
|
||||
memcpy(&rx_unit->curr_trans, trans, sizeof(parlio_rx_transaction_t));
|
||||
portENTER_CRITICAL_SAFE(&s_rx_spinlock);
|
||||
trans->delimiter->under_using = true;
|
||||
portEXIT_CRITICAL_SAFE(&s_rx_spinlock);
|
||||
|
||||
uint32_t desc_num = trans->size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
uint32_t remain_num = trans->size % DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
uint32_t desc_num = trans->size / PARLIO_MAX_ALIGNED_DMA_BUF_SIZE;
|
||||
uint32_t remain_num = trans->size % PARLIO_MAX_ALIGNED_DMA_BUF_SIZE;
|
||||
/* If there are still data remained, need one more descriptor */
|
||||
desc_num += remain_num ? 1 : 0;
|
||||
if (trans->flags.infinite && desc_num < 2) {
|
||||
@ -146,30 +151,40 @@ static IRAM_ATTR size_t s_parlio_mount_transaction_buffer(parlio_rx_unit_handle_
|
||||
}
|
||||
size_t mount_size = 0;
|
||||
size_t offset = 0;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
uint32_t alignment = rx_unit->base.group->dma_align;
|
||||
#else
|
||||
uint32_t alignment = 4;
|
||||
#endif
|
||||
/* Loop the descriptors to assign the data */
|
||||
for (int i = 0; i < desc_num; i++) {
|
||||
size_t rest_size = trans->size - offset;
|
||||
if (rest_size >= 2 * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) {
|
||||
mount_size = trans->size / desc_num;
|
||||
} else if (rest_size <= DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) {
|
||||
mount_size = (desc_num == 2) && (i == 0) ? rest_size / 2 : rest_size;
|
||||
|
||||
if (rest_size >= 2 * PARLIO_MAX_ALIGNED_DMA_BUF_SIZE) {
|
||||
mount_size = PRALIO_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;
|
||||
} else {
|
||||
mount_size = rest_size / 2;
|
||||
mount_size = PRALIO_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;
|
||||
p_desc[i].dw0.length = mount_size;
|
||||
p_desc[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
p_desc[i]->buffer = (void *)((uint8_t *)trans->payload + offset);
|
||||
p_desc[i]->dw0.size = mount_size;
|
||||
p_desc[i]->dw0.length = mount_size;
|
||||
p_desc[i]->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
// Link the descriptor
|
||||
if (i > 0) {
|
||||
p_desc[i - 1].next = &p_desc[i];
|
||||
if (i < desc_num - 1) {
|
||||
p_desc[i]->next = p_desc[i + 1];
|
||||
} else {
|
||||
/* For infinite transaction, link the descriptor as a ring */
|
||||
p_desc[i]->next = trans->flags.infinite ? p_desc[0] : NULL;
|
||||
}
|
||||
offset += mount_size;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
esp_cache_msync(p_desc[i], rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
#endif
|
||||
}
|
||||
/* For infinite transaction, link the descriptor as a ring */
|
||||
p_desc[desc_num - 1].next = trans->flags.infinite ? &p_desc[0] : NULL;
|
||||
/* Reset the current DMA node */
|
||||
rx_unit->curr_desc = p_desc;
|
||||
rx_unit->curr_desc = p_desc[0];
|
||||
|
||||
return offset;
|
||||
}
|
||||
@ -251,6 +266,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
|
||||
gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT;
|
||||
gpio_conf.pin_bit_mask = BIT64(config->clk_in_gpio_num);
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed");
|
||||
} else {
|
||||
gpio_ll_input_enable(&GPIO, config->clk_in_gpio_num);
|
||||
}
|
||||
esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num,
|
||||
parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_in_sig, false);
|
||||
@ -275,6 +292,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
|
||||
if (!config->flags.io_no_init) {
|
||||
gpio_conf.pin_bit_mask = BIT64(config->valid_gpio_num);
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed");
|
||||
} else {
|
||||
gpio_ll_input_enable(&GPIO, config->valid_gpio_num);
|
||||
}
|
||||
/* Not connect the signal here, the signal is lazy connected until the delimiter takes effect */
|
||||
}
|
||||
@ -286,7 +305,8 @@ static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, cons
|
||||
if (!config->flags.io_no_init) {
|
||||
gpio_conf.pin_bit_mask = BIT64(config->data_gpio_nums[i]);
|
||||
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed");
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO);
|
||||
} else {
|
||||
gpio_ll_input_enable(&GPIO, config->data_gpio_nums[i]);
|
||||
}
|
||||
esp_rom_gpio_connect_in_signal(config->data_gpio_nums[i],
|
||||
parlio_periph_signals.groups[group_id].rx_units[unit_id].data_sigs[i], false);
|
||||
@ -330,19 +350,23 @@ static IRAM_ATTR bool s_parlio_rx_default_eof_callback(gdma_channel_handle_t dma
|
||||
/* The current transaction finished, try to get the next transaction from the transaction queue */
|
||||
if (xQueueReceiveFromISR(rx_unit->trans_que, &next_trans, &high_task_woken) == pdTRUE) {
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false);
|
||||
}
|
||||
}
|
||||
/* If the delimiter of the next transaction is not same as the current one, need to re-config the hardware */
|
||||
if (next_trans.delimiter != rx_unit->curr_trans.delimiter) {
|
||||
if ((next_trans.delimiter != NULL) && (next_trans.delimiter != rx_unit->curr_trans.delimiter)) {
|
||||
s_parlio_set_delimiter_config(rx_unit, next_trans.delimiter);
|
||||
}
|
||||
/* Mount the new transaction buffer and start the new transaction */
|
||||
s_parlio_mount_transaction_buffer(rx_unit, &next_trans);
|
||||
gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->dma_descs);
|
||||
gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->dma_descs[0]);
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
parlio_ll_rx_start(rx_unit->base.group->hal.regs, true);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true);
|
||||
}
|
||||
}
|
||||
} else if (rx_unit->curr_trans.delimiter) { // Add condition in case the curr_trans has been cleared in the last timeout isr
|
||||
/* No more transaction pending to receive, clear the current transaction */
|
||||
portENTER_CRITICAL_ISR(&s_rx_spinlock);
|
||||
@ -368,7 +392,15 @@ static IRAM_ATTR bool s_parlio_rx_default_desc_done_callback(gdma_channel_handle
|
||||
}
|
||||
|
||||
/* Get the finished descriptor from the current descriptor */
|
||||
dma_descriptor_t *finished_desc = rx_unit->curr_desc;
|
||||
parlio_dma_desc_t *finished_desc = rx_unit->curr_desc;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
esp_err_t ret = ESP_OK;
|
||||
ret |= esp_cache_msync((void *)finished_desc, rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
ret |= esp_cache_msync((void *)(finished_desc->buffer), finished_desc->dw0.size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGW(TAG, "failed to sync dma buffer from memory to cache");
|
||||
}
|
||||
#endif
|
||||
parlio_rx_event_data_t evt_data = {
|
||||
.delimiter = rx_unit->curr_trans.delimiter,
|
||||
.data = finished_desc->buffer,
|
||||
@ -399,21 +431,41 @@ static IRAM_ATTR bool s_parlio_rx_default_desc_done_callback(gdma_channel_handle
|
||||
static esp_err_t s_parlio_rx_create_dma_descriptors(parlio_rx_unit_handle_t rx_unit, uint32_t max_recv_size)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid param");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t desc_num = max_recv_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED + 1;
|
||||
/* set at least 2 descriptors */
|
||||
if (desc_num < 2) {
|
||||
desc_num = 4;
|
||||
desc_num = 2;
|
||||
}
|
||||
rx_unit->desc_num = desc_num;
|
||||
|
||||
/* Allocated and link the descriptor nodes */
|
||||
rx_unit->dma_descs = (dma_descriptor_t *)heap_caps_calloc(desc_num, sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
ESP_RETURN_ON_FALSE(rx_unit->dma_descs, ESP_ERR_NO_MEM, TAG, "no memory for DMA descriptors");
|
||||
rx_unit->dma_descs = heap_caps_calloc(desc_num, sizeof(parlio_dma_desc_t *), MALLOC_CAP_DMA);
|
||||
ESP_RETURN_ON_FALSE(rx_unit->dma_descs, ESP_ERR_NO_MEM, TAG, "no memory for DMA descriptor array");
|
||||
uint32_t cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
size_t alignment = MAX(cache_line_size, PARLIO_DMA_DESC_ALIGNMENT);
|
||||
rx_unit->desc_size = ALIGN_UP(sizeof(parlio_dma_desc_t), alignment);
|
||||
for (int i = 0; i < desc_num; i++) {
|
||||
rx_unit->dma_descs[i] = heap_caps_aligned_calloc(alignment, 1, rx_unit->desc_size, PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(rx_unit->dma_descs[i], ESP_ERR_NO_MEM, err, TAG, "no memory for DMA descriptors");
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
esp_cache_msync(rx_unit->dma_descs[i], rx_unit->desc_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
#endif
|
||||
}
|
||||
|
||||
rx_unit->max_recv_size = max_recv_size;
|
||||
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
err:
|
||||
for (int i = 0; i < desc_num; i++) {
|
||||
if (rx_unit->dma_descs[i]) {
|
||||
free(rx_unit->dma_descs[i]);
|
||||
rx_unit->dma_descs[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(rx_unit->dma_descs);
|
||||
rx_unit->dma_descs = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit)
|
||||
@ -422,7 +474,7 @@ static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit)
|
||||
gdma_channel_alloc_config_t dma_chan_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed");
|
||||
ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed");
|
||||
gdma_connect(rx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0));
|
||||
|
||||
/* Set GDMA strategy */
|
||||
@ -487,8 +539,10 @@ static esp_err_t s_parlio_select_periph_clock(parlio_rx_unit_handle_t rx_unit, c
|
||||
#endif
|
||||
|
||||
/* Set clock configuration */
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_set_clock_source(hal->regs, clk_src);
|
||||
parlio_ll_rx_set_clock_div(hal->regs, &clk_div);
|
||||
}
|
||||
|
||||
rx_unit->clk_src = clk_src;
|
||||
/* warning if precision lost due to division */
|
||||
@ -525,7 +579,14 @@ static esp_err_t s_parlio_destroy_rx_unit(parlio_rx_unit_handle_t rx_unit)
|
||||
}
|
||||
/* Free the DMA descriptors */
|
||||
if (rx_unit->dma_descs) {
|
||||
for (int i = 0; i < rx_unit->desc_num; i++) {
|
||||
if (rx_unit->dma_descs[i]) {
|
||||
free(rx_unit->dma_descs[i]);
|
||||
rx_unit->dma_descs[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(rx_unit->dma_descs);
|
||||
rx_unit->dma_descs = NULL;
|
||||
}
|
||||
/* Free the internal DMA buffer */
|
||||
if (rx_unit->dma_buf) {
|
||||
@ -591,9 +652,13 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un
|
||||
/* Install DMA service */
|
||||
ESP_GOTO_ON_ERROR(s_parlio_rx_unit_init_dma(unit), err, TAG, "install rx DMA failed");
|
||||
/* Reset RX module */
|
||||
PARLIO_RCC_ATOMIC() {
|
||||
parlio_ll_rx_reset_clock(hal->regs);
|
||||
}
|
||||
parlio_ll_rx_reset_fifo(hal->regs);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, false);
|
||||
}
|
||||
parlio_ll_rx_start(hal->regs, false);
|
||||
/* parlio_ll_clock_source_t and parlio_clock_source_t are binary compatible if the clock source is from internal */
|
||||
ESP_GOTO_ON_ERROR(s_parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed");
|
||||
@ -651,8 +716,10 @@ esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queu
|
||||
if (!rx_unit->cfg.flags.free_clk) {
|
||||
parlio_ll_rx_reset_fifo(hal->regs);
|
||||
parlio_ll_rx_start(hal->regs, true);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we need to start a pending transaction */
|
||||
parlio_rx_transaction_t trans = {};
|
||||
@ -663,16 +730,20 @@ esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queu
|
||||
// The semaphore always supposed to be taken successfully
|
||||
assert(xSemaphoreTake(rx_unit->trans_sem, 0) == pdTRUE);
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, false);
|
||||
}
|
||||
}
|
||||
s_parlio_set_delimiter_config(rx_unit, trans.delimiter);
|
||||
s_parlio_mount_transaction_buffer(rx_unit, &trans);
|
||||
gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc);
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
parlio_ll_rx_start(hal->regs, true);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
err:
|
||||
xSemaphoreGive(rx_unit->mutex);
|
||||
|
||||
@ -691,7 +762,9 @@ esp_err_t parlio_rx_unit_disable(parlio_rx_unit_handle_t rx_unit)
|
||||
rx_unit->is_enabled = false;
|
||||
/* stop the RX engine */
|
||||
gdma_stop(rx_unit->dma_chan);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(hal->regs, false);
|
||||
}
|
||||
parlio_ll_rx_start(hal->regs, false);
|
||||
if (rx_unit->curr_trans.delimiter) {
|
||||
portENTER_CRITICAL(&s_rx_spinlock);
|
||||
@ -842,8 +915,10 @@ static esp_err_t s_parlio_rx_unit_do_transaction(parlio_rx_unit_handle_t rx_unit
|
||||
portEXIT_CRITICAL_ISR(&s_rx_spinlock);
|
||||
if (is_stopped) {
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false);
|
||||
}
|
||||
}
|
||||
if (trans->delimiter != rx_unit->curr_trans.delimiter) {
|
||||
s_parlio_set_delimiter_config(rx_unit, trans->delimiter);
|
||||
}
|
||||
@ -853,8 +928,10 @@ static esp_err_t s_parlio_rx_unit_do_transaction(parlio_rx_unit_handle_t rx_unit
|
||||
gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc);
|
||||
if (rx_unit->cfg.flags.free_clk) {
|
||||
parlio_ll_rx_start(rx_unit->base.group->hal.regs, true);
|
||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||
parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true);
|
||||
}
|
||||
}
|
||||
} else { // Otherwise send to the queue
|
||||
/* Send the transaction to the queue */
|
||||
ESP_RETURN_ON_FALSE(xQueueSend(rx_unit->trans_que, trans, 0) == pdTRUE,
|
||||
@ -871,8 +948,17 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit,
|
||||
ESP_RETURN_ON_FALSE(rx_unit && payload && recv_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(recv_cfg->delimiter, ESP_ERR_INVALID_ARG, TAG, "no delimiter specified");
|
||||
ESP_RETURN_ON_FALSE(payload_size <= rx_unit->max_recv_size, ESP_ERR_INVALID_ARG, TAG, "trans length too large");
|
||||
uint32_t alignment = rx_unit->base.group->dma_align;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
ESP_RETURN_ON_FALSE(payload_size % alignment == 0, ESP_ERR_INVALID_ARG, TAG, "The payload size should align with %"PRIu32, alignment);
|
||||
if (recv_cfg->flags.partial_rx_en) {
|
||||
ESP_RETURN_ON_FALSE(payload_size >= 2 * alignment, ESP_ERR_INVALID_ARG, TAG, "The payload size should greater than %"PRIu32, 2 * alignment);
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_GDMA_ISR_IRAM_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,
|
||||
@ -895,7 +981,7 @@ esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit,
|
||||
if (recv_cfg->flags.partial_rx_en && recv_cfg->flags.indirect_mount) {
|
||||
ESP_RETURN_ON_FALSE(!rx_unit->dma_buf, ESP_ERR_INVALID_STATE, TAG, "infinite transaction is using the internal DMA buffer");
|
||||
/* Allocate the internal DMA buffer to store the data temporary */
|
||||
rx_unit->dma_buf = heap_caps_calloc(1, payload_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
rx_unit->dma_buf = heap_caps_aligned_calloc(alignment, 1, payload_size, PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
ESP_RETURN_ON_FALSE(rx_unit->dma_buf, ESP_ERR_NO_MEM, TAG, "No memory for the internal DMA buffer");
|
||||
/* Use the internal DMA buffer so that the user buffer can always be available */
|
||||
p_buffer = rx_unit->dma_buf;
|
||||
|
@ -405,7 +405,7 @@ static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_tx_unit_t *tx_unit, const
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// Write back to cache to synchronize the cache before DMA start
|
||||
esp_cache_msync(buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
esp_cache_msync((void *)buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32P4
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ components/esp_driver_parlio/test_apps/parlio:
|
||||
disable:
|
||||
- if: SOC_PARLIO_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
- if: IDF_TARGET in ["esp32h2", "esp32p4"]
|
||||
temporary: true
|
||||
reason: lack of runner
|
||||
reason: IDF-9806 waiting for the fix of the bit shift issue after reset
|
||||
depends_components:
|
||||
- esp_driver_parlio
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 |
|
||||
| ----------------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -18,6 +18,7 @@ extern "C" {
|
||||
#define TEST_PARLIO_CALLBACK_ATTR
|
||||
#define TEST_PARLIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
#define TEST_PARLIO_DMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#define TEST_CLK_GPIO 10
|
||||
@ -42,15 +43,16 @@ extern "C" {
|
||||
#define TEST_DATA6_GPIO 8
|
||||
#define TEST_DATA7_GPIO 9
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
#define TEST_CLK_GPIO 20
|
||||
#define TEST_DATA0_GPIO 21
|
||||
#define TEST_DATA1_GPIO 22
|
||||
#define TEST_DATA2_GPIO 34
|
||||
#define TEST_DATA3_GPIO 35
|
||||
#define TEST_DATA4_GPIO 48
|
||||
#define TEST_DATA5_GPIO 49
|
||||
#define TEST_DATA6_GPIO 10
|
||||
#define TEST_DATA7_GPIO 11
|
||||
#define TEST_CLK_GPIO 32
|
||||
#define TEST_VALID_GPIO 36
|
||||
#define TEST_DATA0_GPIO 20
|
||||
#define TEST_DATA1_GPIO 21
|
||||
#define TEST_DATA2_GPIO 22
|
||||
#define TEST_DATA3_GPIO 23
|
||||
#define TEST_DATA4_GPIO 45
|
||||
#define TEST_DATA5_GPIO 46
|
||||
#define TEST_DATA6_GPIO 47
|
||||
#define TEST_DATA7_GPIO 48
|
||||
#else
|
||||
#error "Unsupported target"
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -17,16 +17,26 @@
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/parlio_periph.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "esp_attr.h"
|
||||
#include "test_board.h"
|
||||
|
||||
#define TEST_SPI_HOST SPI2_HOST
|
||||
#define TEST_I2S_PORT I2S_NUM_0
|
||||
#define TEST_VALID_SIG (PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1)
|
||||
|
||||
#if SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT
|
||||
#define TEST_OUTPUT_CLK_PIN TEST_CLK_GPIO
|
||||
#else
|
||||
#define TEST_OUTPUT_CLK_PIN -1
|
||||
#endif
|
||||
|
||||
#define TEST_DEFAULT_UNIT_CONFIG(_clk_src, _clk_freq) { \
|
||||
.trans_queue_depth = 10, \
|
||||
.max_recv_size = 10 * 1024, \
|
||||
@ -35,7 +45,7 @@
|
||||
.ext_clk_freq_hz = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? _clk_freq : 0, \
|
||||
.clk_in_gpio_num = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? TEST_CLK_GPIO : -1, \
|
||||
.exp_clk_freq_hz = _clk_freq, \
|
||||
.clk_out_gpio_num = -1, \
|
||||
.clk_out_gpio_num = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? -1 : TEST_OUTPUT_CLK_PIN, \
|
||||
.valid_gpio_num = TEST_VALID_GPIO, \
|
||||
.data_gpio_nums = { \
|
||||
[0] = TEST_DATA0_GPIO, \
|
||||
@ -56,6 +66,10 @@ typedef struct {
|
||||
uint32_t timeout_cnt;
|
||||
} test_data_t;
|
||||
|
||||
#ifndef ALIGN_UP
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
#endif
|
||||
|
||||
TEST_PARLIO_CALLBACK_ATTR
|
||||
static bool test_parlio_rx_partial_recv_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data)
|
||||
{
|
||||
@ -285,11 +299,15 @@ static bool test_delimiter(parlio_rx_delimiter_handle_t deli, bool free_running_
|
||||
.delimiter = deli,
|
||||
.flags.partial_rx_en = false,
|
||||
};
|
||||
uint8_t recv_buff[TEST_EOF_DATA_LEN];
|
||||
uint8_t *recv_buff = NULL;
|
||||
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_EOF_DATA_LEN, alignment);
|
||||
recv_buff = heap_caps_aligned_calloc(alignment, 1, buff_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
bool is_success = false;
|
||||
// sample 5 times
|
||||
for (int i = 0; i < 5 && !is_success; i++) {
|
||||
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, recv_buff, TEST_EOF_DATA_LEN, &recv_config));
|
||||
TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, recv_buff, buff_size, &recv_config));
|
||||
TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000));
|
||||
for (int k = 0; k < TEST_EOF_DATA_LEN; k++) {
|
||||
printf("%x ", recv_buff[k]);
|
||||
@ -315,6 +333,7 @@ static bool test_delimiter(parlio_rx_delimiter_handle_t deli, bool free_running_
|
||||
}
|
||||
// Delete the sender task
|
||||
vTaskDelete(sender_task);
|
||||
free(recv_buff);
|
||||
|
||||
TEST_ESP_OK(parlio_rx_unit_disable(rx_unit));
|
||||
TEST_ESP_OK(parlio_del_rx_unit(rx_unit));
|
||||
@ -409,8 +428,7 @@ TEST_CASE("parallel_rx_unit_install_uninstall", "[parlio_rx]")
|
||||
TEST_ESP_OK(parlio_rx_unit_disable(units[0]));
|
||||
TEST_ESP_OK(parlio_del_rx_unit(units[0]));
|
||||
}
|
||||
|
||||
#define TEST_PAYLOAD_SIZE 5000
|
||||
#define TEST_PAYLOAD_SIZE 5120
|
||||
|
||||
// This test case uses soft delimiter
|
||||
TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]")
|
||||
@ -444,7 +462,11 @@ TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]")
|
||||
.delimiter = deli,
|
||||
.flags.partial_rx_en = false,
|
||||
};
|
||||
uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS);
|
||||
uint8_t *payload = NULL;
|
||||
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(TEST_PAYLOAD_SIZE, alignment);
|
||||
payload = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
TEST_ASSERT(payload);
|
||||
|
||||
printf("Testing one normal transaction...\n");
|
||||
@ -535,7 +557,11 @@ TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]")
|
||||
.delimiter = timeout_deli,
|
||||
.flags.partial_rx_en = false,
|
||||
};
|
||||
uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS);
|
||||
uint8_t *payload = NULL;
|
||||
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(TEST_PAYLOAD_SIZE, alignment);
|
||||
payload = heap_caps_aligned_calloc(alignment, 1, payload_size, TEST_PARLIO_DMA_MEM_ALLOC_CAPS);
|
||||
TEST_ASSERT(payload);
|
||||
|
||||
printf("Testing the timeout callback...\n");
|
||||
|
@ -1,12 +1,10 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
|
@ -213,13 +213,13 @@ static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bi
|
||||
* @brief Set the sub mode of the level controlled receive mode
|
||||
*
|
||||
* @param dev Parallel IO register base address
|
||||
* @param active_level Level of the external enable signal, true for active high, false for active low
|
||||
* @param active_low_en Level of the external enable signal, true for active low, false for active high
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_level)
|
||||
static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_low_en)
|
||||
{
|
||||
dev->rx_mode_cfg.rx_smp_mode_sel = 0;
|
||||
dev->rx_mode_cfg.rx_ext_en_inv = !active_level; // 0: active low, 1: active high
|
||||
dev->rx_mode_cfg.rx_ext_en_inv = active_low_en;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -359,7 +359,7 @@ static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the RX clock gating
|
||||
* @brief whether to enable the RX clock gating
|
||||
*
|
||||
* @param dev Parallel IO register base address
|
||||
* @param en True to enable, False to disable
|
||||
@ -519,7 +519,7 @@ static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the TX clock gating
|
||||
* @brief whether to enable the TX clock gating
|
||||
*
|
||||
* @note The MSB of TXD will be taken as the gating enable signal
|
||||
*
|
||||
@ -589,7 +589,6 @@ static inline void parlio_ll_tx_set_bus_width(parl_io_dev_t *dev, uint32_t width
|
||||
{
|
||||
uint32_t width_sel = 0;
|
||||
switch (width) {
|
||||
// TODO: check this field (IDF-8284)
|
||||
case 16:
|
||||
width_sel = 4;
|
||||
break;
|
||||
|
@ -58,6 +58,7 @@ ESP_STATIC_ASSERT(sizeof(dma_descriptor_align8_t) == 16, "dma_descriptor_align8_
|
||||
#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE (4095) /*!< Maximum size of the buffer that can be attached to descriptor */
|
||||
#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED (4095-3) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 4B */
|
||||
#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_16B_ALIGNED (4095-15) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 16B */
|
||||
#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED (4095-63) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 64B */
|
||||
|
||||
/**
|
||||
* Get the number of DMA descriptors required for a given buffer size.
|
||||
|
@ -63,6 +63,10 @@ config SOC_ETM_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PARLIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ASYNC_MEMCPY_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@ -1011,6 +1015,10 @@ config SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PARLIO_TX_SIZE_BY_DMA
|
||||
bool
|
||||
default y
|
||||
|
@ -635,8 +635,8 @@ typedef enum {
|
||||
*/
|
||||
typedef enum {
|
||||
PARLIO_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
|
||||
PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
|
||||
PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
|
||||
PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
|
||||
PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */
|
||||
PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */
|
||||
} soc_periph_parlio_clk_src_t;
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define SOC_MCPWM_SUPPORTED 1
|
||||
#define SOC_TWAI_SUPPORTED 1
|
||||
#define SOC_ETM_SUPPORTED 1
|
||||
// #define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471
|
||||
#define SOC_PARLIO_SUPPORTED 1
|
||||
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
|
||||
#define SOC_EMAC_SUPPORTED 1
|
||||
#define SOC_USB_OTG_SUPPORTED 1
|
||||
@ -398,6 +398,7 @@
|
||||
#define SOC_PARLIO_RX_UNITS_PER_GROUP 1U /*!< number of RX units in each group */
|
||||
#define SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the TX unit */
|
||||
#define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH 16 /*!< Number of data lines of the RX unit */
|
||||
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
||||
#define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */
|
||||
|
||||
/*--------------------------- MPI CAPS ---------------------------------------*/
|
||||
|
@ -261,9 +261,11 @@ examples/peripherals/parlio:
|
||||
|
||||
examples/peripherals/parlio/parlio_rx:
|
||||
disable:
|
||||
- if: SOC_PARLIO_SUPPORTED != 1 or IDF_TARGET == "esp32p4"
|
||||
- if: SOC_PARLIO_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: not support esp32p4 yet (IDF-7471)
|
||||
reason: lack of runner
|
||||
depends_components:
|
||||
- esp_driver_parlio
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 |
|
||||
| ----------------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
|
||||
# Logic Analyzer Example
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -11,6 +11,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_probe.h"
|
||||
|
||||
@ -19,12 +21,17 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_PROBE_DEFAULT_Q_DEPTH 8
|
||||
#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * 4092)
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_64B_ALIGNED)
|
||||
#else
|
||||
#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED)
|
||||
#endif
|
||||
#if CONFIG_PARLIO_ISR_IRAM_SAFE
|
||||
#define ESP_PROBE_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ESP_PROBE_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
#define ESP_PROBE_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
|
||||
|
||||
struct esp_probe_t {
|
||||
uint32_t sample_width; /*!< sample width, i.e., enabled probe channel nums */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -8,8 +8,11 @@
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/parlio_rx.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_probe_private.h"
|
||||
|
||||
@ -43,7 +46,11 @@ esp_err_t esp_probe_priv_init_hardware(esp_probe_handle_t handle, esp_probe_conf
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_ephi = calloc(1, sizeof(esp_probe_impl_pralio_t));
|
||||
ESP_RETURN_ON_FALSE(s_ephi, ESP_ERR_NO_MEM, TAG, "no memory for the esp probe hardware implementation");
|
||||
s_ephi->payload = heap_caps_calloc(1, ESP_PROBE_DEFAULT_MAX_RECV_SIZE, ESP_PROBE_ALLOC_CAPS);
|
||||
|
||||
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_aligned_size = ESP_PROBE_DEFAULT_MAX_RECV_SIZE & ~(alignment - 1);
|
||||
s_ephi->payload = heap_caps_aligned_calloc(alignment, 1, payload_aligned_size, ESP_PROBE_DMA_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(s_ephi->payload, ESP_ERR_NO_MEM, err, TAG, "no memory for payload");
|
||||
|
||||
// Get the channel number, the channel number can only be the power of 2
|
||||
|
@ -1,5 +1,5 @@
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 |
|
||||
| ----------------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
|
||||
# Parallel IO TX Example: Simple RGB LED Matrix
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user