# Parallel IO RX Driver

[中文]

## Introduction

The Parallel IO RX unit typically supports the following scenarios:

- High-speed data acquisition, such as camera and sensor data reading

- High-speed parallel communication with other hosts as a slave device

## Application Examples

- peripherals/parlio/parlio_rx/logic_analyzer demonstrates how to use the Parallel IO RX peripheral to implement a logic analyzer. This analyzer can sample data on multiple GPIOs at high frequency, monitor internal or external signals, and save the raw sampled data to Flash or output it through a TCP stream.

## API Reference

### Header File

- components/esp_driver_parlio/include/driver/parlio_rx.h

- This header file can be included with:

  >     #include "driver/parlio_rx.h"

- This header file is a part of the API provided by the `esp_driver_parlio` component. To declare that your component depends on `esp_driver_parlio`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_parlio

  > or

  >     PRIV_REQUIRES esp_driver_parlio

### Functions

esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_unit_handle_t *ret_unit)

  Create a Parallel IO RX unit.

  Parameters:

    - config -- [in] Parallel IO RX unit configuration

    - ret_unit -- [out] Returned Parallel IO RX unit handle

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the rx unit configuration

    - ESP_ERR_NOT_FOUND No available rx unit found

    - ESP_ERR_NO_MEM No enough memory for the rx unit resources

    - ESP_OK Success to allocate the rx unit

esp_err_t parlio_del_rx_unit(parlio_rx_unit_handle_t rx_unit)

  Delete a Parallel IO RX unit.

  Parameters:

    rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

  Returns:

    - ESP_ERR_INVALID_ARG rx_unit is NULL

    - ESP_ERR_INVALID_STATE The rx unit is enabled, can't delete an enabled rx unit

    - ESP_OK Success to delete the rx unit

esp_err_t parlio_new_rx_level_delimiter(const parlio_rx_level_delimiter_config_t *config, parlio_rx_delimiter_handle_t *ret_delimiter)

  Create a level delimiter.

  Note

  This function only allocate the software resources, the hardware configurations will lazy installed while the transaction that using this delimiter start processing

  Note

  The enable signal must be aligned with the valid data.

  Note

  There're at most `SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1` IO pins left for RXD

  Parameters:

    - config -- [in] Level delimiter configuration

    - ret_delimiter -- [out] Returned delimiter handle

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the level delimiter configuration

    - ESP_ERR_NO_MEM No enough memory for the level delimiter resources

    - ESP_OK Success to allocate the level delimiter

esp_err_t parlio_new_rx_pulse_delimiter(const parlio_rx_pulse_delimiter_config_t *config, parlio_rx_delimiter_handle_t *ret_delimiter)

  Create a pulse delimiter.

  Note

  This function only allocate the software resources, the hardware configurations will lazy installed while the transaction that using this delimiter start processing

  Note

  There're at most `SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1` IO pins left for RXD

  Parameters:

    - config -- [in] Pulse delimiter configuration

    - ret_delimiter -- [out] Returned delimiter handle

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the pulse delimiter configuration

    - ESP_ERR_NO_MEM No enough memory for the pulse delimiter resources

    - ESP_OK Success to allocate the pulse delimiter

esp_err_t parlio_new_rx_soft_delimiter(const parlio_rx_soft_delimiter_config_t *config, parlio_rx_delimiter_handle_t *ret_delimiter)

  Create a pulse delimiter.

  Note

  This function only allocate the software resources, the hardware configurations will lazy installed while the transaction that using this delimiter start processing

  Parameters:

    - config -- [in] Soft delimiter configuration

    - ret_delimiter -- [out] Returned delimiter handle

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the soft delimiter configuration

    - ESP_ERR_NO_MEM No enough memory for the soft delimiter resources

    - ESP_OK Success to allocate the soft delimiter

