mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-29 18:27:20 +02:00
feat(parlio_tx): support to use dma eof on esp32c5
This commit is contained in:
committed by
Chen Ji Chang
parent
f10dcd6140
commit
00b1d66c6e
@ -342,8 +342,13 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
|
||||
// set sample clock edge
|
||||
parlio_ll_tx_set_sample_clock_edge(hal->regs, config->sample_edge);
|
||||
|
||||
#if SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
// always use DMA EOF as the Parlio TX EOF if supported
|
||||
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DMA_EOF);
|
||||
#else
|
||||
// In default, use DATA LEN EOF as the Parlio TX EOF
|
||||
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
||||
#endif // SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
||||
// clear any pending interrupt
|
||||
parlio_ll_clear_interrupt_status(hal->regs, PARLIO_LL_EVENT_TX_MASK);
|
||||
@ -460,6 +465,7 @@ static void parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_
|
||||
|
||||
if (t->flags.loop_transmission) {
|
||||
// Once a loop transmission is started, it cannot be stopped until it is disabled
|
||||
// If SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA is supported, setting the eof condition to PARLIO_LL_TX_EOF_COND_DMA_EOF again is harmless
|
||||
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DMA_EOF);
|
||||
}
|
||||
|
||||
@ -586,9 +592,11 @@ esp_err_t parlio_tx_unit_disable(parlio_tx_unit_handle_t tx_unit)
|
||||
parlio_ll_tx_start(hal->regs, false);
|
||||
parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_MASK, false);
|
||||
|
||||
#if !SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
// 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
|
||||
// change the EOF condition to be the data length, so the EOF will be triggered normally in the following transaction
|
||||
parlio_ll_tx_set_eof_condition(hal->regs, PARLIO_LL_TX_EOF_COND_DATA_LEN);
|
||||
#endif // !SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// release power management lock
|
||||
@ -620,12 +628,13 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p
|
||||
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 !SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
// check the max payload size if it's not a loop transmission and the DMA EOF is not supported
|
||||
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");
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid transfer size, max transfer size should be less than %d", PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8);
|
||||
}
|
||||
#endif // !SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
||||
size_t cache_line_size = 0;
|
||||
size_t alignment = 0;
|
||||
|
@ -8,6 +8,7 @@ endif()
|
||||
|
||||
if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED)
|
||||
list(APPEND srcs "test_parlio_bitscrambler.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_PARLIO_TX_ISR_CACHE_SAFE)
|
||||
list(APPEND srcs "test_parlio_tx_cache_safe.c")
|
||||
|
@ -598,3 +598,51 @@ TEST_CASE("parlio_tx_loop_transmission", "[parlio_tx]")
|
||||
TEST_ESP_OK(parlio_del_tx_unit(tx_unit));
|
||||
}
|
||||
#endif // SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||
|
||||
#if SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
TEST_CASE("parlio_tx can transmit buffer larger than max_size decided by datalen_eof", "[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 = 4,
|
||||
.clk_in_gpio_num = -1, // use internal clock source
|
||||
.valid_gpio_num = TEST_VALID_GPIO, // generate the valid signal
|
||||
.clk_out_gpio_num = TEST_CLK_GPIO,
|
||||
.data_gpio_nums = {
|
||||
TEST_DATA0_GPIO,
|
||||
TEST_DATA1_GPIO,
|
||||
TEST_DATA2_GPIO,
|
||||
TEST_DATA3_GPIO,
|
||||
},
|
||||
.output_clk_freq_hz = 10 * 1000 * 1000,
|
||||
.trans_queue_depth = 1,
|
||||
.max_transfer_size = 100 * 1024,
|
||||
.bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB,
|
||||
.sample_edge = PARLIO_SAMPLE_EDGE_POS,
|
||||
.flags.clk_gate_en = true,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit));
|
||||
TEST_ESP_OK(parlio_tx_unit_enable(tx_unit));
|
||||
|
||||
const size_t buffer_size = 100 * 1024; // 100KB, larger than the 65535 bytes limit
|
||||
uint8_t *buffer = heap_caps_malloc(buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_NULL(buffer);
|
||||
for (int i = 0; i < buffer_size; i++) {
|
||||
buffer[i] = i;
|
||||
}
|
||||
|
||||
parlio_transmit_config_t transmit_config = {
|
||||
.idle_value = 0x00,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, buffer, buffer_size * 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));
|
||||
free(buffer);
|
||||
}
|
||||
#endif // SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
@ -1019,6 +1019,10 @@ config SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
@ -392,6 +392,7 @@
|
||||
#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_TX_SUPPORT_LOOP_TRANSMISSION 1 /*!< Support loop transmission */
|
||||
#define SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA 1 /*!< Support to treat DMA EOF as TX unit EOF */
|
||||
#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_I80_LCD 1 /*!< Support to drive I80 interfaced LCD */
|
||||
|
@ -320,6 +320,12 @@ The waveform of the external clock input is shown below:
|
||||
|
||||
After writing the BitScrambler program, we can enable it by calling :cpp:func:`parlio_tx_unit_decorate_bitscrambler`. And configure the :cpp:member:`parlio_transmit_config_t::bitscrambler_program` to point to the binary file of the BitScrambler program. Different transmission transactions can use different BitScrambler programs. The binary file must conform to the BitScrambler assembly language specification, and will be loaded into the BitScrambler's instruction memory at runtime. For details on how to write and compile the BitScrambler program, please refer to :doc:`BitScrambler Programming Guide </api-reference/peripherals/bitscrambler>`.
|
||||
|
||||
.. only:: not SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
||||
.. note::
|
||||
|
||||
Due to hardware limitations, the bitstream generated by the BitScrambler cannot change the length compared to the original bitstream, otherwise transmission blocking or data loss may occur.
|
||||
|
||||
:cpp:func:`parlio_tx_unit_decorate_bitscrambler` and :cpp:func:`parlio_tx_unit_undecorate_bitscrambler` need to be used in pairs. When deleting the TX unit, you need to call :cpp:func:`parlio_tx_unit_undecorate_bitscrambler` first to remove the BitScrambler.
|
||||
|
||||
Power Management
|
||||
|
@ -320,6 +320,12 @@ TX 单元可以选择各种不同的时钟源,其中外部时钟源较为特
|
||||
|
||||
编写好比特调节器程序后,通过调用 :cpp:func:`parlio_tx_unit_decorate_bitscrambler` 启用比特调节器。并在 :cpp:member:`parlio_transmit_config_t::bitscrambler_program` 配置本次传输使用比特调节器程序的二进制文件。不同的传输事务可以使用不同的比特调节器程序。该二进制文件必须符合比特调节器的汇编语言规范,并且在运行时会被加载到比特调节器的指令存储器中。如何编写并编译比特调节器程序请参考 :doc:`比特调节器编程指南 </api-reference/peripherals/bitscrambler>`。
|
||||
|
||||
.. only:: not SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA
|
||||
|
||||
.. note::
|
||||
|
||||
由于硬件限制,使用比特调节器生成的比特流与原本比特流相比,长度不能发生变化,否则可能会发生传输阻塞或数据丢失。
|
||||
|
||||
:cpp:func:`parlio_tx_unit_decorate_bitscrambler` 和 :cpp:func:`parlio_tx_unit_undecorate_bitscrambler` 需要成对使用。在删除 TX 单元时,需要先调用 :cpp:func:`parlio_tx_unit_undecorate_bitscrambler` 移除比特调节器。
|
||||
|
||||
电源管理
|
||||
|
@ -126,7 +126,7 @@ void example_init_parlio_panel(esp_lcd_panel_io_handle_t *io_handle)
|
||||
#endif
|
||||
},
|
||||
.data_width = CONFIG_EXAMPLE_LCD_PARLIO_DATA_WIDTH,
|
||||
.max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t),
|
||||
.max_transfer_bytes = EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(uint16_t),
|
||||
.dma_burst_size = EXAMPLE_DMA_BURST_SIZE,
|
||||
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
|
||||
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
|
||||
|
Reference in New Issue
Block a user