mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 14:14:33 +02:00
feat(parlio_tx): support loop transmission
This commit is contained in:
@@ -157,6 +157,7 @@ typedef struct {
|
|||||||
uint32_t idle_value; /*!< The value on the data line when the parallel IO is in idle state */
|
uint32_t idle_value; /*!< The value on the data line when the parallel IO is in idle state */
|
||||||
struct {
|
struct {
|
||||||
uint32_t queue_nonblocking : 1; /*!< If set, when the transaction queue is full, driver will not block the thread but return directly */
|
uint32_t queue_nonblocking : 1; /*!< If set, when the transaction queue is full, driver will not block the thread but return directly */
|
||||||
|
uint32_t loop_transmission : 1; /*!< If set, the transmission will be repeated continuously, until the tx_unit is disabled by `parlio_tx_unit_disable` */
|
||||||
} flags; /*!< Transmit specific config flags */
|
} flags; /*!< Transmit specific config flags */
|
||||||
} parlio_transmit_config_t;
|
} parlio_transmit_config_t;
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ entries:
|
|||||||
if PARLIO_TX_ISR_HANDLER_IN_IRAM = y:
|
if PARLIO_TX_ISR_HANDLER_IN_IRAM = y:
|
||||||
parlio_tx: parlio_tx_default_isr (noflash)
|
parlio_tx: parlio_tx_default_isr (noflash)
|
||||||
parlio_tx: parlio_tx_do_transaction (noflash)
|
parlio_tx: parlio_tx_do_transaction (noflash)
|
||||||
|
parlio_tx: parlio_mount_buffer (noflash)
|
||||||
if PARLIO_RX_ISR_HANDLER_IN_IRAM = y:
|
if PARLIO_RX_ISR_HANDLER_IN_IRAM = y:
|
||||||
parlio_rx: parlio_rx_default_eof_callback (noflash)
|
parlio_rx: parlio_rx_default_eof_callback (noflash)
|
||||||
parlio_rx: parlio_rx_default_desc_done_callback (noflash)
|
parlio_rx: parlio_rx_default_desc_done_callback (noflash)
|
||||||
@@ -15,6 +16,7 @@ archive: libesp_hw_support.a
|
|||||||
entries:
|
entries:
|
||||||
if PARLIO_TX_ISR_HANDLER_IN_IRAM = y:
|
if PARLIO_TX_ISR_HANDLER_IN_IRAM = y:
|
||||||
gdma_link: gdma_link_mount_buffers (noflash)
|
gdma_link: gdma_link_mount_buffers (noflash)
|
||||||
|
gdma_link: gdma_link_concat (noflash)
|
||||||
gdma_link: gdma_link_get_head_addr (noflash)
|
gdma_link: gdma_link_get_head_addr (noflash)
|
||||||
gdma: gdma_start (noflash)
|
gdma: gdma_start (noflash)
|
||||||
if PARLIO_RX_ISR_HANDLER_IN_IRAM = y:
|
if PARLIO_RX_ISR_HANDLER_IN_IRAM = y:
|
||||||
|
@@ -61,6 +61,9 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif // defined(SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS)
|
#endif // defined(SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS)
|
||||||
|
|
||||||
|
// loop transmission requires ping-pong link to prevent data tearing.
|
||||||
|
#define PARLIO_DMA_LINK_NUM 2
|
||||||
|
|
||||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||||
#define PARLIO_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
#define PARLIO_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||||
#else
|
#else
|
||||||
|
@@ -46,6 +46,10 @@ typedef struct {
|
|||||||
uint32_t idle_value; // Parallel IO bus idle value
|
uint32_t idle_value; // Parallel IO bus idle value
|
||||||
const void *payload; // payload to be transmitted
|
const void *payload; // payload to be transmitted
|
||||||
size_t payload_bits; // payload size in bits
|
size_t payload_bits; // payload size in bits
|
||||||
|
int dma_link_idx; // index of DMA link list
|
||||||
|
struct {
|
||||||
|
uint32_t loop_transmission : 1; // whether the transmission is in loop mode
|
||||||
|
} flags; // Extra configuration flags
|
||||||
} parlio_tx_trans_desc_t;
|
} parlio_tx_trans_desc_t;
|
||||||
|
|
||||||
typedef struct parlio_tx_unit_t {
|
typedef struct parlio_tx_unit_t {
|
||||||
@@ -54,7 +58,7 @@ typedef struct parlio_tx_unit_t {
|
|||||||
intr_handle_t intr; // allocated interrupt handle
|
intr_handle_t intr; // allocated interrupt handle
|
||||||
esp_pm_lock_handle_t pm_lock; // power management lock
|
esp_pm_lock_handle_t pm_lock; // power management lock
|
||||||
gdma_channel_handle_t dma_chan; // DMA channel
|
gdma_channel_handle_t dma_chan; // DMA channel
|
||||||
gdma_link_list_handle_t dma_link; // DMA link list handle
|
gdma_link_list_handle_t dma_link[PARLIO_DMA_LINK_NUM]; // DMA link list handle
|
||||||
size_t int_mem_align; // Alignment for internal memory
|
size_t int_mem_align; // Alignment for internal memory
|
||||||
size_t ext_mem_align; // Alignment for external memory
|
size_t ext_mem_align; // Alignment for external memory
|
||||||
#if CONFIG_PM_ENABLE
|
#if CONFIG_PM_ENABLE
|
||||||
@@ -129,8 +133,10 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit)
|
|||||||
// de-register from group
|
// de-register from group
|
||||||
parlio_unregister_unit_from_group(&tx_unit->base);
|
parlio_unregister_unit_from_group(&tx_unit->base);
|
||||||
}
|
}
|
||||||
if (tx_unit->dma_link) {
|
for (int i = 0; i < PARLIO_DMA_LINK_NUM; i++) {
|
||||||
ESP_RETURN_ON_ERROR(gdma_del_link_list(tx_unit->dma_link), TAG, "delete dma link list failed");
|
if (tx_unit->dma_link[i]) {
|
||||||
|
ESP_RETURN_ON_ERROR(gdma_del_link_list(tx_unit->dma_link[i]), TAG, "delete dma link list failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(tx_unit);
|
free(tx_unit);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -204,8 +210,9 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit, const parlio
|
|||||||
ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &tx_unit->dma_chan), TAG, "allocate TX DMA channel failed");
|
ESP_RETURN_ON_ERROR(PARLIO_GDMA_NEW_CHANNEL(&dma_chan_config, &tx_unit->dma_chan), TAG, "allocate TX DMA channel failed");
|
||||||
gdma_connect(tx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0));
|
gdma_connect(tx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0));
|
||||||
gdma_strategy_config_t gdma_strategy_conf = {
|
gdma_strategy_config_t gdma_strategy_conf = {
|
||||||
.auto_update_desc = true,
|
.auto_update_desc = false, // for loop transmission, we have no chance to change the owner
|
||||||
.owner_check = true,
|
.owner_check = false,
|
||||||
|
.eof_till_data_popped = true,
|
||||||
};
|
};
|
||||||
gdma_apply_strategy(tx_unit->dma_chan, &gdma_strategy_conf);
|
gdma_apply_strategy(tx_unit->dma_chan, &gdma_strategy_conf);
|
||||||
|
|
||||||
@@ -227,7 +234,9 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit, const parlio
|
|||||||
};
|
};
|
||||||
|
|
||||||
// throw the error to the caller
|
// throw the error to the caller
|
||||||
ESP_RETURN_ON_ERROR(gdma_new_link_list(&dma_link_config, &tx_unit->dma_link), TAG, "create DMA link list failed");
|
for (int i = 0; i < PARLIO_DMA_LINK_NUM; i++) {
|
||||||
|
ESP_RETURN_ON_ERROR(gdma_new_link_list(&dma_link_config, &tx_unit->dma_link[i]), TAG, "create DMA link list failed");
|
||||||
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,8 +325,6 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
|
|||||||
// data_width must not conflict with the valid signal
|
// data_width must not conflict with the valid signal
|
||||||
ESP_RETURN_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG),
|
ESP_RETURN_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG),
|
||||||
ESP_ERR_INVALID_ARG, TAG, "valid signal conflicts with data signal");
|
ESP_ERR_INVALID_ARG, TAG, "valid signal conflicts with data signal");
|
||||||
ESP_RETURN_ON_FALSE(config->max_transfer_size && config->max_transfer_size <= PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8,
|
|
||||||
ESP_ERR_INVALID_ARG, TAG, "invalid max transfer size");
|
|
||||||
#if SOC_PARLIO_TX_CLK_SUPPORT_GATING
|
#if SOC_PARLIO_TX_CLK_SUPPORT_GATING
|
||||||
// clock gating is controlled by either the MSB bit of data bus or the valid signal
|
// clock gating is controlled by either the MSB bit of data bus or the valid signal
|
||||||
ESP_RETURN_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE),
|
ESP_RETURN_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE),
|
||||||
@@ -386,10 +393,8 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
|
|||||||
// set sample clock edge
|
// set sample clock edge
|
||||||
parlio_ll_tx_set_sample_clock_edge(hal->regs, config->sample_edge);
|
parlio_ll_tx_set_sample_clock_edge(hal->regs, config->sample_edge);
|
||||||
|
|
||||||
#if SOC_PARLIO_TX_SIZE_BY_DMA
|
// In default, use DATA LEN EOF as the Parlio TX EOF
|
||||||
// Always use DATA LEN EOF as the Parlio TX EOF
|
|
||||||
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
||||||
#endif // SOC_PARLIO_TX_SIZE_BY_DMA
|
|
||||||
|
|
||||||
// clear any pending interrupt
|
// clear any pending interrupt
|
||||||
parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_MASK);
|
parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_MASK);
|
||||||
@@ -461,10 +466,38 @@ esp_err_t parlio_tx_unit_register_event_callbacks(parlio_tx_unit_handle_t tx_uni
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parlio_mount_buffer(parlio_tx_unit_t *tx_unit, parlio_tx_trans_desc_t *t)
|
||||||
|
{
|
||||||
|
// DMA transfer data based on bytes not bits, so convert the bit length to bytes, round up
|
||||||
|
gdma_buffer_mount_config_t mount_config = {
|
||||||
|
.buffer = (void *)t->payload,
|
||||||
|
.length = (t->payload_bits + 7) / 8,
|
||||||
|
.flags = {
|
||||||
|
// if transmission is loop, we don't need to generate the EOF, as well as the final mark
|
||||||
|
.mark_eof = !t->flags.loop_transmission,
|
||||||
|
.mark_final = !t->flags.loop_transmission,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int next_link_idx = t->flags.loop_transmission ? 1 - t->dma_link_idx : t->dma_link_idx;
|
||||||
|
gdma_link_mount_buffers(tx_unit->dma_link[next_link_idx], 0, &mount_config, 1, NULL);
|
||||||
|
|
||||||
|
if (t->flags.loop_transmission) {
|
||||||
|
// concatenate the DMA linked list of the next frame transmission with the DMA linked list of the current frame to realize the reuse of the current transmission transaction
|
||||||
|
gdma_link_concat(tx_unit->dma_link[t->dma_link_idx], -1, tx_unit->dma_link[next_link_idx], 0);
|
||||||
|
t->dma_link_idx = next_link_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_desc_t *t)
|
static void parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_desc_t *t)
|
||||||
{
|
{
|
||||||
parlio_hal_context_t *hal = &tx_unit->base.group->hal;
|
parlio_hal_context_t *hal = &tx_unit->base.group->hal;
|
||||||
|
|
||||||
|
if (t->flags.loop_transmission) {
|
||||||
|
// Once a loop transmission is started, it cannot be stopped until it is disabled
|
||||||
|
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DMA_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
tx_unit->cur_trans = t;
|
tx_unit->cur_trans = t;
|
||||||
|
|
||||||
// If the external clock is a non-free-running clock, it needs to be switched to the internal free-running clock first.
|
// If the external clock is a non-free-running clock, it needs to be switched to the internal free-running clock first.
|
||||||
@@ -478,21 +511,10 @@ static void parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_
|
|||||||
PARLIO_RCC_ATOMIC() {
|
PARLIO_RCC_ATOMIC() {
|
||||||
parlio_ll_tx_reset_clock(hal->regs);
|
parlio_ll_tx_reset_clock(hal->regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DMA transfer data based on bytes not bits, so convert the bit length to bytes, round up
|
|
||||||
gdma_buffer_mount_config_t mount_config = {
|
|
||||||
.buffer = (void *)t->payload,
|
|
||||||
.length = (t->payload_bits + 7) / 8,
|
|
||||||
.flags = {
|
|
||||||
.mark_eof = true,
|
|
||||||
.mark_final = true, // singly link list, mark final descriptor
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Since the threshold of the clock divider counter is not updated simultaneously with the clock source switching.
|
// Since the threshold of the clock divider counter is not updated simultaneously with the clock source switching.
|
||||||
// The update of the threshold relies on the moment when the counter reaches the threshold each time.
|
// The update of the threshold relies on the moment when the counter reaches the threshold each time.
|
||||||
// We place gdma_link_mount_buffers between reset clock and disable clock to ensure enough time for updating the threshold of the clock divider counter.
|
// We place parlio_mount_buffer between reset clock and disable clock to ensure enough time for updating the threshold of the clock divider counter.
|
||||||
gdma_link_mount_buffers(tx_unit->dma_link, 0, &mount_config, 1, NULL);
|
parlio_mount_buffer(tx_unit, t);
|
||||||
|
|
||||||
if (switch_clk) {
|
if (switch_clk) {
|
||||||
PARLIO_CLOCK_SRC_ATOMIC() {
|
PARLIO_CLOCK_SRC_ATOMIC() {
|
||||||
parlio_ll_tx_set_clock_source(hal->regs, PARLIO_CLK_SRC_EXTERNAL);
|
parlio_ll_tx_set_clock_source(hal->regs, PARLIO_CLK_SRC_EXTERNAL);
|
||||||
@@ -506,7 +528,7 @@ static void parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_
|
|||||||
parlio_ll_tx_set_idle_data_value(hal->regs, t->idle_value);
|
parlio_ll_tx_set_idle_data_value(hal->regs, t->idle_value);
|
||||||
parlio_ll_tx_set_trans_bit_len(hal->regs, t->payload_bits);
|
parlio_ll_tx_set_trans_bit_len(hal->regs, t->payload_bits);
|
||||||
|
|
||||||
gdma_start(tx_unit->dma_chan, gdma_link_get_head_addr(tx_unit->dma_link));
|
gdma_start(tx_unit->dma_chan, gdma_link_get_head_addr(tx_unit->dma_link[t->dma_link_idx]));
|
||||||
// wait until the data goes from the DMA to TX unit's FIFO
|
// wait until the data goes from the DMA to TX unit's FIFO
|
||||||
while (parlio_ll_tx_is_ready(hal->regs) == false);
|
while (parlio_ll_tx_is_ready(hal->regs) == false);
|
||||||
// turn on the core clock after we start the TX unit
|
// turn on the core clock after we start the TX unit
|
||||||
@@ -592,6 +614,10 @@ esp_err_t parlio_tx_unit_disable(parlio_tx_unit_handle_t tx_unit)
|
|||||||
parlio_ll_tx_start(hal->regs, false);
|
parlio_ll_tx_start(hal->regs, false);
|
||||||
parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_MASK, false);
|
parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_MASK, false);
|
||||||
|
|
||||||
|
// Once a loop teansmission transaction is started, it can only be stopped in disable function
|
||||||
|
// change the EOF condition to be the data length, so the EOF will be triggered normally
|
||||||
|
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
||||||
|
|
||||||
// release power management lock
|
// release power management lock
|
||||||
if (tx_unit->pm_lock) {
|
if (tx_unit->pm_lock) {
|
||||||
esp_pm_lock_release(tx_unit->pm_lock);
|
esp_pm_lock_release(tx_unit->pm_lock);
|
||||||
@@ -612,6 +638,21 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p
|
|||||||
ESP_RETURN_ON_FALSE((payload_bits % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "payload bit length must be multiple of 8");
|
ESP_RETURN_ON_FALSE((payload_bits % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "payload bit length must be multiple of 8");
|
||||||
#endif // !SOC_PARLIO_TRANS_BIT_ALIGN
|
#endif // !SOC_PARLIO_TRANS_BIT_ALIGN
|
||||||
|
|
||||||
|
#if SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
|
if (config->flags.loop_transmission) {
|
||||||
|
ESP_RETURN_ON_FALSE(parlio_ll_tx_support_dma_eof(NULL), ESP_ERR_NOT_SUPPORTED, TAG, "loop transmission is not supported by this chip revision");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ESP_RETURN_ON_FALSE(config->flags.loop_transmission == false, ESP_ERR_NOT_SUPPORTED, TAG, "loop transmission is not supported on this chip");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check the max payload size if it's not a loop transmission
|
||||||
|
// workaround for EOF limitation, when DMA EOF issue is fixed, we can remove this check
|
||||||
|
if (!config->flags.loop_transmission) {
|
||||||
|
ESP_RETURN_ON_FALSE(tx_unit->max_transfer_bits <= PARLIO_LL_TX_MAX_BITS_PER_FRAME,
|
||||||
|
ESP_ERR_INVALID_ARG, TAG, "invalid transfer size");
|
||||||
|
}
|
||||||
|
|
||||||
size_t cache_line_size = 0;
|
size_t cache_line_size = 0;
|
||||||
size_t alignment = 0;
|
size_t alignment = 0;
|
||||||
uint8_t cache_type = 0;
|
uint8_t cache_type = 0;
|
||||||
@@ -627,39 +668,48 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p
|
|||||||
ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED), TAG, "cache sync failed");
|
ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED), TAG, "cache sync failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
TickType_t queue_wait_ticks = portMAX_DELAY;
|
// check if to start a new transaction or update the current loop transaction
|
||||||
if (config->flags.queue_nonblocking) {
|
bool no_trans_pending_in_queue = uxQueueMessagesWaiting(tx_unit->trans_queues[PARLIO_TX_QUEUE_PROGRESS]) == 0;
|
||||||
queue_wait_ticks = 0;
|
if (tx_unit->cur_trans && tx_unit->cur_trans->flags.loop_transmission && config->flags.loop_transmission && no_trans_pending_in_queue) {
|
||||||
}
|
tx_unit->cur_trans->payload = payload;
|
||||||
parlio_tx_trans_desc_t *t = NULL;
|
tx_unit->cur_trans->payload_bits = payload_bits;
|
||||||
// acquire one transaction description from ready queue or complete queue
|
parlio_mount_buffer(tx_unit, tx_unit->cur_trans);
|
||||||
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &t, 0) != pdTRUE) {
|
} else {
|
||||||
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, queue_wait_ticks) == pdTRUE) {
|
TickType_t queue_wait_ticks = portMAX_DELAY;
|
||||||
tx_unit->num_trans_inflight--;
|
if (config->flags.queue_nonblocking) {
|
||||||
|
queue_wait_ticks = 0;
|
||||||
}
|
}
|
||||||
}
|
parlio_tx_trans_desc_t *t = NULL;
|
||||||
ESP_RETURN_ON_FALSE(t, ESP_ERR_INVALID_STATE, TAG, "no free transaction descriptor, please consider increasing trans_queue_depth");
|
// acquire one transaction description from ready queue or complete queue
|
||||||
|
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &t, 0) != pdTRUE) {
|
||||||
|
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, queue_wait_ticks) == pdTRUE) {
|
||||||
|
tx_unit->num_trans_inflight--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_RETURN_ON_FALSE(t, ESP_ERR_INVALID_STATE, TAG, "no free transaction descriptor, please consider increasing trans_queue_depth");
|
||||||
|
|
||||||
// fill in the transaction descriptor
|
// fill in the transaction descriptor
|
||||||
memset(t, 0, sizeof(parlio_tx_trans_desc_t));
|
memset(t, 0, sizeof(parlio_tx_trans_desc_t));
|
||||||
t->payload = payload;
|
t->payload = payload;
|
||||||
t->payload_bits = payload_bits;
|
t->payload_bits = payload_bits;
|
||||||
t->idle_value = config->idle_value & tx_unit->idle_value_mask;
|
t->idle_value = config->idle_value & tx_unit->idle_value_mask;
|
||||||
|
t->flags.loop_transmission = config->flags.loop_transmission;
|
||||||
|
|
||||||
// send the transaction descriptor to progress queue
|
// send the transaction descriptor to progress queue
|
||||||
ESP_RETURN_ON_FALSE(xQueueSend(tx_unit->trans_queues[PARLIO_TX_QUEUE_PROGRESS], &t, 0) == pdTRUE,
|
ESP_RETURN_ON_FALSE(xQueueSend(tx_unit->trans_queues[PARLIO_TX_QUEUE_PROGRESS], &t, 0) == pdTRUE,
|
||||||
ESP_ERR_INVALID_STATE, TAG, "failed to send transaction descriptor to progress queue");
|
ESP_ERR_INVALID_STATE, TAG, "failed to send transaction descriptor to progress queue");
|
||||||
tx_unit->num_trans_inflight++;
|
tx_unit->num_trans_inflight++;
|
||||||
|
|
||||||
// check if we need to start one pending transaction
|
// check if we need to start one pending transaction
|
||||||
parlio_tx_fsm_t expected_fsm = PARLIO_TX_FSM_ENABLE;
|
parlio_tx_fsm_t expected_fsm = PARLIO_TX_FSM_ENABLE;
|
||||||
if (atomic_compare_exchange_strong(&tx_unit->fsm, &expected_fsm, PARLIO_TX_FSM_RUN_WAIT)) {
|
if (atomic_compare_exchange_strong(&tx_unit->fsm, &expected_fsm, PARLIO_TX_FSM_RUN_WAIT)) {
|
||||||
// check if we need to start one transaction
|
// check if we need to start one transaction
|
||||||
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_PROGRESS], &t, 0) == pdTRUE) {
|
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_PROGRESS], &t, 0) == pdTRUE) {
|
||||||
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_RUN);
|
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_RUN);
|
||||||
parlio_tx_do_transaction(tx_unit, t);
|
parlio_tx_do_transaction(tx_unit, t);
|
||||||
} else {
|
} else {
|
||||||
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_ENABLE);
|
atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_ENABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -291,7 +291,7 @@ TEST_CASE("parallel_tx_clock_gating", "[paralio_tx]")
|
|||||||
#endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING
|
#endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING
|
||||||
|
|
||||||
#if SOC_PSRAM_DMA_CAPABLE
|
#if SOC_PSRAM_DMA_CAPABLE
|
||||||
TEST_CASE("parlio can transmit PSRAM buffer", "[parlio_tx]")
|
TEST_CASE("parlio_tx_can_transmit_PSRAM_buffer", "[parlio_tx]")
|
||||||
{
|
{
|
||||||
printf("install parlio tx unit\r\n");
|
printf("install parlio tx unit\r\n");
|
||||||
parlio_tx_unit_handle_t tx_unit = NULL;
|
parlio_tx_unit_handle_t tx_unit = NULL;
|
||||||
@@ -447,3 +447,85 @@ TEST_CASE("parallel tx unit use external non-free running clock", "[parlio_tx]")
|
|||||||
TEST_ESP_OK(gpio_reset_pin(config.data_gpio_nums[i]));
|
TEST_ESP_OK(gpio_reset_pin(config.data_gpio_nums[i]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
|
TEST_CASE("parlio_tx_loop_transmission", "[parlio_tx]")
|
||||||
|
{
|
||||||
|
printf("install parlio tx unit\r\n");
|
||||||
|
parlio_tx_unit_handle_t tx_unit = NULL;
|
||||||
|
parlio_tx_unit_config_t config = {
|
||||||
|
.clk_src = PARLIO_CLK_SRC_DEFAULT,
|
||||||
|
.data_width = 8,
|
||||||
|
.clk_in_gpio_num = -1, // use internal clock source
|
||||||
|
.valid_gpio_num = -1,
|
||||||
|
.clk_out_gpio_num = TEST_CLK_GPIO,
|
||||||
|
.data_gpio_nums = {
|
||||||
|
TEST_DATA0_GPIO,
|
||||||
|
TEST_DATA1_GPIO,
|
||||||
|
TEST_DATA2_GPIO,
|
||||||
|
TEST_DATA3_GPIO,
|
||||||
|
TEST_DATA4_GPIO,
|
||||||
|
TEST_DATA5_GPIO,
|
||||||
|
TEST_DATA6_GPIO,
|
||||||
|
TEST_DATA7_GPIO,
|
||||||
|
},
|
||||||
|
.output_clk_freq_hz = 10 * 1000 * 1000,
|
||||||
|
.trans_queue_depth = 3,
|
||||||
|
.max_transfer_size = 256,
|
||||||
|
.bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB,
|
||||||
|
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit));
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_enable(tx_unit));
|
||||||
|
|
||||||
|
printf("send packets and check event is fired\r\n");
|
||||||
|
parlio_transmit_config_t transmit_config = {
|
||||||
|
.idle_value = 0x00,
|
||||||
|
.flags.loop_transmission = true,
|
||||||
|
};
|
||||||
|
__attribute__((aligned(64))) uint8_t payload_loop1[256] = {0};
|
||||||
|
__attribute__((aligned(64))) uint8_t payload_loop2[256] = {0};
|
||||||
|
__attribute__((aligned(64))) uint8_t payload_oneshot[256] = {0};
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
payload_loop1[i] = i;
|
||||||
|
payload_loop2[i] = 255 - i;
|
||||||
|
payload_oneshot[i] = i * 2 + 1;
|
||||||
|
}
|
||||||
|
if (parlio_ll_tx_support_dma_eof(NULL)) { // for some chips, only support in particular ECO version
|
||||||
|
transmit_config.flags.loop_transmission = true;
|
||||||
|
int lopp_count = 3;
|
||||||
|
while (lopp_count--) {
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload_loop1, 256 * sizeof(uint8_t) * 8, &transmit_config));
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
// Should be sent after the previous frame has been completely sent
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload_loop2, 256 * sizeof(uint8_t) * 8, &transmit_config));
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
transmit_config.flags.loop_transmission = false;
|
||||||
|
// should be pending in queue
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload_oneshot, 256 * sizeof(uint8_t) * 8, &transmit_config));
|
||||||
|
transmit_config.flags.loop_transmission = true;
|
||||||
|
// there is a oneshot trans in queue, should also be pending in queue
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload_loop1, 256 * sizeof(uint8_t) * 8, &transmit_config));
|
||||||
|
|
||||||
|
TEST_ESP_ERR(ESP_ERR_TIMEOUT, parlio_tx_unit_wait_all_done(tx_unit, 50));
|
||||||
|
|
||||||
|
// stop infinite loop transmission
|
||||||
|
parlio_tx_unit_disable(tx_unit);
|
||||||
|
// We should see 1 oneshot frame and 1 loop transmission (both pending in queue)
|
||||||
|
parlio_tx_unit_enable(tx_unit);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
// stop the second infinite loop transmission
|
||||||
|
parlio_tx_unit_disable(tx_unit);
|
||||||
|
parlio_tx_unit_enable(tx_unit);
|
||||||
|
} else {
|
||||||
|
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, parlio_tx_unit_transmit(tx_unit, payload_loop1, 256 * sizeof(uint8_t) * 8, &transmit_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_wait_all_done(tx_unit, -1));
|
||||||
|
TEST_ESP_OK(parlio_tx_unit_disable(tx_unit));
|
||||||
|
TEST_ESP_OK(parlio_del_tx_unit(tx_unit));
|
||||||
|
}
|
||||||
|
#endif // SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -474,12 +474,24 @@ static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t b
|
|||||||
dev->tx_data_cfg.tx_bitlen = bitlen;
|
dev->tx_data_cfg.tx_bitlen = bitlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if tx size can be determined by DMA
|
||||||
|
*
|
||||||
|
* @param dev Parallel IO register base address (not used)
|
||||||
|
*/
|
||||||
|
static inline bool parlio_ll_tx_support_dma_eof(parl_io_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the condition to generate the TX EOF event
|
* @brief Set the condition to generate the TX EOF event
|
||||||
*
|
*
|
||||||
* @param dev Parallel IO register base address
|
* @param dev Parallel IO register base address
|
||||||
* @param cond TX EOF condition
|
* @param cond TX EOF condition
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
||||||
{
|
{
|
||||||
dev->tx_genrl_cfg.tx_eof_gen_sel = cond;
|
dev->tx_genrl_cfg.tx_eof_gen_sel = cond;
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -44,6 +44,11 @@ typedef enum {
|
|||||||
PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */
|
PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */
|
||||||
} parlio_ll_rx_eof_cond_t;
|
} parlio_ll_rx_eof_cond_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PARLIO_LL_TX_EOF_COND_DATA_LEN, /*!< TX unit generates EOF event when it transmits particular data bit length that specified in `tx_bitlen`. */
|
||||||
|
PARLIO_LL_TX_EOF_COND_DMA_EOF, /*!< TX unit generates EOF event when the DMA EOF takes place */
|
||||||
|
} parlio_ll_tx_eof_cond_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable or disable the parlio peripheral APB clock
|
* @brief Enable or disable the parlio peripheral APB clock
|
||||||
*
|
*
|
||||||
@@ -450,6 +455,19 @@ static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t b
|
|||||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_cfg0, tx_bytelen, bitlen / 8);
|
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_cfg0, tx_bytelen, bitlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the condition to generate the TX EOF event (this chip does not support)
|
||||||
|
*
|
||||||
|
* @param dev Parallel IO register base address (not used)
|
||||||
|
* @param cond TX EOF condition (not used)
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
||||||
|
{
|
||||||
|
(void) dev;
|
||||||
|
HAL_ASSERT(cond == PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Whether to enable the TX clock gating
|
* @brief Whether to enable the TX clock gating
|
||||||
*
|
*
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -48,6 +48,11 @@ typedef enum {
|
|||||||
PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */
|
PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */
|
||||||
} parlio_ll_rx_eof_cond_t;
|
} parlio_ll_rx_eof_cond_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PARLIO_LL_TX_EOF_COND_DATA_LEN, /*!< TX unit generates EOF event when it transmits particular data bit length that specified in `tx_bitlen`. */
|
||||||
|
PARLIO_LL_TX_EOF_COND_DMA_EOF, /*!< TX unit generates EOF event when the DMA EOF takes place */
|
||||||
|
} parlio_ll_tx_eof_cond_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable or disable the parlio peripheral APB clock
|
* @brief Enable or disable the parlio peripheral APB clock
|
||||||
*
|
*
|
||||||
@@ -475,6 +480,29 @@ static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t b
|
|||||||
dev->tx_data_cfg.tx_bitlen = bitlen;
|
dev->tx_data_cfg.tx_bitlen = bitlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if tx size can be determined by DMA
|
||||||
|
*
|
||||||
|
* @param dev Parallel IO register base address (not used)
|
||||||
|
*/
|
||||||
|
static inline bool parlio_ll_tx_support_dma_eof(parl_io_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
return ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the condition to generate the TX EOF event
|
||||||
|
*
|
||||||
|
* @param dev Parallel IO register base address
|
||||||
|
* @param cond TX EOF condition
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
||||||
|
{
|
||||||
|
dev->tx_genrl_cfg.tx_eof_gen_sel = cond;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Whether to enable the TX clock gating
|
* @brief Whether to enable the TX clock gating
|
||||||
*
|
*
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -523,12 +523,24 @@ static inline void parlio_ll_tx_set_trans_bit_len(parl_io_dev_t *dev, uint32_t b
|
|||||||
dev->tx_data_cfg.tx_bitlen = bitlen;
|
dev->tx_data_cfg.tx_bitlen = bitlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if tx size can be determined by DMA
|
||||||
|
*
|
||||||
|
* @param dev Parallel IO register base address (not used)
|
||||||
|
*/
|
||||||
|
static inline bool parlio_ll_tx_support_dma_eof(parl_io_dev_t *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the condition to generate the TX EOF event
|
* @brief Set the condition to generate the TX EOF event
|
||||||
*
|
*
|
||||||
* @param dev Parallel IO register base address
|
* @param dev Parallel IO register base address
|
||||||
* @param cond TX EOF condition
|
* @param cond TX EOF condition
|
||||||
*/
|
*/
|
||||||
|
__attribute__((always_inline))
|
||||||
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
static inline void parlio_ll_tx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_tx_eof_cond_t cond)
|
||||||
{
|
{
|
||||||
dev->tx_genrl_cfg.tx_eof_gen_sel = cond;
|
dev->tx_genrl_cfg.tx_eof_gen_sel = cond;
|
||||||
|
@@ -987,7 +987,7 @@ config SOC_PARLIO_TRANS_BIT_ALIGN
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SOC_PARLIO_TX_SIZE_BY_DMA
|
config SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
@@ -385,7 +385,7 @@
|
|||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
||||||
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
||||||
#define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */
|
#define SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION 1 /*!< Support loop transmission */
|
||||||
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
||||||
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
||||||
|
|
||||||
|
@@ -947,6 +947,10 @@ config SOC_PARLIO_TRANS_BIT_ALIGN
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
config SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@@ -374,6 +374,7 @@
|
|||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
||||||
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
||||||
|
#define SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION 1 /*!< Support loop transmission. Only avliable in chip version above 1.2 */
|
||||||
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
||||||
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -186,6 +186,14 @@ extern "C" {
|
|||||||
* Parallel TX general configuration register.
|
* Parallel TX general configuration register.
|
||||||
*/
|
*/
|
||||||
#define PARL_IO_TX_GENRL_CFG_REG (DR_REG_PARL_IO_BASE + 0x18)
|
#define PARL_IO_TX_GENRL_CFG_REG (DR_REG_PARL_IO_BASE + 0x18)
|
||||||
|
/** PARL_IO_TX_EOF_GEN_SEL : R/W; bitpos: [13]; default: 0;
|
||||||
|
* Configures the tx eof generated mechanism. 1'b0: eof generated by data bit length.
|
||||||
|
* 1'b1: eof generated by DMA eof.
|
||||||
|
*/
|
||||||
|
#define PARL_IO_TX_EOF_GEN_SEL (BIT(13))
|
||||||
|
#define PARL_IO_TX_EOF_GEN_SEL_M (PARL_IO_TX_EOF_GEN_SEL_V << PARL_IO_TX_EOF_GEN_SEL_S)
|
||||||
|
#define PARL_IO_TX_EOF_GEN_SEL_V 0x00000001U
|
||||||
|
#define PARL_IO_TX_EOF_GEN_SEL_S 13
|
||||||
/** PARL_IO_TX_IDLE_VALUE : R/W; bitpos: [29:14]; default: 0;
|
/** PARL_IO_TX_IDLE_VALUE : R/W; bitpos: [29:14]; default: 0;
|
||||||
* Configures bus value of transmitter in IDLE state.
|
* Configures bus value of transmitter in IDLE state.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +179,12 @@ typedef union {
|
|||||||
*/
|
*/
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t reserved_0:14;
|
uint32_t reserved_0:13;
|
||||||
|
/** tx_eof_gen_sel : R/W; bitpos: [13]; default: 0;
|
||||||
|
* Configures the tx eof generated mechanism. 1'b0: eof generated by data bit length.
|
||||||
|
* 1'b1: eof generated by DMA eof.
|
||||||
|
*/
|
||||||
|
uint32_t tx_eof_gen_sel:1;
|
||||||
/** tx_idle_value : R/W; bitpos: [29:14]; default: 0;
|
/** tx_idle_value : R/W; bitpos: [29:14]; default: 0;
|
||||||
* Configures bus value of transmitter in IDLE state.
|
* Configures bus value of transmitter in IDLE state.
|
||||||
*/
|
*/
|
||||||
|
@@ -1371,7 +1371,7 @@ config SOC_PARLIO_TRANS_BIT_ALIGN
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SOC_PARLIO_TX_SIZE_BY_DMA
|
config SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
@@ -488,7 +488,7 @@
|
|||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */
|
||||||
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */
|
||||||
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
#define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */
|
||||||
#define SOC_PARLIO_TX_SIZE_BY_DMA 1 /*!< Transaction length is controlled by DMA instead of indicated by register */
|
#define SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION 1 /*!< Support loop transmission */
|
||||||
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
#define SOC_PARLIO_SUPPORT_SLEEP_RETENTION 1 /*!< Support back up registers before sleep */
|
||||||
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
#define SOC_PARLIO_SUPPORT_SPI_LCD 1 /*!< Support to drive SPI interfaced LCD */
|
||||||
#define SOC_PARLIO_SUPPORT_I80_LCD 1 /*!< Support to drive I80 interfaced LCD */
|
#define SOC_PARLIO_SUPPORT_I80_LCD 1 /*!< Support to drive I80 interfaced LCD */
|
||||||
|
Reference in New Issue
Block a user