esp_err_t parlio_rx_soft_delimiter_start_stop(parlio_rx_unit_handle_t rx_unit, parlio_rx_delimiter_handle_t delimiter, bool start_stop)

  Start/stop the soft delimiter.

  Note

  Soft delimiter need to start or stop manually because it has no validating/enabling signal to indicate the data has started or stopped

  Parameters:

    - rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

    - delimiter -- [in] Delimiter handle

    - start_stop -- [in] Set true to start, set false to stop

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or not soft delimiter

    - ESP_ERR_INVALID_STATE The rx unit not enabled

    - ESP_OK Success to start or stop the soft delimiter

esp_err_t parlio_del_rx_delimiter(parlio_rx_delimiter_handle_t delimiter)

  Delete the delimiter.

  Note

  To delete the delimiter safely, please delete it after disable all the RX units

  Parameters:

    delimiter -- [in] Delimiter handle

  Returns:

    - ESP_ERR_INVALID_ARG The input delimiter is NULL

    - ESP_ERR_INVALID_STATE The delimiter is on receiving

    - ESP_OK Success to delete the delimiter

esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queue)

  Enable the Parallel IO RX unit.

  Parameters:

    - rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

    - reset_queue -- [in] Whether to reset the receiving queue. If set to false, the legacy receive transactions in the queue are still available, If set to true, the legacy receive transactions in the queue are dropped.

  Returns:

    - ESP_ERR_INVALID_ARG The input rx_unit is NULL

    - ESP_ERR_INVALID_STATE The rx unit has been enabled

    - ESP_OK Success to enable the rx unit

esp_err_t parlio_rx_unit_disable(parlio_rx_unit_handle_t rx_unit)

  Disable the Parallel IO RX unit.

  Parameters:

    rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

  Returns:

    - ESP_ERR_INVALID_ARG The input rx_unit is NULL

    - ESP_ERR_INVALID_STATE The rx unit has been disabled

    - ESP_OK Success to disable the rx unit

esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, void *payload, size_t payload_size, const parlio_receive_config_t *recv_cfg)

  Receive data by Parallel IO RX unit.

  Note

  This is a non-blocking and asynchronous function. To block or realize synchronous receive, please call `parlio_rx_unit_wait_all_done` after this function

  Note

  The receive transaction will start immediately when there is not other transaction on receiving, Otherwise it will be sent to the transaction queue to wait for the bus.

  Parameters:

    - rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

    - payload -- [in] The payload buffer pointer

    - payload_size -- [in] The size of the payload buffer, in bytes.

    - recv_cfg -- [in] The configuration of this receive transaction

  Returns:

    - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the receive configuration

    - ESP_ERR_NO_MEM No memory for the internal DMA buffer (only when parlio_receive_config_t::indirect_mount enabled)

    - ESP_ERR_INVALID_STATE Transaction queue is full, failed to queue the current transaction. Or the internal buffer is under using by an infinite transaction, can't allocate a new one

    - ESP_OK Success to queue the current receiving transaction

esp_err_t parlio_rx_unit_wait_all_done(parlio_rx_unit_handle_t rx_unit, int timeout_ms)

  Wait for all pending RX transactions done.

  Note

  This function will block until all receiving transactions done or timeout. When timeout occurs, either the timeout limitation too short for all transactions done, or the peripheral got stuck and no more interrupts trigger (e.g., external clock stopped).

  Parameters:

    - rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

    - timeout_ms -- [in] Timeout in milliseconds, `-1` means to wait forever (software timeout)

  Returns:

    - ESP_ERR_INVALID_ARG The input rx_unit is NULL

    - ESP_ERR_TIMEOUT Wait for all transactions done timeout

    - ESP_OK All transaction done

