kopia lustrzana https://github.com/espressif/esp-idf
335 wiersze
21 KiB
C
335 wiersze
21 KiB
C
|
/*
|
||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <stddef.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include "esp_err.h"
|
||
|
#include "driver/parlio_types.h"
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* @brief Parallel IO RX unit configuration
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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 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 */
|
||
|
struct {
|
||
|
uint32_t free_clk : 1; /*!< 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 : 1; /*!< 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: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
|
||
|
uint32_t io_no_init: 1; /*!< Set to skip initializing the GPIO, but only attach the pralio rx signals to those GPIOs via IO Matrix.
|
||
|
So that the signals that have attached to those GPIO won't be overwritten. Mainly used for self communication or self monitoring */
|
||
|
} flags; /*!< RX driver flags */
|
||
|
} parlio_rx_unit_config_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Create a Parallel IO RX unit
|
||
|
*
|
||
|
* @param[in] config Parallel IO RX unit configuration
|
||
|
* @param[out] ret_unit Returned Parallel IO RX unit handle
|
||
|
* @return
|
||
|
* - 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_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_unit_handle_t *ret_unit);
|
||
|
|
||
|
/**
|
||
|
* @brief Delete a Parallel IO RX unit
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @return
|
||
|
* - 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_del_rx_unit(parlio_rx_unit_handle_t rx_unit);
|
||
|
|
||
|
/**
|
||
|
* @brief Configuration of level delimiter
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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. */
|
||
|
struct {
|
||
|
uint32_t active_low_en: 1; /*!< Set true to set the valid signal active when the level is low,
|
||
|
otherwise, the valid signal becomes active when its level is high */
|
||
|
} flags; /*!< Extra flags */
|
||
|
} parlio_rx_level_delimiter_config_t;
|
||
|
|
||
|
/**
|
||
|
* @brief 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
|
||
|
*
|
||
|
* @param[in] config Level delimiter configuration
|
||
|
* @param[out] ret_delimiter Returned delimiter handle
|
||
|
* @return
|
||
|
* - 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_level_delimiter(const parlio_rx_level_delimiter_config_t *config,
|
||
|
parlio_rx_delimiter_handle_t *ret_delimiter);
|
||
|
|
||
|
/**
|
||
|
* @brief Configuration of pulse delimiter
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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. */
|
||
|
struct {
|
||
|
uint32_t start_bit_included: 1; /*!< Whether data bit is included in the start pulse */
|
||
|
uint32_t end_bit_included: 1; /*!< Whether data bit is included in the end pulse, only valid when `has_end_pulse` is true */
|
||
|
uint32_t has_end_pulse: 1; /*!< Whether there's an end pulse to terminate the transaction,
|
||
|
if no, the transaction will be terminated by user configured transcation length */
|
||
|
uint32_t pulse_invert: 1; /*!< Whether to invert the pulse */
|
||
|
} flags; /*!< Extra flags */
|
||
|
} parlio_rx_pulse_delimiter_config_t;
|
||
|
|
||
|
/**
|
||
|
* @brief 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
|
||
|
*
|
||
|
* @param[in] config Pulse delimiter configuration
|
||
|
* @param[out] ret_delimiter Returned delimiter handle
|
||
|
* @return
|
||
|
* - 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_pulse_delimiter(const parlio_rx_pulse_delimiter_config_t *config,
|
||
|
parlio_rx_delimiter_handle_t *ret_delimiter);
|
||
|
|
||
|
/**
|
||
|
* @brief Configuration of soft delimiter
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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 */
|
||
|
} parlio_rx_soft_delimiter_config_t;
|
||
|
|
||
|
/**
|
||
|
* @brief 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
|
||
|
* @param[in] config Soft delimiter configuration
|
||
|
* @param[out] ret_delimiter Returned delimiter handle
|
||
|
* @return
|
||
|
* - 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_new_rx_soft_delimiter(const parlio_rx_soft_delimiter_config_t *config,
|
||
|
parlio_rx_delimiter_handle_t *ret_delimiter);
|
||
|
|
||
|
/**
|
||
|
* @brief 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
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @param[in] delimiter Delimiter handle
|
||
|
* @param[in] start_stop Set true to start, set false to stop
|
||
|
* @return
|
||
|
* - 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_rx_soft_delimiter_start_stop(parlio_rx_unit_handle_t rx_unit, parlio_rx_delimiter_handle_t delimiter, bool start_stop);
|
||
|
|
||
|
/**
|
||
|
* @brief Delete the delimiter
|
||
|
* @note To delete the delimiter safely, please delete it after disable all the RX units
|
||
|
*
|
||
|
* @param[in] delimiter Delimiter handle
|
||
|
* @return
|
||
|
* - 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_del_rx_delimiter(parlio_rx_delimiter_handle_t delimiter);
|
||
|
|
||
|
/**
|
||
|
* @brief Enable the Parallel IO RX unit
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @param[in] reset_queue 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.
|
||
|
* @return
|
||
|
* - 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_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queue);
|
||
|
|
||
|
/**
|
||
|
* @brief Disable the Parallel IO RX unit
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @return
|
||
|
* - 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_disable(parlio_rx_unit_handle_t rx_unit);
|
||
|
|
||
|
/**
|
||
|
* @brief Configuration of a receive transaction
|
||
|
*/
|
||
|
typedef struct {
|
||
|
parlio_rx_delimiter_handle_t delimiter; /*!< The delimiter of this receiving transaction */
|
||
|
struct {
|
||
|
uint32_t partial_rx_en: 1; /*!< Whether this is an infinite transaction that supposed to receive continuously and partially */
|
||
|
uint32_t indirect_mount: 1; /*!< 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.
|
||
|
*/
|
||
|
} flags; /*!< Extra flags */
|
||
|
} parlio_receive_config_t;
|
||
|
|
||
|
/**
|
||
|
* @brief 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.
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @param[in] payload The payload buffer pointer
|
||
|
* @param[in] payload_size The size of the payload buffer, in bytes.
|
||
|
* @param[in] recv_cfg The configuration of this receive transaction
|
||
|
* @return
|
||
|
* - 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_receive(parlio_rx_unit_handle_t rx_unit,
|
||
|
void *payload,
|
||
|
size_t payload_size,
|
||
|
const parlio_receive_config_t* recv_cfg);
|
||
|
|
||
|
/**
|
||
|
* @brief 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).
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @param[in] timeout_ms Timeout in milliseconds, `-1` means to wait forever (software timeout)
|
||
|
* @return
|
||
|
* - 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_wait_all_done(parlio_rx_unit_handle_t rx_unit, int timeout_ms);
|
||
|
|
||
|
/**
|
||
|
* @brief Event callback data
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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 */
|
||
|
} parlio_rx_event_data_t;
|
||
|
|
||
|
/**
|
||
|
* @brief The template of the Parallel IO RX callback function
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that given from ISR
|
||
|
* @param[in] edata The event data that given from ISR
|
||
|
* @param[in] user_data The user specified data that given while registering the callbacks
|
||
|
*
|
||
|
* @return
|
||
|
* - True: to awoke high priority tasks
|
||
|
* - False: not to awoke high priority tasks
|
||
|
*/
|
||
|
typedef bool (*parlio_rx_callback_t)(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data);
|
||
|
|
||
|
/**
|
||
|
* @brief Parallel IO RX event callbacks
|
||
|
*/
|
||
|
typedef struct {
|
||
|
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 */
|
||
|
} parlio_rx_event_callbacks_t;
|
||
|
|
||
|
/**
|
||
|
* @brief Register event callbacks for Parallel IO RX unit
|
||
|
*
|
||
|
* @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit`
|
||
|
* @param[in] cbs Callback group, set callback to NULL to deregister the corresponding callback (callback group pointer shouldn't be NULL)
|
||
|
* @param[in] user_data User specified data that will be transported to the callbacks
|
||
|
* @return
|
||
|
* - 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
|
||
|
*/
|
||
|
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);
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|