esp_err_t parlio_rx_unit_register_event_callbacks(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_callbacks_t *cbs, void *user_data)

  Register event callbacks for Parallel IO RX unit.

  Parameters:

    - rx_unit -- [in] Parallel IO RX unit handle that created by `parlio_new_rx_unit`

    - cbs -- [in] Callback group, set callback to NULL to deregister the corresponding callback (callback group pointer shouldn't be NULL)

    - user_data -- [in] User specified data that will be transported to the callbacks

  Returns:

    - ESP_ERR_INVALID_ARG The input rx_unit is NULL

    - ESP_ERR_INVALID_STATE The rx unit has been enabled, callback should be registered before enabling the unit

    - ESP_OK Success to register the callbacks

### Structures

struct parlio_rx_unit_config_t

  Parallel IO RX unit configuration.

  Public Members

  size_t trans_queue_depth

    Depth of internal transaction queue

  size_t max_recv_size

    Maximum receive size in one transaction, in bytes. This decides the number of DMA nodes will be used for each transaction

  size_t dma_burst_size

    DMA burst size, in bytes

  size_t data_width

    Parallel IO data width, can set to 1/2/4/8/..., but can't be greater than PARLIO_RX_UNIT_MAX_DATA_WIDTH

  parlio_clock_source_t clk_src

    Parallel IO clock source

  uint32_t ext_clk_freq_hz

    The external source clock frequency. Only be valid when select PARLIO_CLK_SRC_EXTERNAL as clock source

  uint32_t exp_clk_freq_hz

    The expected sample/bit clock frequency, which is divided from the internal or external clock regarding the clock source

  gpio_num_t clk_in_gpio_num

    The the external clock input pin. Only be valid when select PARLIO_CLK_SRC_EXTERNAL as clock source. Set to -1 if not needed

  gpio_num_t clk_out_gpio_num

    The sample/bit clock output pin. Set to -1 if not needed

  gpio_num_t valid_gpio_num

    GPIO number of the valid signal. The signal on this pin is used to indicate whether the data on the data lines are valid. Only takes effect when using level or pulse delimiter, set to `-1` if only use the soft delimiter

  gpio_num_t data_gpio_nums[PARLIO_RX_UNIT_MAX_DATA_WIDTH]

    Parallel IO data GPIO numbers, set to `-1` if it's not used, The driver will take [0 .. (data_width - 1)] as the data pins

  uint32_t free_clk

    Whether the input external clock is a free-running clock. A free-running clock will always keep running (e.g. I2S bclk), a non-free-running clock will start when there are data transporting and stop when the bus idle (e.g. SPI). This flag only takes effect when select PARLIO_CLK_SRC_EXTERNAL as clock source

  uint32_t clk_gate_en

    Enable RX clock gating, only available when the clock direction is output(not supported on ESP32-C6) the output clock will be controlled by the valid gpio, i.e. high level of valid gpio to enable the clock output, low to disable

  uint32_t io_loop_back

    For debug/test, the signal output from the GPIO will be fed to the input path as well

  uint32_t io_no_init

    Deprecated. Driver won't change the GPIO configuration in inilization.

  uint32_t allow_pd

    Set to allow power down. When this flag set, the driver will backup/restore the PARLIO registers before/after entering/exist sleep mode. By this approach, the system can power off PARLIO's power domain. This can save power, but at the expense of more RAM being consumed.

  struct parlio_rx_unit_config_t flags

    RX driver flags

struct parlio_rx_level_delimiter_config_t

  Configuration of level delimiter.

  Public Members

  uint32_t valid_sig_line_id

    The data line id of valid/enable signal. The selected data line will be used as the valid/enable signal (i.e. level signal) in this delimiter. As the line of valid/enable signal is shared with the data line, this line_id will be conflict with the data line if set the id within 'data_width', therefore the range is (data_width, PARLIO_RX_UNIT_MAX_DATA_WIDTH].

  parlio_sample_edge_t sample_edge

    Parallel IO sample edge

  parlio_bit_pack_order_t bit_pack_order

    Set how we pack the bits into one bytes

  uint32_t eof_data_len

    Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) interrupt, if the data length is set to `0`, that mean the EOF will only triggers when the enable signal inactivated

  uint32_t timeout_ticks

    The number of source clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt The timeout counter starts when the valid/enable signal is invalid/disabled.

  uint32_t active_low_en

    Set true to set the valid signal active when the level is low, otherwise, the valid signal becomes active when its level is high

  struct parlio_rx_level_delimiter_config_t flags

    Extra flags

struct parlio_rx_pulse_delimiter_config_t

  Configuration of pulse delimiter.

  Public Members

  uint32_t valid_sig_line_id

    The data line id of valid/enable signal. The selected data line will be used as the valid/enable signal (i.e. pulse signal) in this delimiter. As the line of valid/enable signal is shared with the data line, this line_id will be conflict with the data line if set the id within 'data_width', therefore the range is (data_width, PARLIO_RX_UNIT_MAX_DATA_WIDTH].

  parlio_sample_edge_t sample_edge

    Parallel IO sample edge

  parlio_bit_pack_order_t bit_pack_order

    Set how we pack the bits into one bytes

  uint32_t eof_data_len

    Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) 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 `has_end_pulse` flag is set

  uint32_t timeout_ticks

    The number of source clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt The timeout counter starts when the valid/enable signal is invalid/disabled.

  uint32_t start_bit_included

    Whether data bit is included in the start pulse

  uint32_t end_bit_included

    Whether data bit is included in the end pulse, only valid when `has_end_pulse` is true

  uint32_t has_end_pulse

    Whether there's an end pulse to terminate the transaction, if no, the transaction will be terminated by user configured transaction length

  uint32_t pulse_invert

    Whether to invert the pulse

  struct parlio_rx_pulse_delimiter_config_t flags

    Extra flags

struct parlio_rx_soft_delimiter_config_t

  Configuration of soft delimiter.

  Public Members

  parlio_sample_edge_t sample_edge

    Parallel IO sample edge

  parlio_bit_pack_order_t bit_pack_order

    Set how we pack the bits into one bytes, set 1 to pack the bits into a byte from LSB, otherwise from MSB

  uint32_t eof_data_len

    Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) 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

struct parlio_receive_config_t

  Configuration of a receive transaction.

  Public Members

  parlio_rx_delimiter_handle_t delimiter

    The delimiter of this receiving transaction

  uint32_t partial_rx_en

    Whether this is an infinite transaction that supposed to receive continuously and partially

  uint32_t indirect_mount

    This flag only take effect when `partial_rx_en` is enabled. Enable this flag, an INTERNAL DMA buffer will be mounted to the DMA descriptor instead, The data will be copy to the payload in every interrupt. So that to guarantee the payload buffer is valid during the `on_receive_done` callback. Either `partial_rx_en` or `indirect_mount` is disabled, the user given finite payload will be mounted to the DMA descriptor directly. By default, the user given receive payload will be mounted to the DMA descriptor directly.

  struct parlio_receive_config_t flags

    Extra flags

struct parlio_rx_event_data_t

  Event callback data.

  Public Members

  parlio_rx_delimiter_handle_t delimiter

    The current delimiter of this receiving event

  void *data

    The data buffer address that just finished receiving

  size_t recv_bytes

    The number of received bytes in the data buffer

struct parlio_rx_event_callbacks_t

  Parallel IO RX event callbacks.

  Public Members

  parlio_rx_callback_t on_partial_receive

    Callback of received partial data

  parlio_rx_callback_t on_receive_done

    Callback of receiving transaction done

  parlio_rx_callback_t on_timeout

    Callback of hardware receiving timeout

### Type Definitions

typedef bool (*parlio_rx_callback_t)(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data)

  The template of the Parallel IO RX callback function.

  Param rx_unit:

    [in] Parallel IO RX unit handle that given from ISR

  Param edata:

    [in] The event data that given from ISR

  Param user_data:

    [in] The user specified data that given while registering the callbacks

  Return:

    - True: to awoke high priority tasks

    - False: not to awoke high priority tasks

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.