driver: pack peripherals

This commit is contained in:
laokaiyao
2023-01-31 14:36:21 +08:00
parent b97a98a703
commit f27cd67c00
116 changed files with 262 additions and 174 deletions
@@ -1,263 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "driver/dac_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DAC_SUPPORTED
/**
* @brief DAC channel mask
*
*/
typedef enum {
DAC_CHANNEL_MASK_CH0 = BIT(0), /*!< DAC channel 0 is GPIO25(ESP32) / GPIO17(ESP32S2) */
DAC_CHANNEL_MASK_CH1 = BIT(1), /*!< DAC channel 1 is GPIO26(ESP32) / GPIO18(ESP32S2) */
DAC_CHANNEL_MASK_ALL = BIT(0) | BIT(1), /*!< Both DAC channel 0 and channel 1 */
} dac_channel_mask_t;
typedef struct dac_continuous_s *dac_continuous_handle_t; /*!< DAC continuous channel handle */
/**
* @brief DAC continuous channels' configurations
*
*/
typedef struct {
dac_channel_mask_t chan_mask; /*!< DAC channels' mask for selecting which channels are used */
uint32_t desc_num; /*!< The number of DMA descriptor, at least 2 descriptors are required
* The number of descriptors is directly proportional to the max data buffer size while converting in cyclic output
* but only need to ensure it is greater than '1' in acyclic output
* Typically, suggest to set the number bigger than 5, in case the DMA stopped while sending a short buffer
*/
size_t buf_size; /*!< The DMA buffer size, should be within 32~4092 bytes. Each DMA buffer will be attached to a DMA descriptor,
* i.e. the number of DMA buffer will be equal to the DMA descriptor number
* The DMA buffer size is not allowed to be greater than 4092 bytes
* The total DMA buffer size equal to `desc_num * buf_size`
* Typically, suggest to set the size to the multiple of 4
*/
uint32_t freq_hz; /*!< The frequency of DAC conversion in continuous mode, unit: Hz
* The supported range is related to the target and the clock source.
* For the clock `DAC_DIGI_CLK_SRC_DEFAULT`: the range is 19.6 KHz to several MHz on ESP32
* and 77 Hz to several MHz on ESP32-S2.
* For the clock `DAC_DIGI_CLK_SRC_APLL`: the range is 648 Hz to several MHz on ESP32
* and 6 Hz to several MHz on ESP32-S2.
* Typically not suggest to set the frequency higher than 2 MHz, otherwise the severe distortion will appear
*/
int8_t offset; /*!< The offset of the DAC digital data. Range -128~127 */
dac_continuous_digi_clk_src_t clk_src; /*!< The clock source of digital controller, which can affect the range of supported frequency
* Currently `DAC_DIGI_CLK_SRC_DEFAULT` and `DAC_DIGI_CLK_SRC_APLL` are available
*/
dac_continuous_channel_mode_t chan_mode; /*!< The channel mode of continuous mode, only take effect when multiple channels enabled, depends converting the buffer alternately or simultaneously */
} dac_continuous_config_t;
/**
* @brief Event structure used in DAC event queue
*/
typedef struct {
void *buf; /*!< The pointer of DMA buffer that just finished sending */
size_t buf_size; /*!< The writable buffer size of the DMA buffer, equal to 'dac_continuous_config_t::buf_size' */
size_t write_bytes; /*!< The number of bytes that be written successfully */
} dac_event_data_t;
/**
* @brief DAC event callback
* @param[in] handle DAC channel handle, created from `dac_continuous_new_channels()`
* @param[in] event DAC event data
* @param[in] user_data User registered context, passed from `dac_continuous_register_event_callback()`
*
* @return Whether a high priority task has been waken up by this callback function
*/
typedef bool (*dac_isr_callback_t)(dac_continuous_handle_t handle, const dac_event_data_t *event, void *user_data);
/**
* @brief Group of DAC callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well.
*/
typedef struct {
dac_isr_callback_t on_convert_done; /**< Callback of data conversion done event
* An event data buffer previously loaded to the driver has been output and converted.
* The event data includes DMA buffer address and size that just finished converting.
*/
dac_isr_callback_t on_stop; /**< Callback of finished sending all the data.
* All loaded event data buffers are converted. Driver is pending for new data buffers to be loaded.
* The event data will be NULL in this callback.
*/
} dac_event_callbacks_t;
/**
* @brief Allocate new DAC channels in continuous mode
* @note The DAC channels can't be registered to continuous mode separately
*
* @param[in] cont_cfg Continuous mode configuration
* @param[out] ret_handle The returned continuous mode handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
* - ESP_ERR_NOT_FOUND Not found the available dma peripheral, might be occupied
* - ESP_ERR_NO_MEM No memory for the DAC continuous mode resources
* - ESP_OK Allocate the new DAC continuous mode success
*/
esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, dac_continuous_handle_t *ret_handle);
/**
* @brief Delete the DAC continuous handle
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channels have already been deregistered or not disabled
* - ESP_OK Delete the continuous channels success
*/
esp_err_t dac_continuous_del_channels(dac_continuous_handle_t handle);
/**
* @brief Enabled the DAC continuous mode
* @note Must enable the channels before
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channels have been enabled already
* - ESP_OK Enable the continuous output success
*/
esp_err_t dac_continuous_enable(dac_continuous_handle_t handle);
/**
* @brief Disable the DAC continuous mode
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channels have been enabled already
* - ESP_OK Disable the continuous output success
*/
esp_err_t dac_continuous_disable(dac_continuous_handle_t handle);
/**
* @brief Write DAC data continuously
* @note The data in buffer will only be converted one time,
* This function will be blocked until all data loaded or timeout
* then the DAC output will keep outputting the voltage of the last data in the buffer
* @note Specially, on ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
* The driver will help to expand the inputted buffer automatically by default,
* you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @param[in] buf The digital data buffer to convert
* @param[in] buf_size The buffer size of digital data buffer
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
* @param[in] timeout_ms The timeout time in millisecond, set a minus value means will block forever
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
* - ESP_ERR_TIMEOUT Waiting for semaphore or message queue timeout
* - ESP_OK Success to output the acyclic DAC data
*/
esp_err_t dac_continuous_write(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded, int timeout_ms);
/**
* @brief Write DAC continuous data cyclically
* @note The data in buffer will be converted cyclically using DMA once this function is called,
* This function will return once the data loaded into DMA buffers.
* @note The buffer size of cyclically output is limited by the descriptor number and
* dma buffer size while initializing the continuous mode.
* Concretely, in order to load all the data into descriptors,
* the cyclic buffer size is not supposed to be greater than `desc_num * buf_size`
* @note Specially, on ESP32, the data bit width of DAC continuous data is fixed to 16 bits while only the high 8 bits are available,
* The driver will help to expand the inputted buffer automatically by default,
* you can also align the data to 16 bits manually by clearing `CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in menuconfig.
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @param[in] buf The digital data buffer to convert
* @param[in] buf_size The buffer size of digital data buffer
* @param[out] bytes_loaded The bytes that has been loaded into DMA buffer, can be NULL if don't need it
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The DAC continuous mode has not been enabled yet
* - ESP_OK Success to output the acyclic DAC data
*/
esp_err_t dac_continuous_write_cyclically(dac_continuous_handle_t handle, uint8_t *buf, size_t buf_size, size_t *bytes_loaded);
/**
* @brief Set event callbacks for DAC continuous mode
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `callbacks` structure to NULL.
* @note When CONFIG_DAC_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in this function, including the `user_data`, should be in the internal RAM as well.
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @param[in] callbacks Group of callback functions, input NULL to clear the former callbacks
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK Set event callbacks successfully
* - ESP_ERR_INVALID_ARG Set event callbacks failed because of invalid argument
*/
esp_err_t dac_continuous_register_event_callback(dac_continuous_handle_t handle, const dac_event_callbacks_t *callbacks, void *user_data);
/**
* @brief Start the async writing
* @note When the asynchronous writing start, the DAC will keep outputting '0' until the data are loaded into the DMA buffer.
* To loaded the data into DMA buffer, 'on_convert_done' callback is required,
* which can be registered by 'dac_continuous_register_event_callback' before enabling
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @return
* - ESP_OK Start asynchronous writing successfully
* - ESP_ERR_INVALID_ARG The handle is NULL
* - ESP_ERR_INVALID_STATE The channel is not enabled or the 'on_convert_done' callback is not registered
*/
esp_err_t dac_continuous_start_async_writing(dac_continuous_handle_t handle);
/**
* @brief Stop the sync writing
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @return
* - ESP_OK Stop asynchronous writing successfully
* - ESP_ERR_INVALID_ARG The handle is NULL
* - ESP_ERR_INVALID_STATE Asynchronous writing has not started
*/
esp_err_t dac_continuous_stop_async_writing(dac_continuous_handle_t handle);
/**
* @brief Write DAC data asynchronously
* @note This function can be called when the asynchronous writing started, and it can be called in the callback directly
* but recommend to writing data in a task, referring to :example:`peripherals/dac/dac_continuous/dac_audio`
*
* @param[in] handle The DAC continuous channel handle that obtained from 'dac_continuous_new_channels'
* @param[in] dma_buf The DMA buffer address, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
* @param[in] dma_buf_len The DMA buffer length, it can be acquired from 'dac_event_data_t' in the 'on_convert_done' callback
* @param[in] data The data that need to be written
* @param[in] data_len The data length the need to be written
* @param[out] bytes_loaded The bytes number that has been loaded/written into the DMA buffer
* @return
* - ESP_OK Write the data into DMA buffer successfully
* - ESP_ERR_INVALID_ARG NULL pointer
* - ESP_ERR_INVALID_STATE The channels haven't start the asynchronous writing
* - ESP_ERR_NOT_FOUND The param 'dam_buf' not match any existed DMA buffer
*/
esp_err_t dac_continuous_write_asynchronously(dac_continuous_handle_t handle,
uint8_t *dma_buf,
size_t dma_buf_len,
const uint8_t *data,
size_t data_len,
size_t *bytes_loaded);
#endif // SOC_DAC_SUPPORTED
#ifdef __cplusplus
}
#endif
@@ -1,97 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "driver/dac_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DAC_SUPPORTED
typedef struct dac_cosine_s *dac_cosine_handle_t; /*!< DAC cosine wave channel handle */
/**
* @brief DAC cosine channel configurations
*
*/
typedef struct {
dac_channel_t chan_id; /*!< The cosine wave channel id */
uint32_t freq_hz; /*!< The frequency of cosine wave, unit: Hz.
* The cosine wave generator is driven by RTC_FAST clock which is divide from RC_FAST,
* With the default RTC clock, the minimum frequency of cosine wave is about 130 Hz,
* Although it can support up to several MHz frequency theoretically,
* the waveform will distort at high frequency due to the hardware limitation.
* Typically not suggest to set the frequency higher than 200 KHz
*/
dac_cosine_clk_src_t clk_src; /*!< The clock source of the cosine wave generator, currently only support `DAC_COSINE_CLK_SRC_DEFAULT` */
dac_cosine_atten_t atten; /*!< The attenuation of cosine wave amplitude */
dac_cosine_phase_t phase; /*!< The phase of cosine wave, can only support DAC_COSINE_PHASE_0 or DAC_COSINE_PHASE_180, default as 0 while setting an unsupported phase */
int8_t offset; /*!< The DC offset of cosine wave */
struct {
bool force_set_freq: 1; /*!< Force to set the cosine wave frequency */
} flags; /*!< Flags of cosine mode */
} dac_cosine_config_t;
/**
* @brief Allocate a new DAC cosine wave channel
* @note Since there is only one cosine wave generator,
* only the first channel can set the frequency of the cosine wave.
* Normally, the latter one is not allowed to set a different frequency,
* but the it can be forced to set by setting the bit `force_set_freq` in the configuration,
* notice that another channel will be affected as well when the frequency is updated.
*
* @param[in] cos_cfg The configuration of cosine wave channel
* @param[out] ret_handle The returned cosine wave channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
* - ESP_ERR_NO_MEM No memory for the DAC cosine wave channel resources
* - ESP_OK Allocate the new DAC cosine wave channel success
*/
esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_handle_t *ret_handle);
/**
* @brief Delete the DAC cosine wave channel
*
* @param[in] handle The DAC cosine wave channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channel has already been deregistered
* - ESP_OK Delete the cosine wave channel success
*/
esp_err_t dac_cosine_del_channel(dac_cosine_handle_t handle);
/**
* @brief Start outputting the cosine wave on the channel
*
* @param[in] handle The DAC cosine wave channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channel has been started already
* - ESP_OK Start the cosine wave success
*/
esp_err_t dac_cosine_start(dac_cosine_handle_t handle);
/**
* @brief Stop outputting the cosine wave on the channel
*
* @param[in] handle The DAC cosine wave channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channel has been stopped already
* - ESP_OK Stop the cosine wave success
*/
esp_err_t dac_cosine_stop(dac_cosine_handle_t handle);
#endif // SOC_DAC_SUPPORTED
#ifdef __cplusplus
}
#endif
@@ -1,70 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "driver/dac_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DAC_SUPPORTED
typedef struct dac_oneshot_s *dac_oneshot_handle_t; /*!< DAC oneshot channel handle */
/**
* @brief DAC oneshot channel configuration
*
*/
typedef struct {
dac_channel_t chan_id; /*!< DAC channel id */
} dac_oneshot_config_t;
/**
* @brief Allocate a new DAC oneshot channel
* @note The channel will be enabled as well when the channel allocated
*
* @param[in] oneshot_cfg The configuration for the oneshot channel
* @param[out] ret_handle The returned oneshot channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The DAC channel has been registered already
* - ESP_ERR_NO_MEM No memory for the DAC oneshot channel resources
* - ESP_OK Allocate the new DAC oneshot channel success
*/
esp_err_t dac_oneshot_new_channel(const dac_oneshot_config_t *oneshot_cfg, dac_oneshot_handle_t *ret_handle);
/**
* @brief Delete the DAC oneshot channel
* @note The channel will be disabled as well when the channel deleted
*
* @param[in] handle The DAC oneshot channel handle
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_ERR_INVALID_STATE The channel has already been de-registered
* - ESP_OK Delete the oneshot channel success
*/
esp_err_t dac_oneshot_del_channel(dac_oneshot_handle_t handle);
/**
* @brief Output the voltage
* @note Generally it'll take 7~11 us on ESP32 and 10~21 us on ESP32-S2
*
* @param[in] handle The DAC oneshot channel handle
* @param[in] digi_value The digital value that need to be converted
* @return
* - ESP_ERR_INVALID_ARG The input parameter is invalid
* - ESP_OK Convert the digital value success
*/
esp_err_t dac_oneshot_output_voltage(dac_oneshot_handle_t handle, uint8_t digi_value);
#endif // SOC_DAC_SUPPORTED
#ifdef __cplusplus
}
#endif
@@ -1,56 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "hal/adc_types.h"
#include "hal/dac_types.h"
#include "esp_bit_defs.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_DAC_SUPPORTED
/**
* @brief DAC channel work mode in dma mode
* @note Only take effect when multiple channels enabled.
* @note Assume the data in buffer is 'A B C D E F'
* DAC_CHANNEL_MODE_SIMUL:
* - channel 0: A B C D E F
* - channel 1: A B C D E F
* DAC_CHANNEL_MODE_ALTER:
* - channel 0: A C E
* - channel 1: B D F
*/
typedef enum {
DAC_CHANNEL_MODE_SIMUL, /*!< The data in the DMA buffer is simultaneously output to the enable channel of the DAC. */
DAC_CHANNEL_MODE_ALTER, /*!< The data in the DMA buffer is alternately output to the enable channel of the DAC. */
} dac_continuous_channel_mode_t;
/**
* @brief DAC DMA (digitial controller) clock source
*
*/
typedef soc_periph_dac_digi_clk_src_t dac_continuous_digi_clk_src_t;
/**
* @brief DAC cosine wave generator clock source
*
*/
typedef soc_periph_dac_cosine_clk_src_t dac_cosine_clk_src_t;
#endif // SOC_DAC_SUPPORTED
#ifdef __cplusplus
}
#endif
@@ -1,184 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_attr.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of Dedicated GPIO bundle
*/
typedef struct dedic_gpio_bundle_t *dedic_gpio_bundle_handle_t;
/**
* @brief Type of Dedicated GPIO bundle configuration
*/
typedef struct {
const int *gpio_array; /*!< Array of GPIO numbers, gpio_array[0] ~ gpio_array[size-1] <=> low_dedic_channel_num ~ high_dedic_channel_num */
size_t array_size; /*!< Number of GPIOs in gpio_array */
struct {
unsigned int in_en: 1; /*!< Enable input */
unsigned int in_invert: 1; /*!< Invert input signal */
unsigned int out_en: 1; /*!< Enable output */
unsigned int out_invert: 1; /*!< Invert output signal */
} flags; /*!< Flags to control specific behaviour of GPIO bundle */
} dedic_gpio_bundle_config_t;
/**
* @brief Create GPIO bundle and return the handle
*
* @param[in] config Configuration of GPIO bundle
* @param[out] ret_bundle Returned handle of the new created GPIO bundle
* @return
* - ESP_OK: Create GPIO bundle successfully
* - ESP_ERR_INVALID_ARG: Create GPIO bundle failed because of invalid argument
* - ESP_ERR_NO_MEM: Create GPIO bundle failed because of no capable memory
* - ESP_ERR_NOT_FOUND: Create GPIO bundle failed because of no enough continuous dedicated channels
* - ESP_FAIL: Create GPIO bundle failed because of other error
*
* @note One has to enable at least input or output mode in "config" parameter.
*/
esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_gpio_bundle_handle_t *ret_bundle);
/**
* @brief Destroy GPIO bundle
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @return
* - ESP_OK: Destroy GPIO bundle successfully
* - ESP_ERR_INVALID_ARG: Destroy GPIO bundle failed because of invalid argument
* - ESP_FAIL: Destroy GPIO bundle failed because of other error
*/
esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle);
/**@{*/
/**
* @brief Get allocated channel mask
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @param[out] mask Returned mask value for on specific direction (in or out)
* @return
* - ESP_OK: Get channel mask successfully
* - ESP_ERR_INVALID_ARG: Get channel mask failed because of invalid argument
* - ESP_FAIL: Get channel mask failed because of other error
*
* @note Each bundle should have at least one mask (in or/and out), based on bundle configuration.
* @note With the returned mask, user can directly invoke LL function like "dedic_gpio_cpu_ll_write_mask"
* or write assembly code with dedicated GPIO instructions, to get better performance on GPIO manipulation.
*/
esp_err_t dedic_gpio_get_out_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
esp_err_t dedic_gpio_get_in_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
/**@}*/
/**@{*/
/**
* @brief Get the channel offset of the GPIO bundle
*
* A GPIO bundle maps the GPIOS of a particular direction to a consecutive set of channels within
* a particular GPIO bank of a particular CPU. This function returns the offset to
* the bundle's first channel of a particular direction within the bank.
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @param[out] offset Offset value to the first channel of a specific direction (in or out)
* @return
* - ESP_OK: Get channel offset successfully
* - ESP_ERR_INVALID_ARG: Get channel offset failed because of invalid argument
* - ESP_FAIL: Get channel offset failed because of other error
*/
esp_err_t dedic_gpio_get_out_offset(dedic_gpio_bundle_handle_t bundle, uint32_t *offset);
esp_err_t dedic_gpio_get_in_offset(dedic_gpio_bundle_handle_t bundle, uint32_t *offset);
/**@}*/
/**
* @brief Write value to GPIO bundle
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @param[in] mask Mask of the GPIOs to be written in the given bundle
* @param[in] value Value to write to given GPIO bundle, low bit represents low member in the bundle
*
* @note The mask is seen from the view of GPIO bundle.
* For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
* @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
*/
void dedic_gpio_bundle_write(dedic_gpio_bundle_handle_t bundle, uint32_t mask, uint32_t value) IRAM_ATTR;
/**
* @brief Read the value that output from the given GPIO bundle
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @return Value that output from the GPIO bundle, low bit represents low member in the bundle
*
* @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
*/
uint32_t dedic_gpio_bundle_read_out(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
/**
* @brief Read the value that input to the given GPIO bundle
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @return Value that input to the GPIO bundle, low bit represents low member in the bundle
*
* @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
*/
uint32_t dedic_gpio_bundle_read_in(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
#if SOC_DEDIC_GPIO_HAS_INTERRUPT
/**
* @brief Supported type of dedicated GPIO interrupt
*/
typedef enum {
DEDIC_GPIO_INTR_NONE, /*!< No interrupt */
DEDIC_GPIO_INTR_LOW_LEVEL = 2, /*!< Interrupt on low level */
DEDIC_GPIO_INTR_HIGH_LEVEL, /*!< Interrupt on high level */
DEDIC_GPIO_INTR_NEG_EDGE, /*!< Interrupt on negedge */
DEDIC_GPIO_INTR_POS_EDGE, /*!< Interrupt on posedge */
DEDIC_GPIO_INTR_BOTH_EDGE /*!< Interrupt on both negedge and posedge */
} dedic_gpio_intr_type_t;
/**
* @brief Type of dedicated GPIO ISR callback function
*
* @param bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @param index Index of the GPIO in its corresponding bundle (count from 0)
* @param args User defined arguments for the callback function. It's passed through `dedic_gpio_bundle_set_interrupt_and_callback`
* @return If a high priority task is woken up by the callback function
*/
typedef bool (*dedic_gpio_isr_callback_t)(dedic_gpio_bundle_handle_t bundle, uint32_t index, void *args);
/**
* @brief Set interrupt and callback function for GPIO bundle
*
* @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
* @param[in] mask Mask of the GPIOs in the given bundle
* @param[in] intr_type Interrupt type, set to DEDIC_GPIO_INTR_NONE can disable interrupt
* @param[in] cb_isr Callback function, which got invoked in ISR context. A NULL pointer here will bypass the callback
* @param[in] cb_args User defined argument to be passed to the callback function
*
* @note This function is only valid for bundle with input mode enabled. See "dedic_gpio_bundle_config_t"
* @note The mask is seen from the view of GPIO Bundle.
* For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
*
* @return
* - ESP_OK: Set GPIO interrupt and callback function successfully
* - ESP_ERR_INVALID_ARG: Set GPIO interrupt and callback function failed because of invalid argument
* - ESP_FAIL: Set GPIO interrupt and callback function failed because of other error
*/
esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_t bundle, uint32_t mask, dedic_gpio_intr_type_t intr_type, dedic_gpio_isr_callback_t cb_isr, void *cb_args);
#endif // SOC_DEDIC_GPIO_HAS_INTERRUPT
#ifdef __cplusplus
}
#endif
-548
View File
@@ -1,548 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "soc/soc_caps.h"
#include "hal/gpio_types.h"
#include "esp_rom_gpio.h"
#include "driver/gpio_etm.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GPIO_PIN_COUNT (SOC_GPIO_PIN_COUNT)
/// Check whether it is a valid GPIO number
#define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num >= 0) && \
(((1ULL << (gpio_num)) & SOC_GPIO_VALID_GPIO_MASK) != 0))
/// Check whether it can be a valid GPIO number of output mode
#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((gpio_num >= 0) && \
(((1ULL << (gpio_num)) & SOC_GPIO_VALID_OUTPUT_GPIO_MASK) != 0))
/// Check whether it can be a valid digital I/O pad
#define GPIO_IS_VALID_DIGITAL_IO_PAD(gpio_num) ((gpio_num >= 0) && \
(((1ULL << (gpio_num)) & SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK) != 0))
typedef intr_handle_t gpio_isr_handle_t;
/**
* @brief GPIO interrupt handler
*
* @param arg User registered data
*/
typedef void (*gpio_isr_t)(void *arg);
/**
* @brief Configuration parameters of GPIO pad for gpio_config function
*/
typedef struct {
uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
gpio_mode_t mode; /*!< GPIO mode: set input/output mode */
gpio_pullup_t pull_up_en; /*!< GPIO pull-up */
gpio_pulldown_t pull_down_en; /*!< GPIO pull-down */
gpio_int_type_t intr_type; /*!< GPIO interrupt type */
} gpio_config_t;
/**
* @brief GPIO common configuration
*
* Configure GPIO's Mode,pull-up,PullDown,IntrType
*
* @param pGPIOConfig Pointer to GPIO configure struct
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*
*/
esp_err_t gpio_config(const gpio_config_t *pGPIOConfig);
/**
* @brief Reset an gpio to default state (select gpio function, enable pullup and disable input and output).
*
* @param gpio_num GPIO number.
*
* @note This function also configures the IOMUX for this pin to the GPIO
* function, and disconnects any other peripheral output configured via GPIO
* Matrix.
*
* @return Always return ESP_OK.
*/
esp_err_t gpio_reset_pin(gpio_num_t gpio_num);
/**
* @brief GPIO set interrupt trigger type
*
* @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param intr_type Interrupt type, select from gpio_int_type_t
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*
*/
esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Enable GPIO module interrupt signal
*
* @note ESP32: Please do not use the interrupt of GPIO36 and GPIO39 when using ADC or Wi-Fi and Bluetooth with sleep mode enabled.
* Please refer to the comments of `adc1_get_raw`.
* Please refer to Section 3.11 of <a href="https://espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf">ESP32 ECO and Workarounds for Bugs</a> for the description of this issue.
*
* @param gpio_num GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*
*/
esp_err_t gpio_intr_enable(gpio_num_t gpio_num);
/**
* @brief Disable GPIO module interrupt signal
*
* @note This function is allowed to be executed when Cache is disabled within ISR context, by enabling `CONFIG_GPIO_CTRL_FUNC_IN_IRAM`
*
* @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*
*/
esp_err_t gpio_intr_disable(gpio_num_t gpio_num);
/**
* @brief GPIO set output level
*
* @note This function is allowed to be executed when Cache is disabled within ISR context, by enabling `CONFIG_GPIO_CTRL_FUNC_IN_IRAM`
*
* @param gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param level Output level. 0: low ; 1: high
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO number error
*
*/
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
/**
* @brief GPIO get input level
*
* @warning If the pad is not configured for input (or input and output) the returned value is always 0.
*
* @param gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
*
* @return
* - 0 the GPIO input level is 0
* - 1 the GPIO input level is 1
*
*/
int gpio_get_level(gpio_num_t gpio_num);
/**
* @brief GPIO set direction
*
* Configure GPIO direction,such as output_only,input_only,output_and_input
*
* @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param mode GPIO direction
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO error
*
*/
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
/**
* @brief Configure GPIO pull-up/pull-down resistors
*
* @note ESP32: Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
*
* @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param pull GPIO pull up/down mode.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG : Parameter error
*
*/
esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
/**
* @brief Enable GPIO wake-up function.
*
* @param gpio_num GPIO number.
*
* @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Disable GPIO wake-up function.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
/**
* @brief Register GPIO interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* This ISR function is called whenever any GPIO interrupt occurs. See
* the alternative gpio_install_isr_service() and
* gpio_isr_handler_add() API in order to have the driver support
* per-GPIO ISRs.
*
* @param fn Interrupt handler function.
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
*
* \verbatim embed:rst:leading-asterisk
* To disable or remove the ISR, pass the returned handle to the :doc:`interrupt allocation functions </api-reference/system/intr_alloc>`.
* \endverbatim
*
* @return
* - ESP_OK Success ;
* - ESP_ERR_INVALID_ARG GPIO error
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
*/
esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
/**
* @brief Enable pull-up on GPIO.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_pullup_en(gpio_num_t gpio_num);
/**
* @brief Disable pull-up on GPIO.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num);
/**
* @brief Enable pull-down on GPIO.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
/**
* @brief Disable pull-down on GPIO.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
/**
* @brief Install the GPIO driver's ETS_GPIO_INTR_SOURCE ISR handler service, which allows per-pin GPIO interrupt handlers.
*
* This function is incompatible with gpio_isr_register() - if that function is used, a single global ISR is registered for all GPIO interrupts. If this function is used, the ISR service provides a global GPIO ISR and individual pin handlers are registered via the gpio_isr_handler_add() function.
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM No memory to install this service
* - ESP_ERR_INVALID_STATE ISR service already installed.
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* - ESP_ERR_INVALID_ARG GPIO error
*/
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
/**
* @brief Uninstall the driver's GPIO ISR service, freeing related resources.
*/
void gpio_uninstall_isr_service(void);
/**
* @brief Add ISR handler for the corresponding GPIO pin.
*
* Call this function after using gpio_install_isr_service() to
* install the driver's GPIO ISR handler service.
*
* The pin ISR handlers no longer need to be declared with IRAM_ATTR,
* unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the
* ISR in gpio_install_isr_service().
*
* This ISR handler will be called from an ISR. So there is a stack
* size limit (configurable as "ISR stack size" in menuconfig). This
* limit is smaller compared to a global GPIO interrupt handler due
* to the additional level of indirection.
*
* @param gpio_num GPIO number
* @param isr_handler ISR handler function for the corresponding GPIO number.
* @param args parameter for ISR handler.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args);
/**
* @brief Remove ISR handler for the corresponding GPIO pin.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Wrong state, the ISR service has not been initialized.
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);
/**
* @brief Set GPIO pad drive capability
*
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Drive capability of the pad
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength);
/**
* @brief Get GPIO pad drive capability
*
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Pointer to accept drive capability of the pad
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength);
/**
* @brief Enable gpio pad hold function.
*
* When a GPIO is set to hold, its state is latched at that moment and will not change when the internal
* signal or the IO MUX/GPIO configuration is modified (including input enable, output enable, output value,
* function, and drive strength values). This function can be used to retain the state of GPIOs when the chip
* or system is reset, for example, when watchdog time-out or Deep-sleep events are triggered.
*
* This function works in both input and output modes, and only applicable to output-capable GPIOs.
* If this function is enabled:
* in output mode: the output level of the GPIO will be locked and can not be changed.
* in input mode: the input read value can still reflect the changes of the input signal.
*
* However, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. Even if this
* function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from
* Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call
* `gpio_deep_sleep_hold_en`.
*
* Power down or call `gpio_hold_dis` will disable this function.
*
* @param gpio_num GPIO number, only support output-capable GPIOs
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_SUPPORTED Not support pad hold function
*/
esp_err_t gpio_hold_en(gpio_num_t gpio_num);
/**
* @brief Disable gpio pad hold function.
*
* When the chip is woken up from Deep-sleep, the gpio will be set to the default mode, so, the gpio will output
* the default level if this function is called. If you don't want the level changes, the gpio should be configured to
* a known state before this function is called.
* e.g.
* If you hold gpio18 high during Deep-sleep, after the chip is woken up and `gpio_hold_dis` is called,
* gpio18 will output low level(because gpio18 is input mode by default). If you don't want this behavior,
* you should configure gpio18 as output mode and set it to hight level before calling `gpio_hold_dis`.
*
* @param gpio_num GPIO number, only support output-capable GPIOs
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_SUPPORTED Not support pad hold function
*/
esp_err_t gpio_hold_dis(gpio_num_t gpio_num);
/**
* @brief Enable all digital gpio pads hold function during Deep-sleep.
*
* Enabling this feature makes all digital gpio pads be at the holding state during Deep-sleep. The state of each pad
* holds is its active configuration (not pad's sleep configuration!).
*
* Note that this pad hold feature only works when the chip is in Deep-sleep mode. When the chip is in active mode,
* the digital gpio state can be changed freely even you have called this function.
*
* After this API is being called, the digital gpio Deep-sleep hold feature will work during every sleep process. You
* should call `gpio_deep_sleep_hold_dis` to disable this feature.
*/
void gpio_deep_sleep_hold_en(void);
/**
* @brief Disable all digital gpio pads hold function during Deep-sleep.
*/
void gpio_deep_sleep_hold_dis(void);
/**
* @brief Set pad input to a peripheral signal through the IOMUX.
* @param gpio_num GPIO number of the pad.
* @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
*/
void gpio_iomux_in(uint32_t gpio_num, uint32_t signal_idx);
/**
* @brief Set peripheral output to an GPIO pad through the IOMUX.
* @param gpio_num gpio_num GPIO number of the pad.
* @param func The function number of the peripheral pin to output pin.
* One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
* @param oen_inv True if the output enable needs to be inverted, otherwise False.
*/
void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv);
#if SOC_GPIO_SUPPORT_FORCE_HOLD
/**
* @brief Force hold all digital and rtc gpio pads.
*
* GPIO force hold, no matter the chip in active mode or sleep modes.
*
* This function will immediately cause all pads to latch the current values of input enable, output enable,
* output value, function, and drive strength values.
*
* @warning This function will hold flash and UART pins as well. Therefore, this function, and all code run afterwards
* (till calling `gpio_force_unhold_all` to disable this feature), MUST be placed in internal RAM as holding the flash
* pins will halt SPI flash operation, and holding the UART pins will halt any UART logging.
* */
esp_err_t gpio_force_hold_all(void);
/**
* @brief Force unhold all digital and rtc gpio pads.
* */
esp_err_t gpio_force_unhold_all(void);
#endif
#if SOC_GPIO_SUPPORT_SLP_SWITCH
/**
* @brief Enable SLP_SEL to change GPIO status automantically in lightsleep.
* @param gpio_num GPIO number of the pad.
*
* @return
* - ESP_OK Success
*
*/
esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num);
/**
* @brief Disable SLP_SEL to change GPIO status automantically in lightsleep.
* @param gpio_num GPIO number of the pad.
*
* @return
* - ESP_OK Success
*/
esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
/**
* @brief GPIO set direction at sleep
*
* Configure GPIO direction,such as output_only,input_only,output_and_input
*
* @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param mode GPIO direction
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO error
*/
esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
/**
* @brief Configure GPIO pull-up/pull-down resistors at sleep
*
* @note ESP32: Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
*
* @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
* @param pull GPIO pull up/down mode.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG : Parameter error
*/
esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
#endif
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
#define GPIO_IS_DEEP_SLEEP_WAKEUP_VALID_GPIO(gpio_num) ((gpio_num >= 0) && \
(((1ULL << (gpio_num)) & SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK) != 0))
/**
* @brief Enable GPIO deep-sleep wake-up function.
*
* @param gpio_num GPIO number.
*
* @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
*
* @note Called by the SDK. User shouldn't call this directly in the APP.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Disable GPIO deep-sleep wake-up function.
*
* @param gpio_num GPIO number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num);
#endif
#ifdef __cplusplus
}
#endif
-132
View File
@@ -1,132 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#include "esp_etm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief GPIO edges that can be used as ETM event
*/
typedef enum {
GPIO_ETM_EVENT_EDGE_POS, /*!< A rising edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
} gpio_etm_event_edge_t;
/**
* @brief GPIO ETM event configuration
*/
typedef struct {
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
} gpio_etm_event_config_t;
/**
* @brief Create an ETM event object for the GPIO peripheral
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
* @note The newly created ETM event object is not bind to any GPIO, you need to call `gpio_etm_event_bind_gpio` to bind the wanted GPIO
*
* @param[in] config GPIO ETM event configuration
* @param[out] ret_event Returned ETM event handle
* @return
* - ESP_OK: Create ETM event successfully
* - ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
* - ESP_ERR_NO_MEM: Create ETM event failed because of out of memory
* - ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
* - ESP_FAIL: Create ETM event failed because of other reasons
*/
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event);
/**
* @brief Bind the GPIO with the ETM event
*
* @note Calling this function multiple times with different GPIO number can override the previous setting immediately.
* @note Only GPIO ETM object can call this function
*
* @param[in] event ETM event handle that created by `gpio_new_etm_event`
* @param[in] gpio_num GPIO number that can trigger the ETM event
* @return
* - ESP_OK: Set the GPIO for ETM event successfully
* - ESP_ERR_INVALID_ARG: Set the GPIO for ETM event failed because of invalid argument, e.g. GPIO is not input capable, ETM event is not of GPIO type
* - ESP_FAIL: Set the GPIO for ETM event failed because of other reasons
*/
esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num);
/**
* @brief GPIO actions that can be taken by the ETM task
*/
typedef enum {
GPIO_ETM_TASK_ACTION_SET, /*!< Set the GPIO level to high */
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
} gpio_etm_task_action_t;
/**
* @brief GPIO ETM task configuration
*/
typedef struct {
gpio_etm_task_action_t action; /*!< Which action to take by the ETM task module */
} gpio_etm_task_config_t;
/**
* @brief Create an ETM task object for the GPIO peripheral
*
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
* @note The GPIO ETM task works like a container, a newly created ETM task object doesn't have GPIO members to be managed.
* You need to call `gpio_etm_task_add_gpio` to put one or more GPIOs to the container.
*
* @param[in] config GPIO ETM task configuration
* @param[out] ret_task Returned ETM task handle
* @return
* - ESP_OK: Create ETM task successfully
* - ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
* - ESP_ERR_NO_MEM: Create ETM task failed because of out of memory
* - ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
* - ESP_FAIL: Create ETM task failed because of other reasons
*/
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task);
/**
* @brief Add GPIO to the ETM task.
*
* @note You can call this function multiple times to add more GPIOs
* @note Only GPIO ETM object can call this function
*
* @param[in] task ETM task handle that created by `gpio_new_etm_task`
* @param[in] gpio_num GPIO number that can be controlled by the ETM task
* @return
* - ESP_OK: Add GPIO to the ETM task successfully
* - ESP_ERR_INVALID_ARG: Add GPIO to the ETM task failed because of invalid argument, e.g. GPIO is not output capable, ETM task is not of GPIO type
* - ESP_ERR_INVALID_STATE: Add GPIO to the ETM task failed because the GPIO is used by other ETM task already
* - ESP_FAIL: Add GPIO to the ETM task failed because of other reasons
*/
esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num);
/**
* @brief Remove the GPIO from the ETM task
*
* @note Before deleting the ETM task, you need to remove all the GPIOs from the ETM task by this function
* @note Only GPIO ETM object can call this function
*
* @param[in] task ETM task handle that created by `gpio_new_etm_task`
* @param[in] gpio_num GPIO number that to be remove from the ETM task
* @return
* - ESP_OK: Remove the GPIO from the ETM task successfully
* - ESP_ERR_INVALID_ARG: Remove the GPIO from the ETM task failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Remove the GPIO from the ETM task failed because the GPIO is not controlled by this ETM task
* - ESP_FAIL: Remove the GPIO from the ETM task failed because of other reasons
*/
esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num);
#ifdef __cplusplus
}
#endif
@@ -1,115 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#include "hal/glitch_filter_types.h"
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Typedef of GPIO glitch filter handle
*/
typedef struct gpio_glitch_filter_t *gpio_glitch_filter_handle_t;
/**
* @brief Configuration of GPIO pin glitch filter
*/
typedef struct {
glitch_filter_clock_source_t clk_src; /*!< Clock source for the glitch filter */
gpio_num_t gpio_num; /*!< GPIO number */
} gpio_pin_glitch_filter_config_t;
/**
* @brief Create a pin glitch filter
*
* @note Pin glitch filter parameters are fixed, pulses shorter than two sample clocks (IO-MUX's source clock) will be filtered out.
* It's independent with "flex" glitch filter. See also `gpio_new_flex_glitch_filter`.
* @note The created filter handle can later be deleted by `gpio_del_glitch_filter`.
*
* @param[in] config Glitch filter configuration
* @param[out] ret_filter Returned glitch filter handle
* @return
* - ESP_OK: Create a pin glitch filter successfully
* - ESP_ERR_INVALID_ARG: Create a pin glitch filter failed because of invalid arguments (e.g. wrong GPIO number)
* - ESP_ERR_NO_MEM: Create a pin glitch filter failed because of out of memory
* - ESP_FAIL: Create a pin glitch filter failed because of other error
*/
esp_err_t gpio_new_pin_glitch_filter(const gpio_pin_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter);
/**
* @brief Configuration of GPIO flex glitch filter
*/
typedef struct {
glitch_filter_clock_source_t clk_src; /*!< Clock source for the glitch filter */
gpio_num_t gpio_num; /*!< GPIO number */
uint32_t window_width_ns; /*!< Sample window width (in ns) */
uint32_t window_thres_ns; /*!< Sample window threshold (in ns), during the `window_width_ns` sample window, any pulse whose width < window_thres_ns will be discarded. */
} gpio_flex_glitch_filter_config_t;
/**
* @brief Allocate a flex glitch filter
*
* @note "flex" means the filter parameters (window, threshold) are adjustable. It's independent with pin glitch filter.
* See also `gpio_new_pin_glitch_filter`.
* @note The created filter handle can later be deleted by `gpio_del_glitch_filter`.
*
* @param[in] config Glitch filter configuration
* @param[out] ret_filter Returned glitch filter handle
* @return
* - ESP_OK: Allocate a flex glitch filter successfully
* - ESP_ERR_INVALID_ARG: Allocate a flex glitch filter failed because of invalid arguments (e.g. wrong GPIO number, filter parameters out of range)
* - ESP_ERR_NO_MEM: Allocate a flex glitch filter failed because of out of memory
* - ESP_ERR_NOT_FOUND: Allocate a flex glitch filter failed because the underlying hardware resources are used up
* - ESP_FAIL: Allocate a flex glitch filter failed because of other error
*/
esp_err_t gpio_new_flex_glitch_filter(const gpio_flex_glitch_filter_config_t *config, gpio_glitch_filter_handle_t *ret_filter);
/**
* @brief Delete a glitch filter
*
* @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter`
* @return
* - ESP_OK: Delete glitch filter successfully
* - ESP_ERR_INVALID_ARG: Delete glitch filter failed because of invalid arguments
* - ESP_ERR_INVALID_STATE: Delete glitch filter failed because the glitch filter is still in working
* - ESP_FAIL: Delete glitch filter failed because of other error
*/
esp_err_t gpio_del_glitch_filter(gpio_glitch_filter_handle_t filter);
/**
* @brief Enable a glitch filter
*
* @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter`
* @return
* - ESP_OK: Enable glitch filter successfully
* - ESP_ERR_INVALID_ARG: Enable glitch filter failed because of invalid arguments
* - ESP_ERR_INVALID_STATE: Enable glitch filter failed because the glitch filter is already enabled
* - ESP_FAIL: Enable glitch filter failed because of other error
*/
esp_err_t gpio_glitch_filter_enable(gpio_glitch_filter_handle_t filter);
/**
* @brief Disable a glitch filter
*
* @param[in] filter Glitch filter handle returned from `gpio_new_flex_glitch_filter` or `gpio_new_pin_glitch_filter`
* @return
* - ESP_OK: Disable glitch filter successfully
* - ESP_ERR_INVALID_ARG: Disable glitch filter failed because of invalid arguments
* - ESP_ERR_INVALID_STATE: Disable glitch filter failed because the glitch filter is not enabled yet
* - ESP_FAIL: Disable glitch filter failed because of other error
*/
esp_err_t gpio_glitch_filter_disable(gpio_glitch_filter_handle_t filter);
#ifdef __cplusplus
}
#endif
-245
View File
@@ -1,245 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/gptimer_types.h"
#include "driver/gptimer_etm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief General Purpose Timer configuration
*/
typedef struct {
gptimer_clock_source_t clk_src; /*!< GPTimer clock source */
gptimer_count_direction_t direction; /*!< Count direction */
uint32_t resolution_hz; /*!< Counter resolution (working frequency) in Hz,
hence, the step size of each count tick equals to (1 / resolution_hz) seconds */
struct {
uint32_t intr_shared: 1; /*!< Set true, the timer interrupt number can be shared with other peripherals */
} flags; /*!< GPTimer config flags*/
} gptimer_config_t;
/**
* @brief Create a new General Purpose Timer, and return the handle
*
* @note The newly created timer is put in the init state.
*
* @param[in] config GPTimer configuration
* @param[out] ret_timer Returned timer handle
* @return
* - ESP_OK: Create GPTimer successfully
* - ESP_ERR_INVALID_ARG: Create GPTimer failed because of invalid argument
* - ESP_ERR_NO_MEM: Create GPTimer failed because out of memory
* - ESP_ERR_NOT_FOUND: Create GPTimer failed because all hardware timers are used up and no more free one
* - ESP_FAIL: Create GPTimer failed because of other error
*/
esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *ret_timer);
/**
* @brief Delete the GPTimer handle
*
* @note A timer can't be in the enable state when this function is invoked.
* See also `gptimer_disable` for how to disable a timer.
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @return
* - ESP_OK: Delete GPTimer successfully
* - ESP_ERR_INVALID_ARG: Delete GPTimer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete GPTimer failed because the timer is not in init state
* - ESP_FAIL: Delete GPTimer failed because of other error
*/
esp_err_t gptimer_del_timer(gptimer_handle_t timer);
/**
* @brief Set GPTimer raw count value
*
* @note When updating the raw count of an active timer, the timer will immediately start counting from the new value.
* @note This function is allowed to run within ISR context
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] value Count value to be set
* @return
* - ESP_OK: Set GPTimer raw count value successfully
* - ESP_ERR_INVALID_ARG: Set GPTimer raw count value failed because of invalid argument
* - ESP_FAIL: Set GPTimer raw count value failed because of other error
*/
esp_err_t gptimer_set_raw_count(gptimer_handle_t timer, uint64_t value);
/**
* @brief Get GPTimer raw count value
*
* @note This function will trigger a software capture event and then return the captured count value.
* @note With the raw count value and the resolution returned from `gptimer_get_resolution`, you can convert the count value into seconds.
* @note This function is allowed to run within ISR context
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[out] value Returned GPTimer count value
* @return
* - ESP_OK: Get GPTimer raw count value successfully
* - ESP_ERR_INVALID_ARG: Get GPTimer raw count value failed because of invalid argument
* - ESP_FAIL: Get GPTimer raw count value failed because of other error
*/
esp_err_t gptimer_get_raw_count(gptimer_handle_t timer, uint64_t *value);
/**
* @brief Return the real resolution of the timer
*
* @note usually the timer resolution is same as what you configured in the `gptimer_config_t::resolution_hz`, but for some unstable clock source (e.g. RC_FAST), which needs a calibration, the real resolution may be different from the configured one.
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[out] out_resolution Returned timer resolution, in Hz
* @return
* - ESP_OK: Get GPTimer resolution successfully
* - ESP_ERR_INVALID_ARG: Get GPTimer resolution failed because of invalid argument
* - ESP_FAIL: Get GPTimer resolution failed because of other error
*/
esp_err_t gptimer_get_resolution(gptimer_handle_t timer, uint32_t *out_resolution);
/**
* @brief Get GPTimer captured count value
*
* @note The capture action can be issued either by external event or by software (see also `gptimer_get_raw_count`).
* @note This function is allowed to run within ISR context
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[out] value Returned captured count value
* @return
* - ESP_OK: Get GPTimer captured count value successfully
* - ESP_ERR_INVALID_ARG: Get GPTimer captured count value failed because of invalid argument
* - ESP_FAIL: Get GPTimer captured count value failed because of other error
*/
esp_err_t gptimer_get_captured_count(gptimer_handle_t timer, uint64_t *value);
/**
* @brief Group of supported GPTimer callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_GPTIMER_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
*/
typedef struct {
gptimer_alarm_cb_t on_alarm; /*!< Timer alarm callback */
} gptimer_event_callbacks_t;
/**
* @brief Set callbacks for GPTimer
*
* @note User registered callbacks are expected to be runnable within ISR context
* @note The first call to this function needs to be before the call to `gptimer_enable`
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set event callbacks failed because the timer is not in init state
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer_event_callbacks_t *cbs, void *user_data);
/**
* @brief General Purpose Timer alarm configuration
*/
typedef struct {
uint64_t alarm_count; /*!< Alarm target count value */
uint64_t reload_count; /*!< Alarm reload count value, effect only when `auto_reload_on_alarm` is set to true */
struct {
uint32_t auto_reload_on_alarm: 1; /*!< Reload the count value by hardware, immediately at the alarm event */
} flags; /*!< Alarm config flags*/
} gptimer_alarm_config_t;
/**
* @brief Set alarm event actions for GPTimer.
*
* @note This function is allowed to run within ISR context, so that user can set new alarm action immediately in the ISR callback.
* @note This function is allowed to be executed when Cache is disabled, by enabling `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] config Alarm configuration, especially, set config to NULL means disabling the alarm function
* @return
* - ESP_OK: Set alarm action for GPTimer successfully
* - ESP_ERR_INVALID_ARG: Set alarm action for GPTimer failed because of invalid argument
* - ESP_FAIL: Set alarm action for GPTimer failed because of other error
*/
esp_err_t gptimer_set_alarm_action(gptimer_handle_t timer, const gptimer_alarm_config_t *config);
/**
* @brief Enable GPTimer
*
* @note This function will transit the timer state from init to enable.
* @note This function will enable the interrupt service, if it's lazy installed in `gptimer_register_event_callbacks`.
* @note This function will acquire a PM lock, if a specific source clock (e.g. APB) is selected in the `gptimer_config_t`, while `CONFIG_PM_ENABLE` is enabled.
* @note Enable a timer doesn't mean to start it. See also `gptimer_start` for how to make the timer start counting.
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @return
* - ESP_OK: Enable GPTimer successfully
* - ESP_ERR_INVALID_ARG: Enable GPTimer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable GPTimer failed because the timer is already enabled
* - ESP_FAIL: Enable GPTimer failed because of other error
*/
esp_err_t gptimer_enable(gptimer_handle_t timer);
/**
* @brief Disable GPTimer
*
* @note This function will do the opposite work to the `gptimer_enable`
* @note Disable a timer doesn't mean to stop it. See also `gptimer_stop` for how to make the timer stop counting.
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @return
* - ESP_OK: Disable GPTimer successfully
* - ESP_ERR_INVALID_ARG: Disable GPTimer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable GPTimer failed because the timer is not enabled yet
* - ESP_FAIL: Disable GPTimer failed because of other error
*/
esp_err_t gptimer_disable(gptimer_handle_t timer);
/**
* @brief Start GPTimer (internal counter starts counting)
*
* @note This function should be called when the timer is in the enable state (i.e. after calling `gptimer_enable`)
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @return
* - ESP_OK: Start GPTimer successfully
* - ESP_ERR_INVALID_ARG: Start GPTimer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Start GPTimer failed because the timer is not enabled yet
* - ESP_FAIL: Start GPTimer failed because of other error
*/
esp_err_t gptimer_start(gptimer_handle_t timer);
/**
* @brief Stop GPTimer (internal counter stops counting)
*
* @note This function should be called when the timer is in the enable state (i.e. after calling `gptimer_enable`)
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @return
* - ESP_OK: Stop GPTimer successfully
* - ESP_ERR_INVALID_ARG: Stop GPTimer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Stop GPTimer failed because the timer is not enabled yet
* - ESP_FAIL: Stop GPTimer failed because of other error
*/
esp_err_t gptimer_stop(gptimer_handle_t timer);
#ifdef __cplusplus
}
#endif
@@ -1,63 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_etm.h"
#include "driver/gptimer_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief GPTimer ETM event configuration
*/
typedef struct {
gptimer_etm_event_type_t event_type; /*!< GPTimer ETM event type */
} gptimer_etm_event_config_t;
/**
* @brief Get the ETM event for GPTimer
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] config GPTimer ETM event configuration
* @param[out] out_event Returned ETM event handle
* @return
* - ESP_OK: Get ETM event successfully
* - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument
* - ESP_FAIL: Get ETM event failed because of other error
*/
esp_err_t gptimer_new_etm_event(gptimer_handle_t timer, const gptimer_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
/**
* @brief GPTimer ETM task configuration
*/
typedef struct {
gptimer_etm_task_type_t task_type; /*!< GPTimer ETM task type */
} gptimer_etm_task_config_t;
/**
* @brief Get the ETM task for GPTimer
*
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] config GPTimer ETM task configuration
* @param[out] out_task Returned ETM task handle
* @return
* - ESP_OK: Get ETM task successfully
* - ESP_ERR_INVALID_ARG: Get ETM task failed because of invalid argument
* - ESP_FAIL: Get ETM task failed because of other error
*/
esp_err_t gptimer_new_etm_task(gptimer_handle_t timer, const gptimer_etm_task_config_t *config, esp_etm_task_handle_t *out_task);
#ifdef __cplusplus
}
#endif
@@ -1,42 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "hal/timer_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of General Purpose Timer handle
*/
typedef struct gptimer_t *gptimer_handle_t;
/**
* @brief GPTimer alarm event data
*/
typedef struct {
uint64_t count_value; /*!< Current count value */
uint64_t alarm_value; /*!< Current alarm value */
} gptimer_alarm_event_data_t;
/**
* @brief Timer alarm callback prototype
*
* @param[in] timer Timer handle created by `gptimer_new_timer`
* @param[in] edata Alarm event data, fed by driver
* @param[in] user_ctx User data, passed from `gptimer_register_event_callbacks`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*gptimer_alarm_cb_t) (gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx);
#ifdef __cplusplus
}
#endif
-636
View File
@@ -1,636 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _DRIVER_I2C_H_
#define _DRIVER_I2C_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <esp_types.h>
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "hal/i2c_types.h"
#if SOC_I2C_SUPPORT_APB
#define I2C_APB_CLK_FREQ _Pragma ("GCC warning \"'I2C_APB_CLK_FREQ' macro is deprecated\"") (APB_CLK_FREQ) /*!< I2C source clock is APB clock, 80MHz, deprecated */
#endif
// I2C clk flags for users to use, can be expanded in the future.
#define I2C_SCLK_SRC_FLAG_FOR_NOMAL (0) /*!< Any one clock source that is available for the specified frequency may be choosen*/
#define I2C_SCLK_SRC_FLAG_AWARE_DFS (1 << 0) /*!< For REF tick clock, it won't change with APB.*/
#define I2C_SCLK_SRC_FLAG_LIGHT_SLEEP (1 << 1) /*!< For light sleep mode.*/
/**
* @brief Minimum size, in bytes, of the internal private structure used to describe
* I2C commands link.
*/
#define I2C_INTERNAL_STRUCT_SIZE (24)
/**
* @brief The following macro is used to determine the recommended size of the
* buffer to pass to `i2c_cmd_link_create_static()` function.
* It requires one parameter, `TRANSACTIONS`, describing the number of transactions
* intended to be performed on the I2C port.
* For example, if one wants to perform a read on an I2C device register, `TRANSACTIONS`
* must be at least 2, because the commands required are the following:
* - write device register
* - read register content
*
* Signals such as "(repeated) start", "stop", "nack", "ack" shall not be counted.
*/
#define I2C_LINK_RECOMMENDED_SIZE(TRANSACTIONS) (2 * I2C_INTERNAL_STRUCT_SIZE + I2C_INTERNAL_STRUCT_SIZE * \
(5 * TRANSACTIONS)) /* Make the assumption that each transaction
* of the user is surrounded by a "start", device address
* and a "nack/ack" signal. Allocate one more room for
* "stop" signal at the end.
* Allocate 2 more internal struct size for headers.
*/
/**
* @brief I2C initialization parameters
*/
typedef struct{
i2c_mode_t mode; /*!< I2C mode */
int sda_io_num; /*!< GPIO number for I2C sda signal */
int scl_io_num; /*!< GPIO number for I2C scl signal */
bool sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/
bool scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/
union {
struct {
uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
} master; /*!< I2C master config */
#if SOC_I2C_SUPPORT_SLAVE
struct {
uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */
uint16_t slave_addr; /*!< I2C address for slave mode */
uint32_t maximum_speed; /*!< I2C expected clock speed from SCL. */
} slave; /*!< I2C slave config */
#endif // SOC_I2C_SUPPORT_SLAVE
};
uint32_t clk_flags; /*!< Bitwise of ``I2C_SCLK_SRC_FLAG_**FOR_DFS**`` for clk source choice*/
} i2c_config_t;
typedef void *i2c_cmd_handle_t; /*!< I2C command handle */
/**
* @brief Install an I2C driver
* @note Not all Espressif chips can support slave mode (e.g. ESP32C2)
*
* @param i2c_num I2C port number
* @param mode I2C mode (either master or slave).
* @param slv_rx_buf_len Receiving buffer size. Only slave mode will use this value, it is ignored in master mode.
* @param slv_tx_buf_len Sending buffer size. Only slave mode will use this value, it is ignored in master mode.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values.
* See esp_intr_alloc.h for more info.
* @note
* In master mode, if the cache is likely to be disabled(such as write flash) and the slave is time-sensitive,
* `ESP_INTR_FLAG_IRAM` is suggested to be used. In this case, please use the memory allocated from internal RAM in i2c read and write function,
* because we can not access the psram(if psram is enabled) in interrupt handle function when cache is disabled.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Driver installation error
*/
esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags);
/**
* @brief Delete I2C driver
*
* @note This function does not guarantee thread safety.
* Please make sure that no thread will continuously hold semaphores before calling the delete function.
*
* @param i2c_num I2C port to delete
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_driver_delete(i2c_port_t i2c_num);
/**
* @brief Configure an I2C bus with the given configuration.
*
* @param i2c_num I2C port to configure
* @param i2c_conf Pointer to the I2C configuration
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf);
/**
* @brief reset I2C tx hardware fifo
*
* @param i2c_num I2C port number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_reset_tx_fifo(i2c_port_t i2c_num);
/**
* @brief reset I2C rx fifo
*
* @param i2c_num I2C port number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_reset_rx_fifo(i2c_port_t i2c_num);
/**
* @brief Configure GPIO pins for I2C SCK and SDA signals.
*
* @param i2c_num I2C port number
* @param sda_io_num GPIO number for I2C SDA signal
* @param scl_io_num GPIO number for I2C SCL signal
* @param sda_pullup_en Enable the internal pullup for SDA pin
* @param scl_pullup_en Enable the internal pullup for SCL pin
* @param mode I2C mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num,
bool sda_pullup_en, bool scl_pullup_en, i2c_mode_t mode);
/**
* @brief Perform a write to a device connected to a particular I2C port.
* This function is a wrapper to `i2c_master_start()`, `i2c_master_write()`, `i2c_master_read()`, etc...
* It shall only be called in I2C master mode.
*
* @param i2c_num I2C port number to perform the transfer on
* @param device_address I2C device's 7-bit address
* @param write_buffer Bytes to send on the bus
* @param write_size Size, in bytes, of the write buffer
* @param ticks_to_wait Maximum ticks to wait before issuing a timeout.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Sending command error, slave hasn't ACK the transfer.
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
*/
esp_err_t i2c_master_write_to_device(i2c_port_t i2c_num, uint8_t device_address,
const uint8_t* write_buffer, size_t write_size,
TickType_t ticks_to_wait);
/**
* @brief Perform a read to a device connected to a particular I2C port.
* This function is a wrapper to `i2c_master_start()`, `i2c_master_write()`, `i2c_master_read()`, etc...
* It shall only be called in I2C master mode.
*
* @param i2c_num I2C port number to perform the transfer on
* @param device_address I2C device's 7-bit address
* @param read_buffer Buffer to store the bytes received on the bus
* @param read_size Size, in bytes, of the read buffer
* @param ticks_to_wait Maximum ticks to wait before issuing a timeout.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Sending command error, slave hasn't ACK the transfer.
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
*/
esp_err_t i2c_master_read_from_device(i2c_port_t i2c_num, uint8_t device_address,
uint8_t* read_buffer, size_t read_size,
TickType_t ticks_to_wait);
/**
* @brief Perform a write followed by a read to a device on the I2C bus.
* A repeated start signal is used between the `write` and `read`, thus, the bus is
* not released until the two transactions are finished.
* This function is a wrapper to `i2c_master_start()`, `i2c_master_write()`, `i2c_master_read()`, etc...
* It shall only be called in I2C master mode.
*
* @param i2c_num I2C port number to perform the transfer on
* @param device_address I2C device's 7-bit address
* @param write_buffer Bytes to send on the bus
* @param write_size Size, in bytes, of the write buffer
* @param read_buffer Buffer to store the bytes received on the bus
* @param read_size Size, in bytes, of the read buffer
* @param ticks_to_wait Maximum ticks to wait before issuing a timeout.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Sending command error, slave hasn't ACK the transfer.
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
*/
esp_err_t i2c_master_write_read_device(i2c_port_t i2c_num, uint8_t device_address,
const uint8_t* write_buffer, size_t write_size,
uint8_t* read_buffer, size_t read_size,
TickType_t ticks_to_wait);
/**
* @brief Create and initialize an I2C commands list with a given buffer.
* All the allocations for data or signals (START, STOP, ACK, ...) will be
* performed within this buffer.
* This buffer must be valid during the whole transaction.
* After finishing the I2C transactions, it is required to call `i2c_cmd_link_delete_static()`.
*
* @note It is **highly** advised to not allocate this buffer on the stack. The size of the data
* used underneath may increase in the future, resulting in a possible stack overflow as the macro
* `I2C_LINK_RECOMMENDED_SIZE` would also return a bigger value.
* A better option is to use a buffer allocated statically or dynamically (with `malloc`).
*
* @param buffer Buffer to use for commands allocations
* @param size Size in bytes of the buffer
*
* @return Handle to the I2C command link or NULL if the buffer provided is too small, please
* use `I2C_LINK_RECOMMENDED_SIZE` macro to get the recommended size for the buffer.
*/
i2c_cmd_handle_t i2c_cmd_link_create_static(uint8_t* buffer, uint32_t size);
/**
* @brief Create and initialize an I2C commands list with a given buffer.
* After finishing the I2C transactions, it is required to call `i2c_cmd_link_delete()`
* to release and return the resources.
* The required bytes will be dynamically allocated.
*
* @return Handle to the I2C command link or NULL in case of insufficient dynamic memory.
*/
i2c_cmd_handle_t i2c_cmd_link_create(void);
/**
* @brief Free the I2C commands list allocated statically with `i2c_cmd_link_create_static`.
*
* @param cmd_handle I2C commands list allocated statically. This handle should be created thanks to
* `i2c_cmd_link_create_static()` function
*/
void i2c_cmd_link_delete_static(i2c_cmd_handle_t cmd_handle);
/**
* @brief Free the I2C commands list
*
* @param cmd_handle I2C commands list. This handle should be created thanks to
* `i2c_cmd_link_create()` function
*/
void i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle);
/**
* @brief Queue a "START signal" to the given commands list.
* This function shall only be called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all the queued commands.
*
* @param cmd_handle I2C commands list
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle);
/**
* @brief Queue a "write byte" command to the commands list.
* A single byte will be sent on the I2C port. This function shall only be
* called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all queued commands
*
* @param cmd_handle I2C commands list
* @param data Byte to send on the port
* @param ack_en Enable ACK signal
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en);
/**
* @brief Queue a "write (multiple) bytes" command to the commands list.
* This function shall only be called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all queued commands
*
* @param cmd_handle I2C commands list
* @param data Bytes to send. This buffer shall remain **valid** until the transaction is finished.
* If the PSRAM is enabled and `intr_flag` is set to `ESP_INTR_FLAG_IRAM`,
* `data` should be allocated from internal RAM.
* @param data_len Length, in bytes, of the data buffer
* @param ack_en Enable ACK signal
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, const uint8_t *data, size_t data_len, bool ack_en);
/**
* @brief Queue a "read byte" command to the commands list.
* A single byte will be read on the I2C bus. This function shall only be
* called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all queued commands
*
* @param cmd_handle I2C commands list
* @param data Pointer where the received byte will the stored. This buffer shall remain **valid**
* until the transaction is finished.
* @param ack ACK signal
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t *data, i2c_ack_type_t ack);
/**
* @brief Queue a "read (multiple) bytes" command to the commands list.
* Multiple bytes will be read on the I2C bus. This function shall only be
* called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all queued commands
*
* @param cmd_handle I2C commands list
* @param data Pointer where the received bytes will the stored. This buffer shall remain **valid**
* until the transaction is finished.
* @param data_len Size, in bytes, of the `data` buffer
* @param ack ACK signal
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t data_len, i2c_ack_type_t ack);
/**
* @brief Queue a "STOP signal" to the given commands list.
* This function shall only be called in I2C master mode.
* Call `i2c_master_cmd_begin()` to send all the queued commands.
*
* @param cmd_handle I2C commands list
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NO_MEM The static buffer used to create `cmd_handler` is too small
* - ESP_FAIL No more memory left on the heap
*/
esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);
/**
* @brief Send all the queued commands on the I2C bus, in master mode.
* The task will be blocked until all the commands have been sent out.
* The I2C port is protected by mutex, so this function is thread-safe.
* This function shall only be called in I2C master mode.
*
* @param i2c_num I2C port number
* @param cmd_handle I2C commands list
* @param ticks_to_wait Maximum ticks to wait before issuing a timeout.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Sending command error, slave hasn't ACK the transfer.
* - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode.
* - ESP_ERR_TIMEOUT Operation timeout because the bus is busy.
*/
esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait);
#if SOC_I2C_SUPPORT_SLAVE
/**
* @brief Write bytes to internal ringbuffer of the I2C slave data. When the TX fifo empty, the ISR will
* fill the hardware FIFO with the internal ringbuffer's data.
* @note This function shall only be called in I2C slave mode.
*
* @param i2c_num I2C port number
* @param data Bytes to write into internal buffer
* @param size Size, in bytes, of `data` buffer
* @param ticks_to_wait Maximum ticks to wait.
*
* @return
* - ESP_FAIL (-1) Parameter error
* - Other (>=0) The number of data bytes pushed to the I2C slave buffer.
*/
int i2c_slave_write_buffer(i2c_port_t i2c_num, const uint8_t *data, int size, TickType_t ticks_to_wait);
/**
* @brief Read bytes from I2C internal buffer. When the I2C bus receives data, the ISR will copy them
* from the hardware RX FIFO to the internal ringbuffer.
* Calling this function will then copy bytes from the internal ringbuffer to the `data` user buffer.
* @note This function shall only be called in I2C slave mode.
*
* @param i2c_num I2C port number
* @param data Buffer to fill with ringbuffer's bytes
* @param max_size Maximum bytes to read
* @param ticks_to_wait Maximum waiting ticks
*
* @return
* - ESP_FAIL(-1) Parameter error
* - Others(>=0) The number of data bytes read from I2C slave buffer.
*/
int i2c_slave_read_buffer(i2c_port_t i2c_num, uint8_t *data, size_t max_size, TickType_t ticks_to_wait);
#endif // SOC_I2C_SUPPORT_SLAVE
/**
* @brief Set I2C master clock period
*
* @param i2c_num I2C port number
* @param high_period Clock cycle number during SCL is high level, high_period is a 14 bit value
* @param low_period Clock cycle number during SCL is low level, low_period is a 14 bit value
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period);
/**
* @brief Get I2C master clock period
*
* @param i2c_num I2C port number
* @param high_period pointer to get clock cycle number during SCL is high level, will get a 14 bit value
* @param low_period pointer to get clock cycle number during SCL is low level, will get a 14 bit value
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_period(i2c_port_t i2c_num, int *high_period, int *low_period);
/**
* @brief Enable hardware filter on I2C bus
* Sometimes the I2C bus is disturbed by high frequency noise(about 20ns), or the rising edge of
* the SCL clock is very slow, these may cause the master state machine to break.
* Enable hardware filter can filter out high frequency interference and make the master more stable.
* @note Enable filter will slow down the SCL clock.
*
* @param i2c_num I2C port number to filter
* @param cyc_num the APB cycles need to be filtered (0<= cyc_num <=7).
* When the period of a pulse is less than cyc_num * APB_cycle, the I2C controller will ignore this pulse.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num);
/**
* @brief Disable filter on I2C bus
*
* @param i2c_num I2C port number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_filter_disable(i2c_port_t i2c_num);
/**
* @brief set I2C master start signal timing
*
* @param i2c_num I2C port number
* @param setup_time clock number between the falling-edge of SDA and rising-edge of SCL for start mark, it's a 10-bit value.
* @param hold_time clock num between the falling-edge of SDA and falling-edge of SCL for start mark, it's a 10-bit value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
/**
* @brief get I2C master start signal timing
*
* @param i2c_num I2C port number
* @param setup_time pointer to get setup time
* @param hold_time pointer to get hold time
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_start_timing(i2c_port_t i2c_num, int *setup_time, int *hold_time);
/**
* @brief set I2C master stop signal timing
*
* @param i2c_num I2C port number
* @param setup_time clock num between the rising-edge of SCL and the rising-edge of SDA, it's a 10-bit value.
* @param hold_time clock number after the STOP bit's rising-edge, it's a 14-bit value.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time);
/**
* @brief get I2C master stop signal timing
*
* @param i2c_num I2C port number
* @param setup_time pointer to get setup time.
* @param hold_time pointer to get hold time.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_stop_timing(i2c_port_t i2c_num, int *setup_time, int *hold_time);
/**
* @brief set I2C data signal timing
*
* @param i2c_num I2C port number
* @param sample_time clock number I2C used to sample data on SDA after the rising-edge of SCL, it's a 10-bit value
* @param hold_time clock number I2C used to hold the data after the falling-edge of SCL, it's a 10-bit value
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time);
/**
* @brief get I2C data signal timing
*
* @param i2c_num I2C port number
* @param sample_time pointer to get sample time
* @param hold_time pointer to get hold time
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_data_timing(i2c_port_t i2c_num, int *sample_time, int *hold_time);
/**
* @brief set I2C timeout value
* @param i2c_num I2C port number
* @param timeout timeout value for I2C bus (unit: APB 80Mhz clock cycle)
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_timeout(i2c_port_t i2c_num, int timeout);
/**
* @brief get I2C timeout value
* @param i2c_num I2C port number
* @param timeout pointer to get timeout value
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_timeout(i2c_port_t i2c_num, int *timeout);
/**
* @brief set I2C data transfer mode
*
* @param i2c_num I2C port number
* @param tx_trans_mode I2C sending data mode
* @param rx_trans_mode I2C receving data mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, i2c_trans_mode_t rx_trans_mode);
/**
* @brief get I2C data transfer mode
*
* @param i2c_num I2C port number
* @param tx_trans_mode pointer to get I2C sending data mode
* @param rx_trans_mode pointer to get I2C receiving data mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode, i2c_trans_mode_t *rx_trans_mode);
#ifdef __cplusplus
}
#endif
#endif /*_DRIVER_I2C_H_*/
@@ -1,213 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "driver/i2s_types.h"
#include "hal/i2s_types.h"
#include "esp_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief get default I2S property
*/
#define I2S_CHANNEL_DEFAULT_CONFIG(i2s_num, i2s_role) { \
.id = i2s_num, \
.role = i2s_role, \
.dma_desc_num = 6, \
.dma_frame_num = 240, \
.auto_clear = false, \
}
#define I2S_GPIO_UNUSED GPIO_NUM_NC /*!< Used in i2s_gpio_config_t for signals which are not used */
/**
* @brief Group of I2S callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well.
*/
typedef struct {
i2s_isr_callback_t on_recv; /**< Callback of data received event, only for rx channel
* The event data includes DMA buffer address and size that just finished receiving data
*/
i2s_isr_callback_t on_recv_q_ovf; /**< Callback of receiving queue overflowed event, only for rx channel
* The event data includes buffer size that has been overwritten
*/
i2s_isr_callback_t on_sent; /**< Callback of data sent event, only for tx channel
* The event data includes DMA buffer address and size that just finished sending data
*/
i2s_isr_callback_t on_send_q_ovf; /**< Callback of sending queue overflowed event, only for tx channel
* The event data includes buffer size that has been overwritten
*/
} i2s_event_callbacks_t;
/**
* @brief I2S controller channel configuration
*/
typedef struct {
i2s_port_t id; /*!< I2S port id */
i2s_role_t role; /*!< I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE */
/* DMA configurations */
uint32_t dma_desc_num; /*!< I2S DMA buffer number, it is also the number of DMA descriptor */
uint32_t dma_frame_num; /*!< I2S frame number in one DMA buffer. One frame means one-time sample data in all slots,
* it should be the multiple of '3' when the data bit width is 24.
*/
bool auto_clear; /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */
} i2s_chan_config_t;
/**
* @brief I2S channel information
*/
typedef struct {
i2s_port_t id; /*!< I2S port id */
i2s_role_t role; /*!< I2S role, I2S_ROLE_MASTER or I2S_ROLE_SLAVE */
i2s_dir_t dir; /*!< I2S channel direction */
i2s_comm_mode_t mode; /*!< I2S channel communication mode */
i2s_chan_handle_t pair_chan; /*!< I2S pair channel handle in duplex mode, always NULL in simplex mode */
} i2s_chan_info_t;
/**
* @brief Allocate new I2S channel(s)
* @note The new created I2S channel handle will be REGISTERED state after it is allocated successfully.
* @note When the port id in channel configuration is I2S_NUM_AUTO, driver will allocate I2S port automatically
* on one of the i2s controller, otherwise driver will try to allocate the new channel on the selected port.
* @note If both tx_handle and rx_handle are not NULL, it means this I2S controller will work at full-duplex mode,
* the rx and tx channels will be allocated on a same I2S port in this case.
* Note that some configurations of tx/rx channel are shared on ESP32 and ESP32S2,
* so please make sure they are working at same condition and under same status(start/stop).
* Currently, full-duplex mode can't guarantee tx/rx channels write/read synchronously,
* they can only share the clock signals for now.
* @note If tx_handle OR rx_handle is NULL, it means this I2S controller will work at simplex mode.
* For ESP32 and ESP32S2, the whole I2S controller (i.e. both rx and tx channel) will be occupied,
* even if only one of rx or tx channel is registered.
* For the other targets, another channel on this controller will still available.
*
* @param[in] chan_cfg I2S controller channel configurations
* @param[out] ret_tx_handle I2S channel handler used for managing the sending channel(optional)
* @param[out] ret_rx_handle I2S channel handler used for managing the receiving channel(optional)
* @return
* - ESP_OK Allocate new channel(s) success
* - ESP_ERR_NOT_SUPPORTED The communication mode is not supported on the current chip
* - ESP_ERR_INVALID_ARG NULL pointer or illegal parameter in i2s_chan_config_t
* - ESP_ERR_NOT_FOUND No available I2S channel found
*/
esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *ret_tx_handle, i2s_chan_handle_t *ret_rx_handle);
/**
* @brief Delete the i2s channel
* @note Only allowed to be called when the i2s channel is at REGISTERED or READY state (i.e., it should stop before deleting it).
* @note Resource will be free automatically if all channels in one port are deleted
*
* @param[in] handle I2S channel handler
* - ESP_OK Delete successfully
* - ESP_ERR_INVALID_ARG NULL pointer
*/
esp_err_t i2s_del_channel(i2s_chan_handle_t handle);
/**
* @brief Get I2S channel information
*
* @param[in] handle I2S channel handler
* @param[out] chan_info I2S channel basic information
* @return
* - ESP_OK Get i2s channel information success
* - ESP_ERR_NOT_FOUND The input handle doesn't match any registered I2S channels, it may not an i2s channel handle or not available any more
* - ESP_ERR_INVALID_ARG The input handle or chan_info pointer is NULL
*/
esp_err_t i2s_channel_get_info(i2s_chan_handle_t handle, i2s_chan_info_t *chan_info);
/**
* @brief Enable the i2s channel
* @note Only allowed to be called when the channel state is READY, (i.e., channel has been initialized, but not started)
* the channel will enter RUNNING state once it is enabled successfully.
* @note Enable the channel can start the I2S communication on hardware. It will start outputting bclk and ws signal.
* For mclk signal, it will start to output when initialization is finished
*
* @param[in] handle I2S channel handler
* - ESP_OK Start successfully
* - ESP_ERR_INVALID_ARG NULL pointer
* - ESP_ERR_INVALID_STATE This channel has not initialized or already started
*/
esp_err_t i2s_channel_enable(i2s_chan_handle_t handle);
/**
* @brief Disable the i2s channel
* @note Only allowed to be called when the channel state is READY / RUNNING, (i.e., channel has been initialized)
* the channel will enter READY state once it is disabled successfully.
* @note Disable the channel can stop the I2S communication on hardware. It will stop bclk and ws signal but not mclk signal
*
* @param[in] handle I2S channel handler
* @return
* - ESP_OK Stop successfully
* - ESP_ERR_INVALID_ARG NULL pointer
* - ESP_ERR_INVALID_STATE This channel has not stated
*/
esp_err_t i2s_channel_disable(i2s_chan_handle_t handle);
/**
* @brief I2S write data
* @note Only allowed to be called when the channel state is RUNNING, (i.e., tx channel has been started and is not writing now)
* but the RUNNING only stands for the software state, it doesn't mean there is no the signal transporting on line.
*
* @param[in] handle I2S channel handler
* @param[in] src The pointer of sent data buffer
* @param[in] size Max data buffer length
* @param[out] bytes_written Byte number that actually be sent
* @param[in] timeout_ms Max block time
* @return
* - ESP_OK Write successfully
* - ESP_ERR_INVALID_ARG NULL pointer or this handle is not tx handle
* - ESP_ERR_TIMEOUT Writing timeout, no writing event received from ISR within ticks_to_wait
* - ESP_ERR_INVALID_STATE I2S is not ready to write
*/
esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t size, size_t *bytes_written, uint32_t timeout_ms);
/**
* @brief I2S read data
* @note Only allowed to be called when the channel state is RUNNING
* but the RUNNING only stands for the software state, it doesn't mean there is no the signal transporting on line.
*
* @param[in] handle I2S channel handler
* @param[in] dest The pointer of receiving data buffer
* @param[in] size Max data buffer length
* @param[out] bytes_read Byte number that actually be read
* @param[in] timeout_ms Max block time
* @return
* - ESP_OK Read successfully
* - ESP_ERR_INVALID_ARG NULL pointer or this handle is not rx handle
* - ESP_ERR_TIMEOUT Reading timeout, no reading event received from ISR within ticks_to_wait
* - ESP_ERR_INVALID_STATE I2S is not ready to read
*/
esp_err_t i2s_channel_read(i2s_chan_handle_t handle, void *dest, size_t size, size_t *bytes_read, uint32_t timeout_ms);
/**
* @brief Set event callbacks for I2S channel
*
* @note Only allowed to be called when the channel state is REGISTARED / READY, (i.e., before channel starts)
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `callbacks` structure to NULL.
* @note When CONFIG_I2S_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well. The `user_data` should also reside in SRAM or internal RAM as well.
*
* @param[in] handle I2S channel handler
* @param[in] callbacks Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK Set event callbacks successfully
* - ESP_ERR_INVALID_ARG Set event callbacks failed because of invalid argument
* - ESP_ERR_INVALID_STATE Set event callbacks failed because the current channel state is not REGISTARED or READY
*/
esp_err_t i2s_channel_register_event_callback(i2s_chan_handle_t handle, const i2s_event_callbacks_t *callbacks, void *user_data);
#ifdef __cplusplus
}
#endif
-373
View File
@@ -1,373 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S PDM communication mode
* Features:
* - Only support PDM tx/rx mode
* - Fixed to 2 slots
* - Data bit width only support 16 bits
*/
#pragma once
#include "hal/i2s_types.h"
#include "hal/gpio_types.h"
#include "driver/i2s_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_I2S_SUPPORTS_PDM_RX
/**
* @brief PDM format in 2 slots(RX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \
}
/**
* @brief i2s default pdm rx clock configuration
* @param rate sample rate
*/
#define I2S_PDM_RX_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_SRC_DEFAULT, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
.dn_sample_mode = I2S_PDM_DSR_8S \
}
/**
* @brief I2S slot configuration for pdm rx mode
*/
typedef struct {
/* General fields */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) , only support 16 bits for PDM mode */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
/* Particular fields */
i2s_pdm_slot_mask_t slot_mask; /*!< Choose the slots to activate */
} i2s_pdm_rx_slot_config_t;
/**
* @brief I2S clock configuration for pdm rx mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
/* Particular fields */
i2s_pdm_dsr_t dn_sample_mode; /*!< Down-sampling rate mode */
} i2s_pdm_rx_clk_config_t;
/**
* @brief I2S PDM tx mode GPIO pins configuration
*/
typedef struct {
gpio_num_t clk; /*!< PDM clk pin, output */
union {
gpio_num_t din; /*!< DATA pin 0, input */
gpio_num_t dins[SOC_I2S_PDM_MAX_RX_LINES]; /*!< DATA pins, input, only take effect when corresponding I2S_PDM_RX_LINEx_SLOT_xxx is enabled in i2s_pdm_rx_slot_config_t::slot_mask */
};
struct {
uint32_t clk_inv: 1; /*!< Set 1 to invert the clk output */
} invert_flags; /*!< GPIO pin invert flags */
} i2s_pdm_rx_gpio_config_t;
/**
* @brief I2S PDM RX mode major configuration that including clock/slot/gpio configuration
*/
typedef struct {
i2s_pdm_rx_clk_config_t clk_cfg; /*!< PDM RX clock configurations, can be generated by macro I2S_PDM_RX_CLK_DEFAULT_CONFIG */
i2s_pdm_rx_slot_config_t slot_cfg; /*!< PDM RX slot configurations, can be generated by macro I2S_PDM_RX_SLOT_DEFAULT_CONFIG */
i2s_pdm_rx_gpio_config_t gpio_cfg; /*!< PDM RX slot configurations, specified by user */
} i2s_pdm_rx_config_t;
/**
* @brief Initialize i2s channel to PDM RX mode
* @note Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized)
* and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.
*
* @param[in] handle I2S rx channel handler
* @param[in] pdm_rx_cfg Configurations for PDM RX mode, including clock, slot and gpio
* The clock configuration can be generated by the helper macro `I2S_PDM_RX_CLK_DEFAULT_CONFIG`
* The slot configuration can be generated by the helper macro `I2S_PDM_RX_SLOT_DEFAULT_CONFIG`
*
* @return
* - ESP_OK Initialize successfully
* - ESP_ERR_NO_MEM No memory for storing the channel information
* - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration
* - ESP_ERR_INVALID_STATE This channel is not registered
*/
esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_rx_config_t *pdm_rx_cfg);
/**
* @brief Reconfigure the I2S clock for PDM RX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM RX mode, i.e., 'i2s_channel_init_pdm_rx_mode' has been called before reconfiguring
*
* @param[in] handle I2S rx channel handler
* @param[in] clk_cfg PDM RX mode clock configuration, can be generated by `I2S_PDM_RX_CLK_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_rx_clock(i2s_chan_handle_t handle, const i2s_pdm_rx_clk_config_t *clk_cfg);
/**
* @brief Reconfigure the I2S slot for PDM RX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM RX mode, i.e., 'i2s_channel_init_pdm_rx_mode' has been called before reconfiguring
*
* @param[in] handle I2S rx channel handler
* @param[in] slot_cfg PDM RX mode slot configuration, can be generated by `I2S_PDM_RX_SLOT_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_NO_MEM No memory for DMA buffer
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_rx_slot(i2s_chan_handle_t handle, const i2s_pdm_rx_slot_config_t *slot_cfg);
/**
* @brief Reconfigure the I2S gpio for PDM RX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM RX mode, i.e., 'i2s_channel_init_pdm_rx_mode' has been called before reconfiguring
*
* @param[in] handle I2S rx channel handler
* @param[in] gpio_cfg PDM RX mode gpio configuration, specified by user
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_rx_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_gpio_config_t *gpio_cfg);
#endif // SOC_I2S_SUPPORTS_PDM_RX
#if SOC_I2S_SUPPORTS_PDM_TX
#if SOC_I2S_HW_VERSION_2
/**
* @brief PDM style in 2 slots(TX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_TX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.sd_prescale = 0, \
.sd_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.hp_scale = I2S_PDM_SIG_SCALING_DIV_2, \
.lp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.sinc_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.line_mode = I2S_PDM_TX_ONE_LINE_CODEC, \
.hp_en = true, \
.hp_cut_off_freq_hz = 35.5, \
.sd_dither = 0, \
.sd_dither2 = 1, \
}
#else // SOC_I2S_HW_VERSION_2
/**
* @brief PDM style in 2 slots(TX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_TX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = I2S_PDM_SLOT_BOTH, \
.sd_prescale = 0, \
.sd_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.hp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.lp_scale = I2S_PDM_SIG_SCALING_MUL_1, \
.sinc_scale = I2S_PDM_SIG_SCALING_MUL_1, \
}
#endif // SOC_I2S_HW_VERSION_2
/**
* @brief i2s default pdm tx clock configuration
* @note TX PDM can only be set to the following two up-sampling rate configurations:
* 1: fp = 960, fs = sample_rate_hz / 100, in this case, Fpdm = 128*48000
* 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate_hz
* If the pdm receiver do not care the pdm serial clock, it's recommended set Fpdm = 128*48000.
* Otherwise, the second configuration should be adopted.
* @param rate sample rate (not suggest to exceed 48000 Hz, otherwise more glitches and noise may appear)
*/
#define I2S_PDM_TX_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_SRC_DEFAULT, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
.up_sample_fp = 960, \
.up_sample_fs = 480, \
}
/*
High Pass Filter Cut-off Frequency Sheet
+----------------+------------------+----------------+------------------+----------------+------------------+
| param0, param5 | cut-off freq(Hz) | param0, param5 | cut-off freq(Hz) | param0, param5 | cut-off freq(Hz) |
+----------------+------------------+----------------+------------------+----------------+------------------+
| (0, 0) | 185 | (3, 3) | 115 | (5, 5) | 69 |
| (0, 1) | 172 | (1, 7) | 106 | (4, 7) | 63 |
| (1, 1) | 160 | (2, 4) | 104 | (5, 6) | 58 |
| (1, 2) | 150 | (4, 4) | 92 | (5, 7) | 49 |
| (2, 2) | 137 | (2, 7) | 91.5 | (6, 6) | 46 |
| (2, 3) | 126 | (4, 5) | 81 | (6, 7) | 35.5 |
| (0, 3) | 120 | (3, 7) | 77.2 | (7, 7) | 23.3 |
+----------------+------------------+----------------+------------------+----------------+------------------+
*/
/**
* @brief I2S slot configuration for pdm tx mode
*/
typedef struct {
/* General fields */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample), only support 16 bits for PDM mode */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot), only support 16 bits for PDM mode */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* For PDM TX mode, mono means the data buffer only contains one slot data,
* Stereo means the data buffer contains two slots data
*/
/* Particular fields */
#if SOC_I2S_HW_VERSION_1
i2s_pdm_slot_mask_t slot_mask; /*!< Slot mask to choose left or right slot */
#endif
uint32_t sd_prescale; /*!< Sigma-delta filter prescale */
i2s_pdm_sig_scale_t sd_scale; /*!< Sigma-delta filter scaling value */
i2s_pdm_sig_scale_t hp_scale; /*!< High pass filter scaling value */
i2s_pdm_sig_scale_t lp_scale; /*!< Low pass filter scaling value */
i2s_pdm_sig_scale_t sinc_scale; /*!< Sinc filter scaling value */
#if SOC_I2S_HW_VERSION_2
i2s_pdm_tx_line_mode_t line_mode; /*!< PDM TX line mode, one-line codec, one-line dac, two-line dac mode can be selected */
bool hp_en; /*!< High pass filter enable */
float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */
uint32_t sd_dither; /*!< Sigma-delta filter dither */
uint32_t sd_dither2; /*!< Sigma-delta filter dither2 */
#endif // SOC_I2S_HW_VERSION_2
} i2s_pdm_tx_slot_config_t;
/**
* @brief I2S clock configuration for pdm tx mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate, not suggest to exceed 48000 Hz, otherwise more glitches and noise may appear */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate */
/* Particular fields */
uint32_t up_sample_fp; /*!< Up-sampling param fp */
uint32_t up_sample_fs; /*!< Up-sampling param fs, not allowed to be greater than 480 */
} i2s_pdm_tx_clk_config_t;
/**
* @brief I2S PDM tx mode GPIO pins configuration
*/
typedef struct {
gpio_num_t clk; /*!< PDM clk pin, output */
gpio_num_t dout; /*!< DATA pin, output */
#if SOC_I2S_PDM_MAX_TX_LINES > 1
gpio_num_t dout2; /*!< The second data pin for the DAC dual-line mode,
* only take effect when the line mode is `I2S_PDM_TX_TWO_LINE_DAC`
*/
#endif
struct {
uint32_t clk_inv: 1; /*!< Set 1 to invert the clk output */
} invert_flags; /*!< GPIO pin invert flags */
} i2s_pdm_tx_gpio_config_t;
/**
* @brief I2S PDM TX mode major configuration that including clock/slot/gpio configuration
*/
typedef struct {
i2s_pdm_tx_clk_config_t clk_cfg; /*!< PDM TX clock configurations, can be generated by macro I2S_PDM_TX_CLK_DEFAULT_CONFIG */
i2s_pdm_tx_slot_config_t slot_cfg; /*!< PDM TX slot configurations, can be generated by macro I2S_PDM_TX_SLOT_DEFAULT_CONFIG */
i2s_pdm_tx_gpio_config_t gpio_cfg; /*!< PDM TX gpio configurations, specified by user */
} i2s_pdm_tx_config_t;
/**
* @brief Initialize i2s channel to PDM TX mode
* @note Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized)
* and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.
*
* @param[in] handle I2S tx channel handler
* @param[in] pdm_tx_cfg Configurations for PDM TX mode, including clock, slot and gpio
* The clock configuration can be generated by the helper macro `I2S_PDM_TX_CLK_DEFAULT_CONFIG`
* The slot configuration can be generated by the helper macro `I2S_PDM_TX_SLOT_DEFAULT_CONFIG`
*
* @return
* - ESP_OK Initialize successfully
* - ESP_ERR_NO_MEM No memory for storing the channel information
* - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration
* - ESP_ERR_INVALID_STATE This channel is not registered
*/
esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_tx_config_t *pdm_tx_cfg);
/**
* @brief Reconfigure the I2S clock for PDM TX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM TX mode, i.e., 'i2s_channel_init_pdm_tx_mode' has been called before reconfiguring
*
* @param[in] handle I2S tx channel handler
* @param[in] clk_cfg PDM TX mode clock configuration, can be generated by `I2S_PDM_TX_CLK_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_tx_clock(i2s_chan_handle_t handle, const i2s_pdm_tx_clk_config_t *clk_cfg);
/**
* @brief Reconfigure the I2S slot for PDM TX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM TX mode, i.e., 'i2s_channel_init_pdm_tx_mode' has been called before reconfiguring
*
* @param[in] handle I2S tx channel handler
* @param[in] slot_cfg PDM TX mode slot configuration, can be generated by `I2S_PDM_TX_SLOT_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_NO_MEM No memory for DMA buffer
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_tx_slot(i2s_chan_handle_t handle, const i2s_pdm_tx_slot_config_t *slot_cfg);
/**
* @brief Reconfigure the I2S gpio for PDM TX mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to PDM TX mode, i.e., 'i2s_channel_init_pdm_tx_mode' has been called before reconfiguring
*
* @param[in] handle I2S tx channel handler
* @param[in] gpio_cfg PDM TX mode gpio configuration, specified by user
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not PDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_pdm_tx_gpio(i2s_chan_handle_t handle, const i2s_pdm_tx_gpio_config_t *gpio_cfg);
#endif // SOC_I2S_SUPPORTS_PDM_TX
#ifdef __cplusplus
}
#endif
-341
View File
@@ -1,341 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S standard communication mode
* Features:
* - Philips/MSB/PCM are supported in standard mode
* - Fixed to 2 slots
*/
#pragma once
#include "hal/i2s_types.h"
#include "hal/gpio_types.h"
#include "driver/i2s_common.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_IDF_TARGET_ESP32
/**
* @brief Philips format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = true, \
.msb_right = (bits_per_sample <= I2S_DATA_BIT_WIDTH_16BIT) ? \
true : false, \
}
/**
* @brief PCM(short) format in 2 slots
* @note PCM(long) is same as philips in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.msb_right = (bits_per_sample <= I2S_DATA_BIT_WIDTH_16BIT) ? \
true : false, \
}
/**
* @brief MSB format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = false, \
.msb_right = (bits_per_sample <= I2S_DATA_BIT_WIDTH_16BIT) ? \
true : false, \
}
#elif CONFIG_IDF_TARGET_ESP32S2
/**
* @brief Philips format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = true, \
.msb_right = true, \
}
/**
* @brief PCM(short) format in 2 slots
* @note PCM(long) is same as philips in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.msb_right = true, \
}
/**
* @brief MSB format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_STD_SLOT_LEFT : I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = false, \
.msb_right = true, \
}
#else
/**
* @brief Philips format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
/**
* @brief PCM(short) format in 2 slots
* @note PCM(long) is same as philips in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_PCM_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = I2S_STD_SLOT_BOTH, \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
/**
* @brief MSB format in 2 slots
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_STD_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = I2S_STD_SLOT_BOTH, \
.ws_width = bits_per_sample, \
.ws_pol = false, \
.bit_shift = false, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false \
}
#endif
/** @cond */
#define I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) \
I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) // Alias
/** @endcond */
/**
* @brief i2s default standard clock configuration
* @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while using 24 bits data width
* Otherwise the sample rate might be imprecise since the bclk division is not a integer
* @param rate sample rate
*/
#define I2S_STD_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_SRC_DEFAULT, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
}
/**
* @brief I2S slot configuration for standard mode
*/
typedef struct {
/* General fields */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample) */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* In TX direction, mono means the written buffer contains only one slot data
* and stereo means the written buffer contains both left and right data
*/
/* Particular fields */
i2s_std_slot_mask_t slot_mask; /*!< Select the left, right or both slot */
uint32_t ws_width; /*!< WS signal width (i.e. the number of bclk ticks that ws signal is high) */
bool ws_pol; /*!< WS signal polarity, set true to enable high lever first */
bool bit_shift; /*!< Set to enable bit shift in Philips mode */
#if SOC_I2S_HW_VERSION_1 // For esp32/esp32-s2
bool msb_right; /*!< Set to place right channel data at the MSB in the FIFO */
#else
bool left_align; /*!< Set to enable left alignment */
bool big_endian; /*!< Set to enable big endian */
bool bit_order_lsb; /*!< Set to enable lsb first */
#endif
} i2s_std_slot_config_t;
/**
* @brief I2S clock configuration for standard mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate
* Default is 256 in the helper macro, it can satisfy most of cases,
* but please set this field a multiple of '3' (like 384) when using 24-bit data width,
* otherwise the sample rate might be inaccurate
*/
} i2s_std_clk_config_t;
/**
* @brief I2S standard mode GPIO pins configuration
*/
typedef struct {
gpio_num_t mclk; /*!< MCK pin, output */
gpio_num_t bclk; /*!< BCK pin, input in slave role, output in master role */
gpio_num_t ws; /*!< WS pin, input in slave role, output in master role */
gpio_num_t dout; /*!< DATA pin, output */
gpio_num_t din; /*!< DATA pin, input */
struct {
uint32_t mclk_inv: 1; /*!< Set 1 to invert the mclk output */
uint32_t bclk_inv: 1; /*!< Set 1 to invert the bclk input/output */
uint32_t ws_inv: 1; /*!< Set 1 to invert the ws input/output */
} invert_flags; /*!< GPIO pin invert flags */
} i2s_std_gpio_config_t;
/**
* @brief I2S standard mode major configuration that including clock/slot/gpio configuration
*/
typedef struct {
i2s_std_clk_config_t clk_cfg; /*!< Standard mode clock configuration, can be generated by macro I2S_STD_CLK_DEFAULT_CONFIG */
i2s_std_slot_config_t slot_cfg; /*!< Standard mode slot configuration, can be generated by macros I2S_STD_[mode]_SLOT_DEFAULT_CONFIG, [mode] can be replaced with PHILIPS/MSB/PCM */
i2s_std_gpio_config_t gpio_cfg; /*!< Standard mode gpio configuration, specified by user */
} i2s_std_config_t;
/**
* @brief Initialize i2s channel to standard mode
* @note Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized)
* and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.
*
* @param[in] handle I2S channel handler
* @param[in] std_cfg Configurations for standard mode, including clock, slot and gpio
* The clock configuration can be generated by the helper macro `I2S_STD_CLK_DEFAULT_CONFIG`
* The slot configuration can be generated by the helper macro `I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG`,
* `I2S_STD_PCM_SLOT_DEFAULT_CONFIG` or `I2S_STD_MSB_SLOT_DEFAULT_CONFIG`
*
* @return
* - ESP_OK Initialize successfully
* - ESP_ERR_NO_MEM No memory for storing the channel information
* - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration
* - ESP_ERR_INVALID_STATE This channel is not registered
*/
esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_config_t *std_cfg);
/**
* @brief Reconfigure the I2S clock for standard mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to standard mode, i.e., 'i2s_channel_init_std_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] clk_cfg Standard mode clock configuration, can be generated by `I2S_STD_CLK_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_std_clock(i2s_chan_handle_t handle, const i2s_std_clk_config_t *clk_cfg);
/**
* @brief Reconfigure the I2S slot for standard mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to standard mode, i.e., 'i2s_channel_init_std_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] slot_cfg Standard mode slot configuration, can be generated by `I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG`,
* `I2S_STD_PCM_SLOT_DEFAULT_CONFIG` and `I2S_STD_MSB_SLOT_DEFAULT_CONFIG`.
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_NO_MEM No memory for DMA buffer
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_std_slot(i2s_chan_handle_t handle, const i2s_std_slot_config_t *slot_cfg);
/**
* @brief Reconfigure the I2S gpio for standard mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to standard mode, i.e., 'i2s_channel_init_std_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] gpio_cfg Standard mode gpio configuration, specified by user
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not standard mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_std_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_config_t *gpio_cfg);
#ifdef __cplusplus
}
#endif
-260
View File
@@ -1,260 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file is specified for I2S TDM communication mode
* Features:
* - More than 2 slots
*/
#pragma once
#include "hal/i2s_types.h"
#include "hal/gpio_types.h"
#include "driver/i2s_common.h"
#if SOC_I2S_SUPPORTS_TDM
#ifdef __cplusplus
extern "C" {
#endif
#define I2S_TDM_AUTO_SLOT_NUM (0) // Auto means total slot number will be equal to the maximum active slot number
#define I2S_TDM_AUTO_WS_WIDTH (0) // Auto means ws signal width will be equal to the half width of a frame
/**
* @brief Philips format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mask), \
.ws_width = I2S_TDM_AUTO_WS_WIDTH, \
.ws_pol = false, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief MSB format in active slot enabled that by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mask), \
.ws_width = I2S_TDM_AUTO_WS_WIDTH, \
.ws_pol = false, \
.bit_shift = false, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false ,\
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief PCM(short) format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mask), \
.ws_width = 1, \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/**
* @brief PCM(long) format in active slot that enabled by mask
* @param bits_per_sample i2s data bit width
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
* @param mask active slot mask
*/
#define I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) { \
.data_bit_width = (bits_per_sample), \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mask), \
.ws_width = (bits_per_sample), \
.ws_pol = true, \
.bit_shift = true, \
.left_align = false, \
.big_endian = false, \
.bit_order_lsb = false, \
.skip_mask = false, \
.total_slot = I2S_TDM_AUTO_SLOT_NUM \
}
/** @cond */
#define I2S_TDM_PHILIP_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) \
I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo, mask) // Alias
/** @endcond */
/**
* @brief i2s default tdm clock configuration
* @note Please set the mclk_multiple to I2S_MCLK_MULTIPLE_384 while the data width in slot configuration is set to 24 bits
* Otherwise the sample rate might be imprecise since the bclk division is not a integer
* @param rate sample rate
*/
#define I2S_TDM_CLK_DEFAULT_CONFIG(rate) { \
.sample_rate_hz = rate, \
.clk_src = I2S_CLK_SRC_DEFAULT, \
.mclk_multiple = I2S_MCLK_MULTIPLE_256, \
.bclk_div = 8, \
}
/**
* @brief I2S slot configuration for tdm mode
*/
typedef struct {
/* General fields */
i2s_data_bit_width_t data_bit_width; /*!< I2S sample data bit width (valid data bits per sample) */
i2s_slot_bit_width_t slot_bit_width; /*!< I2S slot bit width (total bits per slot) */
i2s_slot_mode_t slot_mode; /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
/* Particular fields */
i2s_tdm_slot_mask_t slot_mask; /*!< Slot mask. Activating slots by setting 1 to corresponding bits. When the activated slots is not consecutive, those data in inactivated slots will be ignored */
uint32_t ws_width; /*!< WS signal width (i.e. the number of bclk ticks that ws signal is high) */
bool ws_pol; /*!< WS signal polarity, set true to enable high lever first */
bool bit_shift; /*!< Set true to enable bit shift in Philips mode */
bool left_align; /*!< Set true to enable left alignment */
bool big_endian; /*!< Set true to enable big endian */
bool bit_order_lsb; /*!< Set true to enable lsb first */
bool skip_mask; /*!< Set true to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
uint32_t total_slot; /*!< I2S total number of slots. If it is smaller than the biggest activated channel number, it will be set to this number automatically. */
} i2s_tdm_slot_config_t;
/**
* @brief I2S clock configuration for tdm mode
*/
typedef struct {
/* General fields */
uint32_t sample_rate_hz; /*!< I2S sample rate */
i2s_clock_src_t clk_src; /*!< Choose clock source */
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of mclk to the sample rate, only take effect for master role */
uint32_t bclk_div; /*!< The division from mclk to bclk, only take effect for slave role, it shouldn't be smaller than 8. Increase this field when data sent by slave lag behind */
} i2s_tdm_clk_config_t;
/**
* @brief I2S TDM mode GPIO pins configuration
*/
typedef struct {
gpio_num_t mclk; /*!< MCK pin, output */
gpio_num_t bclk; /*!< BCK pin, input in slave role, output in master role */
gpio_num_t ws; /*!< WS pin, input in slave role, output in master role */
gpio_num_t dout; /*!< DATA pin, output */
gpio_num_t din; /*!< DATA pin, input */
struct {
uint32_t mclk_inv: 1; /*!< Set 1 to invert the mclk output */
uint32_t bclk_inv: 1; /*!< Set 1 to invert the bclk input/output */
uint32_t ws_inv: 1; /*!< Set 1 to invert the ws input/output */
} invert_flags; /*!< GPIO pin invert flags */
} i2s_tdm_gpio_config_t;
/**
* @brief I2S TDM mode major configuration that including clock/slot/gpio configuration
*/
typedef struct {
i2s_tdm_clk_config_t clk_cfg; /*!< TDM mode clock configuration, can be generated by macro I2S_TDM_CLK_DEFAULT_CONFIG */
i2s_tdm_slot_config_t slot_cfg; /*!< TDM mode slot configuration, can be generated by macros I2S_TDM_[mode]_SLOT_DEFAULT_CONFIG, [mode] can be replaced with PHILIPS/MSB/PCM_SHORT/PCM_LONG */
i2s_tdm_gpio_config_t gpio_cfg; /*!< TDM mode gpio configuration, specified by user */
} i2s_tdm_config_t;
/**
* @brief Initialize i2s channel to TDM mode
* @note Only allowed to be called when the channel state is REGISTERED, (i.e., channel has been allocated, but not initialized)
* and the state will be updated to READY if initialization success, otherwise the state will return to REGISTERED.
*
* @param[in] handle I2S channel handler
* @param[in] tdm_cfg Configurations for TDM mode, including clock, slot and gpio
* The clock configuration can be generated by the helper macro `I2S_TDM_CLK_DEFAULT_CONFIG`
* The slot configuration can be generated by the helper macro `I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG`,
* `I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG`, `I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG` or `I2S_TDM_MSB_SLOT_DEFAULT_CONFIG`
*
* @return
* - ESP_OK Initialize successfully
* - ESP_ERR_NO_MEM No memory for storing the channel information
* - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration
* - ESP_ERR_INVALID_STATE This channel is not registered
*/
esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_config_t *tdm_cfg);
/**
* @brief Reconfigure the I2S clock for TDM mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to TDM mode, i.e., 'i2s_channel_init_tdm_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] clk_cfg Standard mode clock configuration, can be generated by `I2S_TDM_CLK_DEFAULT_CONFIG`
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not TDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_tdm_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_config_t *clk_cfg);
/**
* @brief Reconfigure the I2S slot for TDM mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to TDM mode, i.e., 'i2s_channel_init_tdm_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] slot_cfg Standard mode slot configuration, can be generated by `I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG`,
* `I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG`, `I2S_TDM_PCM_LONG_SLOT_DEFAULT_CONFIG` or `I2S_TDM_MSB_SLOT_DEFAULT_CONFIG`.
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_NO_MEM No memory for DMA buffer
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not TDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_tdm_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_config_t *slot_cfg);
/**
* @brief Reconfigure the I2S gpio for TDM mode
* @note Only allowed to be called when the channel state is READY, i.e., channel has been initialized, but not started
* this function won't change the state. 'i2s_channel_disable' should be called before calling this function if i2s has started.
* @note The input channel handle has to be initialized to TDM mode, i.e., 'i2s_channel_init_tdm_mode' has been called before reconfiguring
*
* @param[in] handle I2S channel handler
* @param[in] gpio_cfg Standard mode gpio configuration, specified by user
* @return
* - ESP_OK Set clock successfully
* - ESP_ERR_INVALID_ARG NULL pointer, invalid configuration or not TDM mode
* - ESP_ERR_INVALID_STATE This channel is not initialized or not stopped
*/
esp_err_t i2s_channel_reconfig_tdm_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_config_t *gpio_cfg);
#ifdef __cplusplus
}
#endif
#endif // SOC_I2S_SUPPORTS_TDM
@@ -1,80 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief I2S controller port number, the max port number is (SOC_I2S_NUM -1).
*/
typedef enum {
I2S_NUM_0 = 0, /*!< I2S controller port 0 */
#if SOC_I2S_NUM > 1
I2S_NUM_1 = 1, /*!< I2S controller port 1 */
#endif
I2S_NUM_AUTO, /*!< Select whichever port is available */
} i2s_port_t;
/**
* @brief I2S controller communication mode
*/
typedef enum {
I2S_COMM_MODE_STD, /*!< I2S controller using standard communication mode, support philips/MSB/PCM format */
#if SOC_I2S_SUPPORTS_PDM
I2S_COMM_MODE_PDM, /*!< I2S controller using PDM communication mode, support PDM output or input */
#endif
#if SOC_I2S_SUPPORTS_TDM
I2S_COMM_MODE_TDM, /*!< I2S controller using TDM communication mode, support up to 16 slots per frame */
#endif
I2S_COMM_MODE_NONE, /*!< Unspecified I2S controller mode */
} i2s_comm_mode_t;
/**
* @brief The multiple of mclk to sample rate
*/
typedef enum {
I2S_MCLK_MULTIPLE_128 = 128, /*!< mclk = sample_rate * 128 */
I2S_MCLK_MULTIPLE_256 = 256, /*!< mclk = sample_rate * 256 */
I2S_MCLK_MULTIPLE_384 = 384, /*!< mclk = sample_rate * 384 */
I2S_MCLK_MULTIPLE_512 = 512, /*!< mclk = sample_rate * 512 */
} i2s_mclk_multiple_t;
/**
* @brief Event structure used in I2S event queue
*/
typedef struct {
void *data; /**< The pointer of DMA buffer that just finished sending or receiving for `on_recv` and `on_sent` callback
* NULL for `on_recv_q_ovf` and `on_send_q_ovf` callback
*/
size_t size; /**< The buffer size of DMA buffer when success to send or receive,
* also the buffer size that dropped when queue overflow.
* It is related to the dma_frame_num and data_bit_width, typically it is fixed when data_bit_width is not changed.
*/
} i2s_event_data_t;
typedef struct i2s_channel_obj_t *i2s_chan_handle_t; /*!< i2s channel object handle, the control unit of the i2s driver*/
/**
* @brief I2S event callback
* @param[in] handle I2S channel handle, created from `i2s_new_channel()`
* @param[in] event I2S event data
* @param[in] user_ctx User registered context, passed from `i2s_channel_register_event_callback()`
*
* @return Whether a high priority task has been waken up by this callback function
*/
typedef bool (*i2s_isr_callback_t)(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx);
#ifdef __cplusplus
}
#endif
@@ -1,23 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
///< Selecting the ISR to be registered on which core
typedef enum {
INTR_CPU_ID_AUTO, ///< Register intr ISR to core automatically select by FreeRTOS.
INTR_CPU_ID_0, ///< Register intr ISR to core 0.
INTR_CPU_ID_1, ///< Register intr ISR to core 1.
} intr_cpu_id_t;
#define INTR_CPU_CONVERT_ID(cpu_id) ((cpu_id) - 1)
#ifdef __cplusplus
}
#endif
-535
View File
@@ -1,535 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "hal/ledc_types.h"
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_LEDC_SUPPORT_APB_CLOCK
/**
* @brief Frequency of one of the LEDC peripheral clock sources, APB_CLK
* @note This macro should have no use in your application, we keep it here only for backward compatible
*/
#define LEDC_APB_CLK_HZ _Pragma ("GCC warning \"'LEDC_APB_CLK_HZ' macro is deprecated\"") (APB_CLK_FREQ)
#endif
#if SOC_LEDC_SUPPORT_REF_TICK
/**
* @brief Frequency of one of the LEDC peripheral clock sources, REF_TICK
* @note This macro should have no use in your application, we keep it here only for backward compatible
*/
#define LEDC_REF_CLK_HZ _Pragma ("GCC warning \"'LEDC_REF_CLK_HZ' macro is deprecated\"") (REF_CLK_FREQ)
#endif
#define LEDC_ERR_DUTY (0xFFFFFFFF)
#define LEDC_ERR_VAL (-1)
/**
* @brief Configuration parameters of LEDC channel for ledc_channel_config function
*/
typedef struct {
int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */
ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */
ledc_channel_t channel; /*!< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */
ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */
uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
int hpoint; /*!< LEDC channel hpoint value, the max value is 0xfffff */
struct {
unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */
} flags; /*!< LEDC flags */
} ledc_channel_config_t;
/**
* @brief Configuration parameters of LEDC Timer timer for ledc_timer_config function
*/
typedef struct {
ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */
ledc_timer_bit_t duty_resolution; /*!< LEDC channel duty resolution */
ledc_timer_t timer_num; /*!< The timer source of channel (0 - LEDC_TIMER_MAX-1) */
uint32_t freq_hz; /*!< LEDC timer frequency (Hz) */
ledc_clk_cfg_t clk_cfg; /*!< Configure LEDC source clock from ledc_clk_cfg_t.
Note that LEDC_USE_RC_FAST_CLK and LEDC_USE_XTAL_CLK are
non-timer-specific clock sources. You can not have one LEDC timer uses
RC_FAST_CLK as the clock source and have another LEDC timer uses XTAL_CLK
as its clock source. All chips except esp32 and esp32s2 do not have
timer-specific clock sources, which means clock source for all timers
must be the same one. */
} ledc_timer_config_t;
typedef intr_handle_t ledc_isr_handle_t;
/**
* @brief LEDC callback event type
*/
typedef enum {
LEDC_FADE_END_EVT /**< LEDC fade end event */
} ledc_cb_event_t;
/**
* @brief LEDC callback parameter
*/
typedef struct {
ledc_cb_event_t event; /**< Event name */
uint32_t speed_mode; /**< Speed mode of the LEDC channel group */
uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
uint32_t duty; /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution) - 1] */
} ledc_cb_param_t;
/**
* @brief Type of LEDC event callback
* @param param LEDC callback parameter
* @param user_arg User registered data
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*ledc_cb_t)(const ledc_cb_param_t *param, void *user_arg);
/**
* @brief Group of supported LEDC callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
ledc_cb_t fade_cb; /**< LEDC fade_end callback function */
} ledc_cbs_t;
/**
* @brief LEDC channel configuration
* Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC duty resolution
*
* @param ledc_conf Pointer of LEDC channel configure struct
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf);
/**
* @brief LEDC timer configuration
* Configure LEDC timer with the given source timer/frequency(Hz)/duty_resolution
*
* @param timer_conf Pointer of LEDC timer configure struct
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
*/
esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf);
/**
* @brief LEDC update channel parameters
* @note Call this function to activate the LEDC updated parameters.
* After ledc_set_duty, we need to call this function to update the settings.
* And the new LEDC parameters don't take effect until the next PWM cycle.
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*
*/
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief Set LEDC output gpio.
*
* @note This function only routes the LEDC signal to GPIO through matrix, other LEDC resources initialization are not involved.
* Please use `ledc_channel_config()` instead to fully configure a LEDC channel.
*
* @param gpio_num The LEDC output gpio
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param ledc_channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel);
/**
* @brief LEDC stop.
* Disable LEDC output, and set idle level
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param idle_level Set output idle level after LEDC stops.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level);
/**
* @brief LEDC set channel frequency (Hz)
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_num LEDC timer index (0-3), select from ledc_timer_t
* @param freq_hz Set the LEDC frequency
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
*/
esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz);
/**
* @brief LEDC get channel frequency (Hz)
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_num LEDC timer index (0-3), select from ledc_timer_t
*
* @return
* - 0 error
* - Others Current LEDC frequency
*/
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
/**
* @brief LEDC set duty and hpoint value
* Only after calling ledc_update_duty will the duty update.
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
* @param hpoint Set the LEDC hpoint value(max: 0xfffff)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/**
* @brief LEDC get hpoint value, the counter value when the output is set high level.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @return
* - LEDC_ERR_VAL if parameter error
* - Others Current hpoint value of LEDC channel
*/
int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC set duty
* This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint.
* only after calling ledc_update_duty will the duty update.
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);
/**
* @brief LEDC get duty
* This function returns the duty at the present PWM cycle.
* You shouldn't expect the function to return the new duty in the same cycle of calling ledc_update_duty,
* because duty update doesn't take effect until the next cycle.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
*
* @return
* - LEDC_ERR_DUTY if parameter error
* - Others Current LEDC duty
*/
uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC set gradient
* Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1]
* @param fade_direction Set the direction of the gradient
* @param step_num Set the number of the gradient
* @param duty_cycle_num Set how many LEDC tick each time the gradient lasts
* @param duty_scale Set gradient change amplitude
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction,
uint32_t step_num, uint32_t duty_cycle_num, uint32_t duty_scale);
/**
* @brief Register LEDC interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* @param fn Interrupt handler function.
* @param arg User-supplied argument passed to the handler function.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
* be returned here.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
/**
* @brief Configure LEDC settings
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_sel Timer index (0-3), there are 4 timers in LEDC module
* @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
* @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)]
* @param clk_src Select LEDC source clock.
*
* @return
* - (-1) Parameter error
* - Other Current LEDC duty
*/
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src);
/**
* @brief Reset LEDC timer
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* @brief Pause LEDC timer counter
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*
*/
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* @brief Resume LEDC timer
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* @brief Bind LEDC channel with the selected timer
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel);
/**
* @brief Set LEDC fade function.
* @note Call ledc_fade_func_install() once before calling this function.
* Call ledc_fade_start() after this to start fading.
* @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_fade_step_and_start
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. ,
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
* @param scale Controls the increase or decrease step scale.
* @param cycle_num increase or decrease the duty every cycle_num cycles
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_FAIL Fade function init error
*/
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num);
/**
* @brief Set LEDC fade function, with a limited time.
* @note Call ledc_fade_func_install() once before calling this function.
* Call ledc_fade_start() after this to start fading.
* @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_fade_step_and_start
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. ,
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
* @param max_fade_time_ms The maximum time of the fading ( ms ).
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_FAIL Fade function init error
*/
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
/**
* @brief Install LEDC fade function. This function will occupy interrupt of LEDC module.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function already installed.
*/
esp_err_t ledc_fade_func_install(int intr_alloc_flags);
/**
* @brief Uninstall LEDC fade function.
*
*/
void ledc_fade_func_uninstall(void);
/**
* @brief Start LEDC fading.
* @note Call ledc_fade_func_install() once before calling this function.
* Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading.
* @note Starting fade operation with this API is not thread-safe, use with care.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number
* @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
* Note that this function will not return until fading to the target duty if LEDC_FADE_WAIT_DONE mode is selected.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_ERR_INVALID_ARG Parameter error.
*/
esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode);
#if SOC_LEDC_SUPPORT_FADE_STOP
/**
* @brief Stop LEDC fading. Duty of the channel will stay at its present vlaue.
* @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress.
* @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode.
* @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards is no use in stopping the fade. Fade will continue until it reachs the target duty.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_ERR_INVALID_ARG Parameter error.
*/
esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel);
#endif //SOC_LEDC_SUPPORT_FADE_STOP
/**
* @brief A thread-safe API to set duty for LEDC channel and return when duty updated.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
* @param hpoint Set the LEDC hpoint value(max: 0xfffff)
*
*/
esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/**
* @brief A thread-safe API to set and start LEDC fade function, with a limited time.
* @note Call ledc_fade_func_install() once, before calling this function.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
* @param max_fade_time_ms The maximum time of the fading ( ms ).
* @param fade_mode choose blocking or non-blocking mode
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_FAIL Fade function init error
*/
esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode);
/**
* @brief A thread-safe API to set and start LEDC fade function.
* @note Call ledc_fade_func_install() once before calling this function.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1]
* @param scale Controls the increase or decrease step scale.
* @param cycle_num increase or decrease the duty every cycle_num cycles
* @param fade_mode choose blocking or non-blocking mode
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_FAIL Fade function init error
*/
esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode);
/**
* @brief LEDC callback registration function
* @note The callback is called from an ISR, it must never attempt to block, and any FreeRTOS API called must be ISR capable.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param cbs Group of LEDC callback functions
* @param user_arg user registered data for the callback function
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed.
* - ESP_FAIL Fade function init error
*/
esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg);
#ifdef __cplusplus
}
#endif
@@ -1,242 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM capture timer configuration structure
*/
typedef struct {
int group_id; /*!< Specify from which group to allocate the capture timer */
mcpwm_capture_clock_source_t clk_src; /*!< MCPWM capture timer clock source */
} mcpwm_capture_timer_config_t;
/**
* @brief Create MCPWM capture timer
*
* @param[in] config MCPWM capture timer configuration
* @param[out] ret_cap_timer Returned MCPWM capture timer handle
* @return
* - ESP_OK: Create MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM capture timer failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM capture timer failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM capture timer failed because can't find free resource
* - ESP_FAIL: Create MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mcpwm_cap_timer_handle_t *ret_cap_timer);
/**
* @brief Delete MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`
* @return
* - ESP_OK: Delete MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM capture timer failed because of invalid argument
* - ESP_FAIL: Delete MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_del_capture_timer(mcpwm_cap_timer_handle_t cap_timer);
/**
* @brief Enable MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`
* @return
* - ESP_OK: Enable MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Enable MCPWM capture timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable MCPWM capture timer failed because timer is enabled already
* - ESP_FAIL: Enable MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_capture_timer_enable(mcpwm_cap_timer_handle_t cap_timer);
/**
* @brief Disable MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`
* @return
* - ESP_OK: Disable MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Disable MCPWM capture timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable MCPWM capture timer failed because timer is disabled already
* - ESP_FAIL: Disable MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_capture_timer_disable(mcpwm_cap_timer_handle_t cap_timer);
/**
* @brief Start MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`
* @return
* - ESP_OK: Start MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Start MCPWM capture timer failed because of invalid argument
* - ESP_FAIL: Start MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_capture_timer_start(mcpwm_cap_timer_handle_t cap_timer);
/**
* @brief Start MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`
* @return
* - ESP_OK: Stop MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Stop MCPWM capture timer failed because of invalid argument
* - ESP_FAIL: Stop MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_capture_timer_stop(mcpwm_cap_timer_handle_t cap_timer);
/**
* @brief Get MCPWM capture timer resolution, in Hz
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`
* @param[out] out_resolution Returned capture timer resolution, in Hz
* @return
* - ESP_OK: Get capture timer resolution successfully
* - ESP_ERR_INVALID_ARG: Get capture timer resolution failed because of invalid argument
* - ESP_FAIL: Get capture timer resolution failed because of other error
*/
esp_err_t mcpwm_capture_timer_get_resolution(mcpwm_cap_timer_handle_t cap_timer, uint32_t *out_resolution);
/**
* @brief MCPWM Capture timer sync phase configuration
*/
typedef struct {
mcpwm_sync_handle_t sync_src; /*!< The sync event source */
uint32_t count_value; /*!< The count value that should lock to upon sync event */
mcpwm_timer_direction_t direction; /*!< The count direction that should lock to upon sync event */
} mcpwm_capture_timer_sync_phase_config_t;
/**
* @brief Set sync phase for MCPWM capture timer
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`
* @param[in] config MCPWM capture timer sync phase configuration
* @return
* - ESP_OK: Set sync phase for MCPWM capture timer successfully
* - ESP_ERR_INVALID_ARG: Set sync phase for MCPWM capture timer failed because of invalid argument
* - ESP_FAIL: Set sync phase for MCPWM capture timer failed because of other error
*/
esp_err_t mcpwm_capture_timer_set_phase_on_sync(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_timer_sync_phase_config_t *config);
/**
* @brief MCPWM capture channel configuration structure
*/
typedef struct {
int gpio_num; /*!< GPIO used capturing input signal */
uint32_t prescale; /*!< Prescale of input signal, effective frequency = cap_input_clk/prescale */
struct {
uint32_t pos_edge: 1; /*!< Whether to capture on positive edge */
uint32_t neg_edge: 1; /*!< Whether to capture on negative edge */
uint32_t pull_up: 1; /*!< Whether to pull up internally */
uint32_t pull_down: 1; /*!< Whether to pull down internally */
uint32_t invert_cap_signal: 1; /*!< Invert the input capture signal */
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 keep_io_conf_at_exit: 1; /*!< For debug/test, whether to keep the GPIO configuration when capture channel is deleted.
By default, driver will reset the GPIO pin at exit. */
} flags; /*!< Extra configuration flags for capture channel */
} mcpwm_capture_channel_config_t;
/**
* @brief Create MCPWM capture channel
*
* @note The created capture channel won't be enabled until calling `mcpwm_capture_channel_enable`
*
* @param[in] cap_timer MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`, will be connected to the new capture channel
* @param[in] config MCPWM capture channel configuration
* @param[out] ret_cap_channel Returned MCPWM capture channel
* @return
* - ESP_OK: Create MCPWM capture channel successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM capture channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM capture channel failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM capture channel failed because can't find free resource
* - ESP_FAIL: Create MCPWM capture channel failed because of other error
*/
esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_channel_config_t *config, mcpwm_cap_channel_handle_t *ret_cap_channel);
/**
* @brief Delete MCPWM capture channel
*
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
* @return
* - ESP_OK: Delete MCPWM capture channel successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM capture channel failed because of invalid argument
* - ESP_FAIL: Delete MCPWM capture channel failed because of other error
*/
esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel);
/**
* @brief Enable MCPWM capture channel
*
* @note This function will transit the channel state from init to enable.
* @note This function will enable the interrupt service, if it's lazy installed in `mcpwm_capture_channel_register_event_callbacks()`.
*
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
* @return
* - ESP_OK: Enable MCPWM capture channel successfully
* - ESP_ERR_INVALID_ARG: Enable MCPWM capture channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable MCPWM capture channel failed because the channel is already enabled
* - ESP_FAIL: Enable MCPWM capture channel failed because of other error
*/
esp_err_t mcpwm_capture_channel_enable(mcpwm_cap_channel_handle_t cap_channel);
/**
* @brief Disable MCPWM capture channel
*
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
* @return
* - ESP_OK: Disable MCPWM capture channel successfully
* - ESP_ERR_INVALID_ARG: Disable MCPWM capture channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable MCPWM capture channel failed because the channel is not enabled yet
* - ESP_FAIL: Disable MCPWM capture channel failed because of other error
*/
esp_err_t mcpwm_capture_channel_disable(mcpwm_cap_channel_handle_t cap_channel);
/**
* @brief Group of supported MCPWM capture event callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
mcpwm_capture_event_cb_t on_cap; /*!< Callback function that would be invoked when capture event occurred */
} mcpwm_capture_event_callbacks_t;
/**
* @brief Set event callbacks for MCPWM capture channel
*
* @note The first call to this function needs to be before the call to `mcpwm_capture_channel_enable`
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set event callbacks failed because the channel is not in init state
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_callbacks_t *cbs, void *user_data);
/**
* @brief Trigger a catch by software
*
* @param[in] cap_channel MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`
* @return
* - ESP_OK: Trigger software catch successfully
* - ESP_ERR_INVALID_ARG: Trigger software catch failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Trigger software catch failed because the channel is not enabled yet
* - ESP_FAIL: Trigger software catch failed because of other error
*/
esp_err_t mcpwm_capture_channel_trigger_soft_catch(mcpwm_cap_channel_handle_t cap_channel);
#ifdef __cplusplus
}
#endif
@@ -1,93 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM comparator configuration
*/
typedef struct {
struct {
uint32_t update_cmp_on_tez: 1; /*!< Whether to update compare value when timer count equals to zero (tez) */
uint32_t update_cmp_on_tep: 1; /*!< Whether to update compare value when timer count equals to peak (tep) */
uint32_t update_cmp_on_sync: 1; /*!< Whether to update compare value on sync event */
} flags; /*!< Extra configuration flags for comparator */
} mcpwm_comparator_config_t;
/**
* @brief Create MCPWM comparator
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`, the new comparator will be allocated from this operator
* @param[in] config MCPWM comparator configuration
* @param[out] ret_cmpr Returned MCPWM comparator
* @return
* - ESP_OK: Create MCPWM comparator successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM comparator failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM comparator failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM comparator failed because can't find free resource
* - ESP_FAIL: Create MCPWM comparator failed because of other error
*/
esp_err_t mcpwm_new_comparator(mcpwm_oper_handle_t oper, const mcpwm_comparator_config_t *config, mcpwm_cmpr_handle_t *ret_cmpr);
/**
* @brief Delete MCPWM comparator
*
* @param[in] cmpr MCPWM comparator handle, allocated by `mcpwm_new_comparator()`
* @return
* - ESP_OK: Delete MCPWM comparator successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM comparator failed because of invalid argument
* - ESP_FAIL: Delete MCPWM comparator failed because of other error
*/
esp_err_t mcpwm_del_comparator(mcpwm_cmpr_handle_t cmpr);
/**
* @brief Group of supported MCPWM compare event callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
mcpwm_compare_event_cb_t on_reach; /*!< ISR callback function which would be invoked when counter reaches compare value */
} mcpwm_comparator_event_callbacks_t;
/**
* @brief Set event callbacks for MCPWM comparator
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] cmpr MCPWM comparator handle, allocated by `mcpwm_new_comparator()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t mcpwm_comparator_register_event_callbacks(mcpwm_cmpr_handle_t cmpr, const mcpwm_comparator_event_callbacks_t *cbs, void *user_data);
/**
* @brief Set MCPWM comparator's compare value
*
* @param[in] cmpr MCPWM comparator handle, allocated by `mcpwm_new_comparator()`
* @param[in] cmp_ticks The new compare value
* @return
* - ESP_OK: Set MCPWM compare value successfully
* - ESP_ERR_INVALID_ARG: Set MCPWM compare value failed because of invalid argument (e.g. the cmp_ticks is out of range)
* - ESP_ERR_INVALID_STATE: Set MCPWM compare value failed because the operator doesn't have a timer connected
* - ESP_FAIL: Set MCPWM compare value failed because of other error
*/
esp_err_t mcpwm_comparator_set_compare_value(mcpwm_cmpr_handle_t cmpr, uint32_t cmp_ticks);
#ifdef __cplusplus
}
#endif
@@ -1,114 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM GPIO fault configuration structure
*/
typedef struct {
int group_id; /*!< In which MCPWM group that the GPIO fault belongs to */
int gpio_num; /*!< GPIO used by the fault signal */
struct {
uint32_t active_level: 1; /*!< On which level the fault signal is treated as active */
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 pull_up: 1; /*!< Whether to pull up internally */
uint32_t pull_down: 1; /*!< Whether to pull down internally */
} flags; /*!< Extra configuration flags for GPIO fault */
} mcpwm_gpio_fault_config_t;
/**
* @brief Create MCPWM GPIO fault
*
* @param[in] config MCPWM GPIO fault configuration
* @param[out] ret_fault Returned GPIO fault handle
* @return
* - ESP_OK: Create MCPWM GPIO fault successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM GPIO fault failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM GPIO fault failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM GPIO fault failed because can't find free resource
* - ESP_FAIL: Create MCPWM GPIO fault failed because of other error
*/
esp_err_t mcpwm_new_gpio_fault(const mcpwm_gpio_fault_config_t *config, mcpwm_fault_handle_t *ret_fault);
/**
* @brief MCPWM software fault configuration structure
*/
typedef struct {
} mcpwm_soft_fault_config_t;
/**
* @brief Create MCPWM software fault
*
* @param[in] config MCPWM software fault configuration
* @param[out] ret_fault Returned software fault handle
* @return
* - ESP_OK: Create MCPWM software fault successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM software fault failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM software fault failed because out of memory
* - ESP_FAIL: Create MCPWM software fault failed because of other error
*/
esp_err_t mcpwm_new_soft_fault(const mcpwm_soft_fault_config_t *config, mcpwm_fault_handle_t *ret_fault);
/**
* @brief Delete MCPWM fault
*
* @param[in] fault MCPWM fault handle allocated by `mcpwm_new_gpio_fault()` or `mcpwm_new_soft_fault()`
* @return
* - ESP_OK: Delete MCPWM fault successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM fault failed because of invalid argument
* - ESP_FAIL: Delete MCPWM fault failed because of other error
*/
esp_err_t mcpwm_del_fault(mcpwm_fault_handle_t fault);
/**
* @brief Activate the software fault, trigger the fault event for once
*
* @param[in] fault MCPWM soft fault, allocated by `mcpwm_new_soft_fault()`
* @return
* - ESP_OK: Trigger MCPWM software fault event successfully
* - ESP_ERR_INVALID_ARG: Trigger MCPWM software fault event failed because of invalid argument
* - ESP_FAIL: Trigger MCPWM software fault event failed because of other error
*/
esp_err_t mcpwm_soft_fault_activate(mcpwm_fault_handle_t fault);
/**
* @brief Group of supported MCPWM fault event callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
mcpwm_fault_event_cb_t on_fault_enter; /*!< ISR callback function that would be invoked when fault signal becomes active */
mcpwm_fault_event_cb_t on_fault_exit; /*!< ISR callback function that would be invoked when fault signal becomes inactive */
} mcpwm_fault_event_callbacks_t;
/**
* @brief Set event callbacks for MCPWM fault
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] fault MCPWM GPIO fault handle, allocated by `mcpwm_new_gpio_fault()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t mcpwm_fault_register_event_callbacks(mcpwm_fault_handle_t fault, const mcpwm_fault_event_callbacks_t *cbs, void *user_data);
#ifdef __cplusplus
}
#endif
@@ -1,230 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM generator configuration
*/
typedef struct {
int gen_gpio_num; /*!< The GPIO number used to output the PWM signal */
struct {
uint32_t invert_pwm: 1; /*!< Whether to invert the PWM signal (done by GPIO matrix) */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
} flags; /*!< Extra configuration flags for generator */
} mcpwm_generator_config_t;
/**
* @brief Allocate MCPWM generator from given operator
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`
* @param[in] config MCPWM generator configuration
* @param[out] ret_gen Returned MCPWM generator
* @return
* - ESP_OK: Create MCPWM generator successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM generator failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM generator failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM generator failed because can't find free resource
* - ESP_FAIL: Create MCPWM generator failed because of other error
*/
esp_err_t mcpwm_new_generator(mcpwm_oper_handle_t oper, const mcpwm_generator_config_t *config, mcpwm_gen_handle_t *ret_gen);
/**
* @brief Delete MCPWM generator
*
* @param[in] gen MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @return
* - ESP_OK: Delete MCPWM generator successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM generator failed because of invalid argument
* - ESP_FAIL: Delete MCPWM generator failed because of other error
*/
esp_err_t mcpwm_del_generator(mcpwm_gen_handle_t gen);
/**
* @brief Set force level for MCPWM generator
*
* @note The force level will be applied to the generator immediately, regardless any other events that would change the generator's behaviour.
* @note If the `hold_on` is true, the force level will retain forever, until user removes the force level by setting the force level to `-1`.
* @note If the `hold_on` is false, the force level can be overridden by the next event action.
*
* @param[in] gen MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] level GPIO level to be applied to MCPWM generator, specially, -1 means to remove the force level
* @param[in] hold_on Whether the forced PWM level should retain (i.e. will remain unchanged until manually remove the force level)
* @return
* - ESP_OK: Set force level for MCPWM generator successfully
* - ESP_ERR_INVALID_ARG: Set force level for MCPWM generator failed because of invalid argument
* - ESP_FAIL: Set force level for MCPWM generator failed because of other error
*/
esp_err_t mcpwm_generator_set_force_level(mcpwm_gen_handle_t gen, int level, bool hold_on);
/**
* @brief Generator action on specific timer event
*/
typedef struct {
mcpwm_timer_direction_t direction; /*!< Timer direction */
mcpwm_timer_event_t event; /*!< Timer event */
mcpwm_generator_action_t action; /*!< Generator action should perform */
} mcpwm_gen_timer_event_action_t;
/**
* @brief Help macros to construct a mcpwm_gen_timer_event_action_t entry
*/
#define MCPWM_GEN_TIMER_EVENT_ACTION(dir, ev, act) \
(mcpwm_gen_timer_event_action_t) { .direction = dir, .event = ev, .action = act }
#define MCPWM_GEN_TIMER_EVENT_ACTION_END() \
(mcpwm_gen_timer_event_action_t) { .event = MCPWM_TIMER_EVENT_INVALID }
/**
* @brief Set generator action on MCPWM timer event
*
* @param[in] gen MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM timer event action, can be constructed by `MCPWM_GEN_TIMER_EVENT_ACTION` helper macro
* @return
* - ESP_OK: Set generator action successfully
* - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set generator action failed because of timer is not connected to operator
* - ESP_FAIL: Set generator action failed because of other error
*/
esp_err_t mcpwm_generator_set_action_on_timer_event(mcpwm_gen_handle_t gen, mcpwm_gen_timer_event_action_t ev_act);
/**
* @brief Set generator actions on multiple MCPWM timer events
*
* @note This is an aggregation version of `mcpwm_generator_set_action_on_timer_event`, which allows user to set multiple actions in one call.
*
* @param[in] gen MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM timer event action list, must be terminated by `MCPWM_GEN_TIMER_EVENT_ACTION_END()`
* @return
* - ESP_OK: Set generator actions successfully
* - ESP_ERR_INVALID_ARG: Set generator actions failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set generator actions failed because of timer is not connected to operator
* - ESP_FAIL: Set generator actions failed because of other error
*/
esp_err_t mcpwm_generator_set_actions_on_timer_event(mcpwm_gen_handle_t gen, mcpwm_gen_timer_event_action_t ev_act, ...);
/**
* @brief Generator action on specific comparator event
*/
typedef struct {
mcpwm_timer_direction_t direction; /*!< Timer direction */
mcpwm_cmpr_handle_t comparator; /*!< Comparator handle */
mcpwm_generator_action_t action; /*!< Generator action should perform */
} mcpwm_gen_compare_event_action_t;
/**
* @brief Help macros to construct a mcpwm_gen_compare_event_action_t entry
*/
#define MCPWM_GEN_COMPARE_EVENT_ACTION(dir, cmp, act) \
(mcpwm_gen_compare_event_action_t) { .direction = dir, .comparator = cmp, .action = act }
#define MCPWM_GEN_COMPARE_EVENT_ACTION_END() \
(mcpwm_gen_compare_event_action_t) { .comparator = NULL }
/**
* @brief Set generator action on MCPWM compare event
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM compare event action, can be constructed by `MCPWM_GEN_COMPARE_EVENT_ACTION` helper macro
* @return
* - ESP_OK: Set generator action successfully
* - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument
* - ESP_FAIL: Set generator action failed because of other error
*/
esp_err_t mcpwm_generator_set_action_on_compare_event(mcpwm_gen_handle_t generator, mcpwm_gen_compare_event_action_t ev_act);
/**
* @brief Set generator actions on multiple MCPWM compare events
*
* @note This is an aggregation version of `mcpwm_generator_set_action_on_compare_event`, which allows user to set multiple actions in one call.
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM compare event action list, must be terminated by `MCPWM_GEN_COMPARE_EVENT_ACTION_END()`
* @return
* - ESP_OK: Set generator actions successfully
* - ESP_ERR_INVALID_ARG: Set generator actions failed because of invalid argument
* - ESP_FAIL: Set generator actions failed because of other error
*/
esp_err_t mcpwm_generator_set_actions_on_compare_event(mcpwm_gen_handle_t generator, mcpwm_gen_compare_event_action_t ev_act, ...);
/**
* @brief Generator action on specific brake event
*/
typedef struct {
mcpwm_timer_direction_t direction; /*!< Timer direction */
mcpwm_operator_brake_mode_t brake_mode; /*!< Brake mode */
mcpwm_generator_action_t action; /*!< Generator action should perform */
} mcpwm_gen_brake_event_action_t;
/**
* @brief Help macros to construct a mcpwm_gen_brake_event_action_t entry
*/
#define MCPWM_GEN_BRAKE_EVENT_ACTION(dir, mode, act) \
(mcpwm_gen_brake_event_action_t) { .direction = dir, .brake_mode = mode, .action = act }
#define MCPWM_GEN_BRAKE_EVENT_ACTION_END() \
(mcpwm_gen_brake_event_action_t) { .brake_mode = MCPWM_OPER_BRAKE_MODE_INVALID }
/**
* @brief Set generator action on MCPWM brake event
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM brake event action, can be constructed by `MCPWM_GEN_BRAKE_EVENT_ACTION` helper macro
* @return
* - ESP_OK: Set generator action successfully
* - ESP_ERR_INVALID_ARG: Set generator action failed because of invalid argument
* - ESP_FAIL: Set generator action failed because of other error
*/
esp_err_t mcpwm_generator_set_action_on_brake_event(mcpwm_gen_handle_t generator, mcpwm_gen_brake_event_action_t ev_act);
/**
* @brief Set generator actions on multiple MCPWM brake events
*
* @note This is an aggregation version of `mcpwm_generator_set_action_on_brake_event`, which allows user to set multiple actions in one call.
*
* @param[in] generator MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] ev_act MCPWM brake event action list, must be terminated by `MCPWM_GEN_BRAKE_EVENT_ACTION_END()`
* @return
* - ESP_OK: Set generator actions successfully
* - ESP_ERR_INVALID_ARG: Set generator actions failed because of invalid argument
* - ESP_FAIL: Set generator actions failed because of other error
*/
esp_err_t mcpwm_generator_set_actions_on_brake_event(mcpwm_gen_handle_t generator, mcpwm_gen_brake_event_action_t ev_act, ...);
/**
* @brief MCPWM dead time configuration structure
*/
typedef struct {
uint32_t posedge_delay_ticks; /*!< delay time applied to rising edge, 0 means no rising delay time */
uint32_t negedge_delay_ticks; /*!< delay time applied to falling edge, 0 means no falling delay time */
struct {
uint32_t invert_output: 1; /*!< Invert the signal after applied the dead time */
} flags; /*!< Extra flags for dead time configuration */
} mcpwm_dead_time_config_t;
/**
* @brief Set dead time for MCPWM generator
*
* @param[in] in_generator MCPWM generator, before adding the dead time
* @param[in] out_generator MCPWM generator, after adding the dead time
* @param[in] config MCPWM dead time configuration
* @return
* - ESP_OK: Set dead time for MCPWM generator successfully
* - ESP_ERR_INVALID_ARG: Set dead time for MCPWM generator failed because of invalid argument
* - ESP_FAIL: Set dead time for MCPWM generator failed because of other error
*/
esp_err_t mcpwm_generator_set_dead_time(mcpwm_gen_handle_t in_generator, mcpwm_gen_handle_t out_generator, const mcpwm_dead_time_config_t *config);
#ifdef __cplusplus
}
#endif
@@ -1,161 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM operator configuration
*/
typedef struct {
int group_id; /*!< Specify from which group to allocate the MCPWM operator */
struct {
uint32_t update_gen_action_on_tez: 1; /*!< Whether to update generator action when timer counts to zero */
uint32_t update_gen_action_on_tep: 1; /*!< Whether to update generator action when timer counts to peak */
uint32_t update_gen_action_on_sync: 1; /*!< Whether to update generator action on sync event */
uint32_t update_dead_time_on_tez: 1; /*!< Whether to update dead time when timer counts to zero */
uint32_t update_dead_time_on_tep: 1; /*!< Whether to update dead time when timer counts to peak */
uint32_t update_dead_time_on_sync: 1; /*!< Whether to update dead time on sync event */
} flags; /*!< Extra configuration flags for operator */
} mcpwm_operator_config_t;
/**
* @brief Create MCPWM operator
*
* @param[in] config MCPWM operator configuration
* @param[out] ret_oper Returned MCPWM operator handle
* @return
* - ESP_OK: Create MCPWM operator successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM operator failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM operator failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM operator failed because can't find free resource
* - ESP_FAIL: Create MCPWM operator failed because of other error
*/
esp_err_t mcpwm_new_operator(const mcpwm_operator_config_t *config, mcpwm_oper_handle_t *ret_oper);
/**
* @brief Delete MCPWM operator
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`
* @return
* - ESP_OK: Delete MCPWM operator successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM operator failed because of invalid argument
* - ESP_FAIL: Delete MCPWM operator failed because of other error
*/
esp_err_t mcpwm_del_operator(mcpwm_oper_handle_t oper);
/**
* @brief Connect MCPWM operator and timer, so that the operator can be driven by the timer
*
* @param[in] oper MCPWM operator handle, allocated by `mcpwm_new_operator()`
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @return
* - ESP_OK: Connect MCPWM operator and timer successfully
* - ESP_ERR_INVALID_ARG: Connect MCPWM operator and timer failed because of invalid argument
* - ESP_FAIL: Connect MCPWM operator and timer failed because of other error
*/
esp_err_t mcpwm_operator_connect_timer(mcpwm_oper_handle_t oper, mcpwm_timer_handle_t timer);
/**
* @brief MCPWM brake configuration structure
*/
typedef struct {
mcpwm_fault_handle_t fault; /*!< Which fault causes the operator to brake */
mcpwm_operator_brake_mode_t brake_mode; /*!< Brake mode */
struct {
uint32_t cbc_recover_on_tez: 1; /*!< Recovery CBC brake state on tez event */
uint32_t cbc_recover_on_tep: 1; /*!< Recovery CBC brake state on tep event */
} flags; /*!< Extra flags for brake configuration */
} mcpwm_brake_config_t;
/**
* @brief Set brake method for MCPWM operator
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`
* @param[in] config MCPWM brake configuration
* @return
* - ESP_OK: Set trip for operator successfully
* - ESP_ERR_INVALID_ARG: Set trip for operator failed because of invalid argument
* - ESP_FAIL: Set trip for operator failed because of other error
*/
esp_err_t mcpwm_operator_set_brake_on_fault(mcpwm_oper_handle_t oper, const mcpwm_brake_config_t *config);
/**
* @brief Try to make the operator recover from fault
*
* @note To recover from fault or escape from trip, you make sure the fault signal has dissappeared already.
* Otherwise the recovery can't succeed.
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`
* @param[in] fault MCPWM fault handle
* @return
* - ESP_OK: Recover from fault successfully
* - ESP_ERR_INVALID_ARG: Recover from fault failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Recover from fault failed because the fault source is still active
* - ESP_FAIL: Recover from fault failed because of other error
*/
esp_err_t mcpwm_operator_recover_from_fault(mcpwm_oper_handle_t oper, mcpwm_fault_handle_t fault);
/**
* @brief Group of supported MCPWM operator event callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
mcpwm_brake_event_cb_t on_brake_cbc; /*!< callback function when mcpwm operator brakes in CBC */
mcpwm_brake_event_cb_t on_brake_ost; /*!< callback function when mcpwm operator brakes in OST */
} mcpwm_operator_event_callbacks_t;
/**
* @brief Set event callbacks for MCPWM operator
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] oper MCPWM operator handle, allocated by `mcpwm_new_operator()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t mcpwm_operator_register_event_callbacks(mcpwm_oper_handle_t oper, const mcpwm_operator_event_callbacks_t *cbs, void *user_data);
/**
* @brief MCPWM carrier configuration structure
*/
typedef struct {
uint32_t frequency_hz; /*!< Carrier frequency in Hz */
uint32_t first_pulse_duration_us; /*!< The duration of the first PWM pulse, in us */
float duty_cycle; /*!< Carrier duty cycle */
struct {
uint32_t invert_before_modulate: 1; /*!< Invert the raw signal */
uint32_t invert_after_modulate: 1; /*!< Invert the modulated signal */
} flags; /*!< Extra flags for carrier configuration */
} mcpwm_carrier_config_t;
/**
* @brief Apply carrier feature for MCPWM operator
*
* @param[in] oper MCPWM operator, allocated by `mcpwm_new_operator()`
* @param[in] config MCPWM carrier specific configuration
* @return
* - ESP_OK: Set carrier for operator successfully
* - ESP_ERR_INVALID_ARG: Set carrier for operator failed because of invalid argument
* - ESP_FAIL: Set carrier for operator failed because of other error
*/
esp_err_t mcpwm_operator_apply_carrier(mcpwm_oper_handle_t oper, const mcpwm_carrier_config_t *config);
#ifdef __cplusplus
}
#endif
@@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief MCPWM peripheral contains many submodules, whose drivers are scattered in different header files.
* This header file serves as a prelude, contains every thing that is needed to work with the MCPWM peripheral.
*/
#pragma once
#include "driver/mcpwm_timer.h"
#include "driver/mcpwm_oper.h"
#include "driver/mcpwm_cmpr.h"
#include "driver/mcpwm_gen.h"
#include "driver/mcpwm_fault.h"
#include "driver/mcpwm_sync.h"
#include "driver/mcpwm_cap.h"
@@ -1,114 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MCPWM timer sync source configuration
*/
typedef struct {
mcpwm_timer_event_t timer_event; /*!< Timer event, upon which MCPWM timer will generate the sync signal */
struct {
uint32_t propagate_input_sync: 1; /*!< The input sync signal would be routed to its sync output */
} flags; /*!< Extra configuration flags for timer sync source */
} mcpwm_timer_sync_src_config_t;
/**
* @brief Create MCPWM timer sync source
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @param[in] config MCPWM timer sync source configuration
* @param[out] ret_sync Returned MCPWM sync handle
* @return
* - ESP_OK: Create MCPWM timer sync source successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM timer sync source failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM timer sync source failed because out of memory
* - ESP_ERR_INVALID_STATE: Create MCPWM timer sync source failed because the timer has created a sync source before
* - ESP_FAIL: Create MCPWM timer sync source failed because of other error
*/
esp_err_t mcpwm_new_timer_sync_src(mcpwm_timer_handle_t timer, const mcpwm_timer_sync_src_config_t *config, mcpwm_sync_handle_t *ret_sync);
/**
* @brief MCPWM GPIO sync source configuration
*/
typedef struct {
int group_id; /*!< MCPWM group ID */
int gpio_num; /*!< GPIO used by sync source */
struct {
uint32_t active_neg: 1; /*!< Whether the sync signal is active on negedge, by default, the sync signal's posedge is treated as active */
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 pull_up: 1; /*!< Whether to pull up internally */
uint32_t pull_down: 1; /*!< Whether to pull down internally */
} flags; /*!< Extra configuration flags for GPIO sync source */
} mcpwm_gpio_sync_src_config_t;
/**
* @brief Create MCPWM GPIO sync source
*
* @param[in] config MCPWM GPIO sync source configuration
* @param[out] ret_sync Returned MCPWM GPIO sync handle
* @return
* - ESP_OK: Create MCPWM GPIO sync source successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM GPIO sync source failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM GPIO sync source failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM GPIO sync source failed because can't find free resource
* - ESP_FAIL: Create MCPWM GPIO sync source failed because of other error
*/
esp_err_t mcpwm_new_gpio_sync_src(const mcpwm_gpio_sync_src_config_t *config, mcpwm_sync_handle_t *ret_sync);
/**
* @brief MCPWM software sync configuration structure
*/
typedef struct {
} mcpwm_soft_sync_config_t;
/**
* @brief Create MCPWM software sync source
*
* @param[in] config MCPWM software sync source configuration
* @param[out] ret_sync Returned software sync handle
* @return
* - ESP_OK: Create MCPWM software sync successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM software sync failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM software sync failed because out of memory
* - ESP_FAIL: Create MCPWM software sync failed because of other error
*/
esp_err_t mcpwm_new_soft_sync_src(const mcpwm_soft_sync_config_t *config, mcpwm_sync_handle_t *ret_sync);
/**
* @brief Delete MCPWM sync source
*
* @param[in] sync MCPWM sync handle, allocated by `mcpwm_new_timer_sync_src()` or `mcpwm_new_gpio_sync_src()` or `mcpwm_new_soft_sync_src()`
* @return
* - ESP_OK: Delete MCPWM sync source successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM sync source failed because of invalid argument
* - ESP_FAIL: Delete MCPWM sync source failed because of other error
*/
esp_err_t mcpwm_del_sync_src(mcpwm_sync_handle_t sync);
/**
* @brief Activate the software sync, trigger the sync event for once
*
* @param[in] sync MCPWM soft sync handle, allocated by `mcpwm_new_soft_sync_src()`
* @return
* - ESP_OK: Trigger MCPWM software sync event successfully
* - ESP_ERR_INVALID_ARG: Trigger MCPWM software sync event failed because of invalid argument
* - ESP_FAIL: Trigger MCPWM software sync event failed because of other error
*/
esp_err_t mcpwm_soft_sync_activate(mcpwm_sync_handle_t sync);
#ifdef __cplusplus
}
#endif
@@ -1,147 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Group of supported MCPWM timer event callbacks
* @note The callbacks are all running under ISR environment
*/
typedef struct {
mcpwm_timer_event_cb_t on_full; /*!< callback function when MCPWM timer counts to peak value */
mcpwm_timer_event_cb_t on_empty; /*!< callback function when MCPWM timer counts to zero */
mcpwm_timer_event_cb_t on_stop; /*!< callback function when MCPWM timer stops */
} mcpwm_timer_event_callbacks_t;
/**
* @brief MCPWM timer configuration
*/
typedef struct {
int group_id; /*!< Specify from which group to allocate the MCPWM timer */
mcpwm_timer_clock_source_t clk_src; /*!< MCPWM timer clock source */
uint32_t resolution_hz; /*!< Counter resolution in Hz, ranges from around 300KHz to 80MHz.
The step size of each count tick equals to (1 / resolution_hz) seconds */
mcpwm_timer_count_mode_t count_mode; /*!< Count mode */
uint32_t period_ticks; /*!< Number of count ticks within a period */
struct {
uint32_t update_period_on_empty: 1; /*!< Whether to update period when timer counts to zero */
uint32_t update_period_on_sync: 1; /*!< Whether to update period on sync event */
} flags; /*!< Extra configuration flags for timer */
} mcpwm_timer_config_t;
/**
* @brief Create MCPWM timer
*
* @param[in] config MCPWM timer configuration
* @param[out] ret_timer Returned MCPWM timer handle
* @return
* - ESP_OK: Create MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Create MCPWM timer failed because of invalid argument
* - ESP_ERR_NO_MEM: Create MCPWM timer failed because out of memory
* - ESP_ERR_NOT_FOUND: Create MCPWM timer failed because all hardware timers are used up and no more free one
* - ESP_FAIL: Create MCPWM timer failed because of other error
*/
esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle_t *ret_timer);
/**
* @brief Delete MCPWM timer
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @return
* - ESP_OK: Delete MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Delete MCPWM timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete MCPWM timer failed because timer is not in init state
* - ESP_FAIL: Delete MCPWM timer failed because of other error
*/
esp_err_t mcpwm_del_timer(mcpwm_timer_handle_t timer);
/**
* @brief Enable MCPWM timer
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @return
* - ESP_OK: Enable MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Enable MCPWM timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable MCPWM timer failed because timer is enabled already
* - ESP_FAIL: Enable MCPWM timer failed because of other error
*/
esp_err_t mcpwm_timer_enable(mcpwm_timer_handle_t timer);
/**
* @brief Disable MCPWM timer
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @return
* - ESP_OK: Disable MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Disable MCPWM timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable MCPWM timer failed because timer is disabled already
* - ESP_FAIL: Disable MCPWM timer failed because of other error
*/
esp_err_t mcpwm_timer_disable(mcpwm_timer_handle_t timer);
/**
* @brief Send specific start/stop commands to MCPWM timer
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @param[in] command Supported command list for MCPWM timer
* @return
* - ESP_OK: Start or stop MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Start or stop MCPWM timer failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Start or stop MCPWM timer failed because timer is not enabled
* - ESP_FAIL: Start or stop MCPWM timer failed because of other error
*/
esp_err_t mcpwm_timer_start_stop(mcpwm_timer_handle_t timer, mcpwm_timer_start_stop_cmd_t command);
/**
* @brief Set event callbacks for MCPWM timer
*
* @note The first call to this function needs to be before the call to `mcpwm_timer_enable`
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set event callbacks failed because timer is not in init state
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t mcpwm_timer_register_event_callbacks(mcpwm_timer_handle_t timer, const mcpwm_timer_event_callbacks_t *cbs, void *user_data);
/**
* @brief MCPWM Timer sync phase configuration
*/
typedef struct {
mcpwm_sync_handle_t sync_src; /*!< The sync event source. Set to NULL will disable the timer being synced by others */
uint32_t count_value; /*!< The count value that should lock to upon sync event */
mcpwm_timer_direction_t direction; /*!< The count direction that should lock to upon sync event */
} mcpwm_timer_sync_phase_config_t;
/**
* @brief Set sync phase for MCPWM timer
*
* @param[in] timer MCPWM timer handle, allocated by `mcpwm_new_timer()`
* @param[in] config MCPWM timer sync phase configuration
* @return
* - ESP_OK: Set sync phase for MCPWM timer successfully
* - ESP_ERR_INVALID_ARG: Set sync phase for MCPWM timer failed because of invalid argument
* - ESP_FAIL: Set sync phase for MCPWM timer failed because of other error
*/
esp_err_t mcpwm_timer_set_phase_on_sync(mcpwm_timer_handle_t timer, const mcpwm_timer_sync_phase_config_t *config);
#ifdef __cplusplus
}
#endif
@@ -1,145 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "hal/mcpwm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of MCPWM timer handle
*/
typedef struct mcpwm_timer_t *mcpwm_timer_handle_t;
/**
* @brief Type of MCPWM operator handle
*/
typedef struct mcpwm_oper_t *mcpwm_oper_handle_t;
/**
* @brief Type of MCPWM comparator handle
*/
typedef struct mcpwm_cmpr_t *mcpwm_cmpr_handle_t;
/**
* @brief Type of MCPWM generator handle
*/
typedef struct mcpwm_gen_t *mcpwm_gen_handle_t;
/**
* @brief Type of MCPWM fault handle
*/
typedef struct mcpwm_fault_t *mcpwm_fault_handle_t;
/**
* @brief Type of MCPWM sync handle
*/
typedef struct mcpwm_sync_t *mcpwm_sync_handle_t;
/**
* @brief Type of MCPWM capture timer handle
*/
typedef struct mcpwm_cap_timer_t *mcpwm_cap_timer_handle_t;
/**
* @brief Type of MCPWM capture channel handle
*/
typedef struct mcpwm_cap_channel_t *mcpwm_cap_channel_handle_t;
/**
* @brief MCPWM timer event data
*/
typedef struct {
uint32_t count_value; /*!< MCPWM timer count value */
mcpwm_timer_direction_t direction; /*!< MCPWM timer count direction */
} mcpwm_timer_event_data_t;
/**
* @brief MCPWM timer event callback function
*
* @param[in] timer MCPWM timer handle
* @param[in] edata MCPWM timer event data, fed by driver
* @param[in] user_ctx User data, set in `mcpwm_timer_register_event_callbacks()`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*mcpwm_timer_event_cb_t)(mcpwm_timer_handle_t timer, const mcpwm_timer_event_data_t *edata, void *user_ctx);
/**
* @brief MCPWM brake event data
*/
typedef struct {
} mcpwm_brake_event_data_t;
/**
* @brief MCPWM operator brake event callback function
*
* @param[in] oper MCPWM operator handle
* @param[in] edata MCPWM brake event data, fed by driver
* @param[in] user_ctx User data, set in `mcpwm_operator_register_event_callbacks()`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*mcpwm_brake_event_cb_t)(mcpwm_oper_handle_t oper, const mcpwm_brake_event_data_t *edata, void *user_ctx);
/**
* @brief MCPWM fault event data
*/
typedef struct {
} mcpwm_fault_event_data_t;
/**
* @brief MCPWM fault event callback function
*
* @param fault MCPWM fault handle
* @param edata MCPWM fault event data, fed by driver
* @param user_ctx User data, set in `mcpwm_fault_register_event_callbacks()`
* @return whether a task switch is needed after the callback returns
*/
typedef bool (*mcpwm_fault_event_cb_t)(mcpwm_fault_handle_t fault, const mcpwm_fault_event_data_t *edata, void *user_ctx);
/**
* @brief MCPWM compare event data
*/
typedef struct {
uint32_t compare_ticks; /*!< Compare value */
mcpwm_timer_direction_t direction; /*!< Count direction */
} mcpwm_compare_event_data_t;
/**
* @brief MCPWM comparator event callback function
*
* @param comparator MCPWM comparator handle
* @param edata MCPWM comparator event data, fed by driver
* @param user_ctx User data, set in `mcpwm_comparator_register_event_callbacks()`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*mcpwm_compare_event_cb_t)(mcpwm_cmpr_handle_t comparator, const mcpwm_compare_event_data_t *edata, void *user_ctx);
/**
* @brief MCPWM capture event data
*/
typedef struct {
uint32_t cap_value; /*!< Captured value */
mcpwm_capture_edge_t cap_edge; /*!< Capture edge */
} mcpwm_capture_event_data_t;
/**
* @brief MCPWM capture event callback function
*
* @param cap_channel MCPWM capture channel handle
* @param edata MCPWM capture event data, fed by driver
* @param user_ctx User data, set in `mcpwm_capture_channel_register_event_callbacks()`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*mcpwm_capture_event_cb_t)(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_ctx);
#ifdef __cplusplus
}
#endif
@@ -1,341 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "hal/pcnt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of PCNT unit handle
*/
typedef struct pcnt_unit_t *pcnt_unit_handle_t;
/**
* @brief Type of PCNT channel handle
*/
typedef struct pcnt_chan_t *pcnt_channel_handle_t;
/**
* @brief PCNT watch event data
*/
typedef struct {
int watch_point_value; /*!< Watch point value that triggered the event */
pcnt_unit_zero_cross_mode_t zero_cross_mode; /*!< Zero cross mode */
} pcnt_watch_event_data_t;
/**
* @brief PCNT watch event callback prototype
*
* @note The callback function is invoked from an ISR context, so it should meet the restrictions of not calling any blocking APIs when implementing the callback.
* e.g. must use ISR version of FreeRTOS APIs.
*
* @param[in] unit PCNT unit handle
* @param[in] edata PCNT event data, fed by the driver
* @param[in] user_ctx User data, passed from `pcnt_unit_register_event_callbacks()`
* @return Whether a high priority task has been woken up by this function
*/
typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx);
/**
* @brief Group of supported PCNT callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_PCNT_ISR_IRAM_SAFE is enabled, the callback itself and functions callbed by it should be placed in IRAM.
*/
typedef struct {
pcnt_watch_cb_t on_reach; /*!< Called when PCNT unit counter reaches any watch point */
} pcnt_event_callbacks_t;
/**
* @brief PCNT unit configuration
*/
typedef struct {
int low_limit; /*!< Low limitation of the count unit, should be lower than 0 */
int high_limit; /*!< High limitation of the count unit, should be higher than 0 */
struct {
uint32_t accum_count: 1; /*!< Whether to accumulate the count value when overflows at the high/low limit */
} flags; /*!< Extra flags */
} pcnt_unit_config_t;
/**
* @brief PCNT channel configuration
*/
typedef struct {
int edge_gpio_num; /*!< GPIO number used by the edge signal, input mode with pull up enabled. Set to -1 if unused */
int level_gpio_num; /*!< GPIO number used by the level signal, input mode with pull up enabled. Set to -1 if unused */
struct {
uint32_t invert_edge_input: 1; /*!< Invert the input edge signal */
uint32_t invert_level_input: 1; /*!< Invert the input level signal */
uint32_t virt_edge_io_level: 1; /*!< Virtual edge IO level, 0: low, 1: high. Only valid when edge_gpio_num is set to -1 */
uint32_t virt_level_io_level: 1; /*!< Virtual level IO level, 0: low, 1: high. Only valid when level_gpio_num is set to -1 */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
} flags; /*!< Channel config flags */
} pcnt_chan_config_t;
/**
* @brief PCNT glitch filter configuration
*/
typedef struct {
uint32_t max_glitch_ns; /*!< Pulse width smaller than this threshold will be treated as glitch and ignored, in the unit of ns */
} pcnt_glitch_filter_config_t;
/**
* @brief Create a new PCNT unit, and return the handle
*
* @note The newly created PCNT unit is put in the init state.
*
* @param[in] config PCNT unit configuration
* @param[out] ret_unit Returned PCNT unit handle
* @return
* - ESP_OK: Create PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Create PCNT unit failed because of invalid argument (e.g. high/low limit value out of the range)
* - ESP_ERR_NO_MEM: Create PCNT unit failed because out of memory
* - ESP_ERR_NOT_FOUND: Create PCNT unit failed because all PCNT units are used up and no more free one
* - ESP_FAIL: Create PCNT unit failed because of other error
*/
esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *ret_unit);
/**
* @brief Delete the PCNT unit handle
*
* @note A PCNT unit can't be in the enable state when this function is invoked.
* See also `pcnt_unit_disable()` for how to disable a unit.
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Delete the PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Delete the PCNT unit failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete the PCNT unit failed because the unit is not in init state or some PCNT channel is still in working
* - ESP_FAIL: Delete the PCNT unit failed because of other error
*/
esp_err_t pcnt_del_unit(pcnt_unit_handle_t unit);
/**
* @brief Set glitch filter for PCNT unit
*
* @note The glitch filter module is clocked from APB, and APB frequency can be changed during DFS, which in return make the filter out of action.
* So this function will lazy-install a PM lock internally when the power management is enabled. With this lock, the APB frequency won't be changed.
* The PM lock can be uninstalled in `pcnt_del_unit()`.
* @note This function should be called when the PCNT unit is in the init state (i.e. before calling `pcnt_unit_enable()`)
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[in] config PCNT filter configuration, set config to NULL means disabling the filter function
* @return
* - ESP_OK: Set glitch filter successfully
* - ESP_ERR_INVALID_ARG: Set glitch filter failed because of invalid argument (e.g. glitch width is too big)
* - ESP_ERR_INVALID_STATE: Set glitch filter failed because the unit is not in the init state
* - ESP_FAIL: Set glitch filter failed because of other error
*/
esp_err_t pcnt_unit_set_glitch_filter(pcnt_unit_handle_t unit, const pcnt_glitch_filter_config_t *config);
/**
* @brief Enable the PCNT unit
*
* @note This function will transit the unit state from init to enable.
* @note This function will enable the interrupt service, if it's lazy installed in `pcnt_unit_register_event_callbacks()`.
* @note This function will acquire the PM lock if it's lazy installed in `pcnt_unit_set_glitch_filter()`.
* @note Enable a PCNT unit doesn't mean to start it. See also `pcnt_unit_start()` for how to start the PCNT counter.
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Enable PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Enable PCNT unit failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable PCNT unit failed because the unit is already enabled
* - ESP_FAIL: Enable PCNT unit failed because of other error
*/
esp_err_t pcnt_unit_enable(pcnt_unit_handle_t unit);
/**
* @brief Disable the PCNT unit
*
* @note This function will do the opposite work to the `pcnt_unit_enable()`
* @note Disable a PCNT unit doesn't mean to stop it. See also `pcnt_unit_stop()` for how to stop the PCNT counter.
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Disable PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Disable PCNT unit failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable PCNT unit failed because the unit is not enabled yet
* - ESP_FAIL: Disable PCNT unit failed because of other error
*/
esp_err_t pcnt_unit_disable(pcnt_unit_handle_t unit);
/**
* @brief Start the PCNT unit, the counter will start to count according to the edge and/or level input signals
*
* @note This function should be called when the unit is in the enable state (i.e. after calling `pcnt_unit_enable()`)
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Start PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Start PCNT unit failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Start PCNT unit failed because the unit is not enabled yet
* - ESP_FAIL: Start PCNT unit failed because of other error
*/
esp_err_t pcnt_unit_start(pcnt_unit_handle_t unit);
/**
* @brief Stop PCNT from counting
*
* @note This function should be called when the unit is in the enable state (i.e. after calling `pcnt_unit_enable()`)
* @note The stop operation won't clear the counter. Also see `pcnt_unit_clear_count()` for how to clear pulse count value.
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM`, so that it is allowed to be executed when Cache is disabled
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Stop PCNT unit successfully
* - ESP_ERR_INVALID_ARG: Stop PCNT unit failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Stop PCNT unit failed because the unit is not enabled yet
* - ESP_FAIL: Stop PCNT unit failed because of other error
*/
esp_err_t pcnt_unit_stop(pcnt_unit_handle_t unit);
/**
* @brief Clear PCNT pulse count value to zero
*
* @note It's recommended to call this function after adding a watch point by `pcnt_unit_add_watch_point()`, so that the newly added watch point is effective immediately.
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM`, so that it's allowed to be executed when Cache is disabled
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @return
* - ESP_OK: Clear PCNT pulse count successfully
* - ESP_ERR_INVALID_ARG: Clear PCNT pulse count failed because of invalid argument
* - ESP_FAIL: Clear PCNT pulse count failed because of other error
*/
esp_err_t pcnt_unit_clear_count(pcnt_unit_handle_t unit);
/**
* @brief Get PCNT count value
*
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_PCNT_CTRL_FUNC_IN_IRAM`, so that it's allowed to be executed when Cache is disabled
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[out] value Returned count value
* @return
* - ESP_OK: Get PCNT pulse count successfully
* - ESP_ERR_INVALID_ARG: Get PCNT pulse count failed because of invalid argument
* - ESP_FAIL: Get PCNT pulse count failed because of other error
*/
esp_err_t pcnt_unit_get_count(pcnt_unit_handle_t unit, int *value);
/**
* @brief Set event callbacks for PCNT unit
*
* @note User registered callbacks are expected to be runnable within ISR context
* @note The first call to this function needs to be before the call to `pcnt_unit_enable`
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Set event callbacks failed because the unit is not in init state
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt_event_callbacks_t *cbs, void *user_data);
/**
* @brief Add a watch point for PCNT unit, PCNT will generate an event when the counter value reaches the watch point value
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[in] watch_point Value to be watched
* @return
* - ESP_OK: Add watch point successfully
* - ESP_ERR_INVALID_ARG: Add watch point failed because of invalid argument (e.g. the value to be watched is out of the limitation set in `pcnt_unit_config_t`)
* - ESP_ERR_INVALID_STATE: Add watch point failed because the same watch point has already been added
* - ESP_ERR_NOT_FOUND: Add watch point failed because no more hardware watch point can be configured
* - ESP_FAIL: Add watch point failed because of other error
*/
esp_err_t pcnt_unit_add_watch_point(pcnt_unit_handle_t unit, int watch_point);
/**
* @brief Remove a watch point for PCNT unit
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[in] watch_point Watch point value
* @return
* - ESP_OK: Remove watch point successfully
* - ESP_ERR_INVALID_ARG: Remove watch point failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Remove watch point failed because the watch point was not added by `pcnt_unit_add_watch_point()` yet
* - ESP_FAIL: Remove watch point failed because of other error
*/
esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point);
/**
* @brief Create PCNT channel for specific unit, each PCNT has several channels associated with it
*
* @note This function should be called when the unit is in init state (i.e. before calling `pcnt_unit_enable()`)
*
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
* @param[in] config PCNT channel configuration
* @param[out] ret_chan Returned channel handle
* @return
* - ESP_OK: Create PCNT channel successfully
* - ESP_ERR_INVALID_ARG: Create PCNT channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create PCNT channel failed because of insufficient memory
* - ESP_ERR_NOT_FOUND: Create PCNT channel failed because all PCNT channels are used up and no more free one
* - ESP_ERR_INVALID_STATE: Create PCNT channel failed because the unit is not in the init state
* - ESP_FAIL: Create PCNT channel failed because of other error
*/
esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *config, pcnt_channel_handle_t *ret_chan);
/**
* @brief Delete the PCNT channel
*
* @param[in] chan PCNT channel handle created by `pcnt_new_channel()`
* @return
* - ESP_OK: Delete the PCNT channel successfully
* - ESP_ERR_INVALID_ARG: Delete the PCNT channel failed because of invalid argument
* - ESP_FAIL: Delete the PCNT channel failed because of other error
*/
esp_err_t pcnt_del_channel(pcnt_channel_handle_t chan);
/**
* @brief Set channel actions when edge signal changes (e.g. falling or rising edge occurred).
* The edge signal is input from the `edge_gpio_num` configured in `pcnt_chan_config_t`.
* We use these actions to control when and how to change the counter value.
*
* @param[in] chan PCNT channel handle created by `pcnt_new_channel()`
* @param[in] pos_act Action on posedge signal
* @param[in] neg_act Action on negedge signal
* @return
* - ESP_OK: Set edge action for PCNT channel successfully
* - ESP_ERR_INVALID_ARG: Set edge action for PCNT channel failed because of invalid argument
* - ESP_FAIL: Set edge action for PCNT channel failed because of other error
*/
esp_err_t pcnt_channel_set_edge_action(pcnt_channel_handle_t chan, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act);
/**
* @brief Set channel actions when level signal changes (e.g. signal level goes from high to low).
* The level signal is input from the `level_gpio_num` configured in `pcnt_chan_config_t`.
* We use these actions to control when and how to change the counting mode.
*
* @param[in] chan PCNT channel handle created by `pcnt_new_channel()`
* @param[in] high_act Action on high level signal
* @param[in] low_act Action on low level signal
* @return
* - ESP_OK: Set level action for PCNT channel successfully
* - ESP_ERR_INVALID_ARG: Set level action for PCNT channel failed because of invalid argument
* - ESP_FAIL: Set level action for PCNT channel failed because of other error
*/
esp_err_t pcnt_channel_set_level_action(pcnt_channel_handle_t chan, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act);
#ifdef __cplusplus
}
#endif
@@ -1,83 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#include "driver/rmt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief RMT carrier wave configuration (for either modulation or demodulation)
*/
typedef struct {
uint32_t frequency_hz; /*!< Carrier wave frequency, in Hz, 0 means disabling the carrier */
float duty_cycle; /*!< Carrier wave duty cycle (0~100%) */
struct {
uint32_t polarity_active_low: 1; /*!< Specify the polarity of carrier, by default it's modulated to base signal's high level */
uint32_t always_on: 1; /*!< If set, the carrier can always exist even there's not transfer undergoing */
} flags; /*!< Carrier config flags */
} rmt_carrier_config_t;
/**
* @brief Delete an RMT channel
*
* @param[in] channel RMT generic channel that created by `rmt_new_tx_channel()` or `rmt_new_rx_channel()`
* @return
* - ESP_OK: Delete RMT channel successfully
* - ESP_ERR_INVALID_ARG: Delete RMT channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete RMT channel failed because it is still in working
* - ESP_FAIL: Delete RMT channel failed because of other error
*/
esp_err_t rmt_del_channel(rmt_channel_handle_t channel);
/**
* @brief Apply modulation feature for TX channel or demodulation feature for RX channel
*
* @param[in] channel RMT generic channel that created by `rmt_new_tx_channel()` or `rmt_new_rx_channel()`
* @param[in] config Carrier configuration. Specially, a NULL config means to disable the carrier modulation or demodulation feature
* @return
* - ESP_OK: Apply carrier configuration successfully
* - ESP_ERR_INVALID_ARG: Apply carrier configuration failed because of invalid argument
* - ESP_FAIL: Apply carrier configuration failed because of other error
*/
esp_err_t rmt_apply_carrier(rmt_channel_handle_t channel, const rmt_carrier_config_t *config);
/**
* @brief Enable the RMT channel
*
* @note This function will acquire a PM lock that might be installed during channel allocation
*
* @param[in] channel RMT generic channel that created by `rmt_new_tx_channel()` or `rmt_new_rx_channel()`
* @return
* - ESP_OK: Enable RMT channel successfully
* - ESP_ERR_INVALID_ARG: Enable RMT channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable RMT channel failed because it's enabled already
* - ESP_FAIL: Enable RMT channel failed because of other error
*/
esp_err_t rmt_enable(rmt_channel_handle_t channel);
/**
* @brief Disable the RMT channel
*
* @note This function will release a PM lock that might be installed during channel allocation
*
* @param[in] channel RMT generic channel that created by `rmt_new_tx_channel()` or `rmt_new_rx_channel()`
* @return
* - ESP_OK: Disable RMT channel successfully
* - ESP_ERR_INVALID_ARG: Disable RMT channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable RMT channel failed because it's not enabled yet
* - ESP_FAIL: Disable RMT channel failed because of other error
*/
esp_err_t rmt_disable(rmt_channel_handle_t channel);
#ifdef __cplusplus
}
#endif
@@ -1,137 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#include "hal/rmt_types.h"
#include "driver/rmt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @cond */
typedef struct rmt_encoder_t rmt_encoder_t;
/** @endcond */
/**
* @brief RMT encoding state
*/
typedef enum {
RMT_ENCODING_COMPLETE = (1 << 0), /*!< The encoding session is finished, the caller can continue with subsequent encoding */
RMT_ENCODING_MEM_FULL = (1 << 1), /*!< The encoding artifact memory is full, the caller should return from current encoding session */
} rmt_encode_state_t;
/**
* @brief Interface of RMT encoder
*/
struct rmt_encoder_t {
/**
* @brief Encode the user data into RMT symbols and write into RMT memory
*
* @note The encoding function will also be called from an ISR context, thus the function must not call any blocking API.
* @note It's recommended to put this function implementation in the IRAM, to achieve a high performance and less interrupt latency.
*
* @param[in] encoder Encoder handle
* @param[in] tx_channel RMT TX channel handle, returned from `rmt_new_tx_channel()`
* @param[in] primary_data App data to be encoded into RMT symbols
* @param[in] data_size Size of primary_data, in bytes
* @param[out] ret_state Returned current encoder's state
* @return Number of RMT symbols that the primary data has been encoded into
*/
size_t (*encode)(rmt_encoder_t *encoder, rmt_channel_handle_t tx_channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state);
/**
* @brief Reset encoding state
*
* @param[in] encoder Encoder handle
* @return
* - ESP_OK: reset encoder successfully
* - ESP_FAIL: reset encoder failed
*/
esp_err_t (*reset)(rmt_encoder_t *encoder);
/**
* @brief Delete encoder object
*
* @param[in] encoder Encoder handle
* @return
* - ESP_OK: delete encoder successfully
* - ESP_FAIL: delete encoder failed
*/
esp_err_t (*del)(rmt_encoder_t *encoder);
};
/**
* @brief Bytes encoder configuration
*/
typedef struct {
rmt_symbol_word_t bit0; /*!< How to represent BIT0 in RMT symbol */
rmt_symbol_word_t bit1; /*!< How to represent BIT1 in RMT symbol */
struct {
uint32_t msb_first: 1; /*!< Whether to encode MSB bit first */
} flags; /*!< Encoder config flag */
} rmt_bytes_encoder_config_t;
/**
* @brief Copy encoder configuration
*/
typedef struct {
} rmt_copy_encoder_config_t;
/**
* @brief Create RMT bytes encoder, which can encode byte stream into RMT symbols
*
* @param[in] config Bytes encoder configuration
* @param[out] ret_encoder Returned encoder handle
* @return
* - ESP_OK: Create RMT bytes encoder successfully
* - ESP_ERR_INVALID_ARG: Create RMT bytes encoder failed because of invalid argument
* - ESP_ERR_NO_MEM: Create RMT bytes encoder failed because out of memory
* - ESP_FAIL: Create RMT bytes encoder failed because of other error
*/
esp_err_t rmt_new_bytes_encoder(const rmt_bytes_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
/**
* @brief Create RMT copy encoder, which copies the given RMT symbols into RMT memory
*
* @param[in] config Copy encoder configuration
* @param[out] ret_encoder Returned encoder handle
* @return
* - ESP_OK: Create RMT copy encoder successfully
* - ESP_ERR_INVALID_ARG: Create RMT copy encoder failed because of invalid argument
* - ESP_ERR_NO_MEM: Create RMT copy encoder failed because out of memory
* - ESP_FAIL: Create RMT copy encoder failed because of other error
*/
esp_err_t rmt_new_copy_encoder(const rmt_copy_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
/**
* @brief Delete RMT encoder
*
* @param[in] encoder RMT encoder handle, created by e.g `rmt_new_bytes_encoder()`
* @return
* - ESP_OK: Delete RMT encoder successfully
* - ESP_ERR_INVALID_ARG: Delete RMT encoder failed because of invalid argument
* - ESP_FAIL: Delete RMT encoder failed because of other error
*/
esp_err_t rmt_del_encoder(rmt_encoder_handle_t encoder);
/**
* @brief Reset RMT encoder
*
* @param[in] encoder RMT encoder handle, created by e.g `rmt_new_bytes_encoder()`
* @return
* - ESP_OK: Reset RMT encoder successfully
* - ESP_ERR_INVALID_ARG: Reset RMT encoder failed because of invalid argument
* - ESP_FAIL: Reset RMT encoder failed because of other error
*/
esp_err_t rmt_encoder_reset(rmt_encoder_handle_t encoder);
#ifdef __cplusplus
}
#endif
-103
View File
@@ -1,103 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#include "driver/rmt_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Group of RMT RX callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_RMT_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well.
*/
typedef struct {
rmt_rx_done_callback_t on_recv_done; /*!< Event callback, invoked when one RMT channel receiving transaction completes */
} rmt_rx_event_callbacks_t;
/**
* @brief RMT RX channel specific configuration
*/
typedef struct {
int gpio_num; /*!< GPIO number used by RMT RX channel. Set to -1 if unused */
rmt_clock_source_t clk_src; /*!< Clock source of RMT RX channel, channels in the same group must use the same clock source */
uint32_t resolution_hz; /*!< Channel clock resolution, in Hz */
size_t mem_block_symbols; /*!< Size of memory block, in number of `rmt_symbol_word_t`, must be an even */
struct {
uint32_t invert_in: 1; /*!< Whether to invert the incoming RMT channel signal */
uint32_t with_dma: 1; /*!< If set, the driver will allocate an RMT channel with DMA capability */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
} flags; /*!< RX channel config flags */
} rmt_rx_channel_config_t;
/**
* @brief RMT receive specific configuration
*/
typedef struct {
uint32_t signal_range_min_ns; /*!< A pulse whose width is smaller than this threshold will be treated as glitch and ignored */
uint32_t signal_range_max_ns; /*!< RMT will stop receiving if one symbol level has kept more than `signal_range_max_ns` */
} rmt_receive_config_t;
/**
* @brief Create a RMT RX channel
*
* @param[in] config RX channel configurations
* @param[out] ret_chan Returned generic RMT channel handle
* @return
* - ESP_OK: Create RMT RX channel successfully
* - ESP_ERR_INVALID_ARG: Create RMT RX channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create RMT RX channel failed because out of memory
* - ESP_ERR_NOT_FOUND: Create RMT RX channel failed because all RMT channels are used up and no more free one
* - ESP_ERR_NOT_SUPPORTED: Create RMT RX channel failed because some feature is not supported by hardware, e.g. DMA feature is not supported by hardware
* - ESP_FAIL: Create RMT RX channel failed because of other error
*/
esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_handle_t *ret_chan);
/**
* @brief Initiate a receive job for RMT RX channel
*
* @note This function is non-blocking, it initiates a new receive job and then returns.
* User should check the received data from the `on_recv_done` callback that registered by `rmt_rx_register_event_callbacks()`.
*
* @param[in] rx_channel RMT RX channel that created by `rmt_new_rx_channel()`
* @param[in] buffer The buffer to store the received RMT symbols
* @param[in] buffer_size size of the `buffer`, in bytes
* @param[in] config Receive specific configurations
* @return
* - ESP_OK: Initiate receive job successfully
* - ESP_ERR_INVALID_ARG: Initiate receive job failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Initiate receive job failed because channel is not enabled
* - ESP_FAIL: Initiate receive job failed because of other error
*/
esp_err_t rmt_receive(rmt_channel_handle_t rx_channel, void *buffer, size_t buffer_size, const rmt_receive_config_t *config);
/**
* @brief Set callbacks for RMT RX channel
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
* @note When CONFIG_RMT_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well. The `user_data` should also reside in SRAM.
*
* @param[in] rx_channel RMT generic channel that created by `rmt_new_rx_channel()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t rmt_rx_register_event_callbacks(rmt_channel_handle_t rx_channel, const rmt_rx_event_callbacks_t *cbs, void *user_data);
#ifdef __cplusplus
}
#endif
-175
View File
@@ -1,175 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#include "driver/rmt_common.h"
#include "driver/rmt_encoder.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Group of RMT TX callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_RMT_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well.
*/
typedef struct {
rmt_tx_done_callback_t on_trans_done; /*!< Event callback, invoked when transmission is finished */
} rmt_tx_event_callbacks_t;
/**
* @brief RMT TX channel specific configuration
*/
typedef struct {
int gpio_num; /*!< GPIO number used by RMT TX channel. Set to -1 if unused */
rmt_clock_source_t clk_src; /*!< Clock source of RMT TX channel, channels in the same group must use the same clock source */
uint32_t resolution_hz; /*!< Channel clock resolution, in Hz */
size_t mem_block_symbols; /*!< Size of memory block, in number of `rmt_symbol_word_t`, must be an even */
size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background */
struct {
uint32_t invert_out: 1; /*!< Whether to invert the RMT channel signal before output to GPIO pad */
uint32_t with_dma: 1; /*!< If set, the driver will allocate an RMT channel with DMA capability */
uint32_t io_loop_back: 1; /*!< The signal output from the GPIO will be fed to the input path as well */
uint32_t io_od_mode: 1; /*!< Configure the GPIO as open-drain mode */
} flags; /*!< TX channel config flags */
} rmt_tx_channel_config_t;
/**
* @brief RMT transmit specific configuration
*/
typedef struct {
int loop_count; /*!< Specify the times of transmission in a loop, -1 means transmitting in an infinite loop */
struct {
uint32_t eot_level : 1; /*!< Set the output level for the "End Of Transmission" */
} flags; /*!< Transmit config flags */
} rmt_transmit_config_t;
/**
* @brief Synchronous manager configuration
*/
typedef struct {
const rmt_channel_handle_t *tx_channel_array; /*!< Array of TX channels that are about to be managed by a synchronous controller */
size_t array_size; /*!< Size of the `tx_channel_array` */
} rmt_sync_manager_config_t;
/**
* @brief Create a RMT TX channel
*
* @param[in] config TX channel configurations
* @param[out] ret_chan Returned generic RMT channel handle
* @return
* - ESP_OK: Create RMT TX channel successfully
* - ESP_ERR_INVALID_ARG: Create RMT TX channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create RMT TX channel failed because out of memory
* - ESP_ERR_NOT_FOUND: Create RMT TX channel failed because all RMT channels are used up and no more free one
* - ESP_ERR_NOT_SUPPORTED: Create RMT TX channel failed because some feature is not supported by hardware, e.g. DMA feature is not supported by hardware
* - ESP_FAIL: Create RMT TX channel failed because of other error
*/
esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_handle_t *ret_chan);
/**
* @brief Transmit data by RMT TX channel
*
* @note This function will construct a transaction descriptor and push to a queue. The transaction will not start immediately until it's dispatched in the ISR.
* If there're too many transactions pending in the queue, this function will block until the queue has free space.
* @note The data to be transmitted will be encoded into RMT symbols by the specific `encoder`.
*
* @param[in] tx_channel RMT TX channel that created by `rmt_new_tx_channel()`
* @param[in] encoder RMT encoder that created by various factory APIs like `rmt_new_bytes_encoder()`
* @param[in] payload The raw data to be encoded into RMT symbols
* @param[in] payload_bytes Size of the `payload` in bytes
* @param[in] config Transmission specific configuration
* @return
* - ESP_OK: Transmit data successfully
* - ESP_ERR_INVALID_ARG: Transmit data failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Transmit data failed because channel is not enabled
* - ESP_ERR_NOT_SUPPORTED: Transmit data failed because some feature is not supported by hardware, e.g. unsupported loop count
* - ESP_FAIL: Transmit data failed because of other error
*/
esp_err_t rmt_transmit(rmt_channel_handle_t tx_channel, rmt_encoder_handle_t encoder, const void *payload, size_t payload_bytes, const rmt_transmit_config_t *config);
/**
* @brief Wait for all pending TX transactions done
*
* @note This function will block forever if the pending transaction can't be finished within a limited time (e.g. an infinite loop transaction).
* See also `rmt_disable()` for how to terminate a working channel.
*
* @param[in] tx_channel RMT TX channel that created by `rmt_new_tx_channel()`
* @param[in] timeout_ms Wait timeout, in ms. Specially, -1 means to wait forever.
* @return
* - ESP_OK: Flush transactions successfully
* - ESP_ERR_INVALID_ARG: Flush transactions failed because of invalid argument
* - ESP_ERR_TIMEOUT: Flush transactions failed because of timeout
* - ESP_FAIL: Flush transactions failed because of other error
*/
esp_err_t rmt_tx_wait_all_done(rmt_channel_handle_t tx_channel, int timeout_ms);
/**
* @brief Set event callbacks for RMT TX channel
*
* @note User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.
* @note When CONFIG_RMT_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
* The variables used in the function should be in the SRAM as well. The `user_data` should also reside in SRAM.
*
* @param[in] tx_channel RMT generic channel that created by `rmt_new_tx_channel()`
* @param[in] cbs Group of callback functions
* @param[in] user_data User data, which will be passed to callback functions directly
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t rmt_tx_register_event_callbacks(rmt_channel_handle_t tx_channel, const rmt_tx_event_callbacks_t *cbs, void *user_data);
/**
* @brief Create a synchronization manager for multiple TX channels, so that the managed channel can start transmitting at the same time
*
* @note All the channels to be managed should be enabled by `rmt_enable()` before put them into sync manager.
*
* @param[in] config Synchronization manager configuration
* @param[out] ret_synchro Returned synchronization manager handle
* @return
* - ESP_OK: Create sync manager successfully
* - ESP_ERR_INVALID_ARG: Create sync manager failed because of invalid argument
* - ESP_ERR_NOT_SUPPORTED: Create sync manager failed because it is not supported by hardware
* - ESP_ERR_INVALID_STATE: Create sync manager failed because not all channels are enabled
* - ESP_ERR_NO_MEM: Create sync manager failed because out of memory
* - ESP_ERR_NOT_FOUND: Create sync manager failed because all sync controllers are used up and no more free one
* - ESP_FAIL: Create sync manager failed because of other error
*/
esp_err_t rmt_new_sync_manager(const rmt_sync_manager_config_t *config, rmt_sync_manager_handle_t *ret_synchro);
/**
* @brief Delete synchronization manager
*
* @param[in] synchro Synchronization manager handle returned from `rmt_new_sync_manager()`
* @return
* - ESP_OK: Delete the synchronization manager successfully
* - ESP_ERR_INVALID_ARG: Delete the synchronization manager failed because of invalid argument
* - ESP_FAIL: Delete the synchronization manager failed because of other error
*/
esp_err_t rmt_del_sync_manager(rmt_sync_manager_handle_t synchro);
/**
* @brief Reset synchronization manager
*
* @param[in] synchro Synchronization manager handle returned from `rmt_new_sync_manager()`
* @return
* - ESP_OK: Reset the synchronization manager successfully
* - ESP_ERR_INVALID_ARG: Reset the synchronization manager failed because of invalid argument
* - ESP_FAIL: Reset the synchronization manager failed because of other error
*/
esp_err_t rmt_sync_reset(rmt_sync_manager_handle_t synchro);
#ifdef __cplusplus
}
#endif
@@ -1,73 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "hal/rmt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of RMT channel handle
*/
typedef struct rmt_channel_t *rmt_channel_handle_t;
/**
* @brief Type of RMT synchronization manager handle
*/
typedef struct rmt_sync_manager_t *rmt_sync_manager_handle_t;
/**
* @brief Type of RMT encoder handle
*/
typedef struct rmt_encoder_t *rmt_encoder_handle_t;
/**
* @brief Type of RMT TX done event data
*/
typedef struct {
size_t num_symbols; /*!< The number of transmitted RMT symbols, including one EOF symbol, which is appended by the driver to mark the end of a transmission.
For a loop transmission, this value only counts for one round. */
} rmt_tx_done_event_data_t;
/**
* @brief Prototype of RMT event callback
* @param[in] tx_chan RMT channel handle, created from `rmt_new_tx_channel()`
* @param[in] edata Point to RMT event data. The lifecycle of this pointer memory is inside this function,
* user should copy it into static memory if used outside this funcion.
* @param[in] user_ctx User registered context, passed from `rmt_tx_register_event_callbacks()`
*
* @return Whether a high priority task has been waken up by this callback function
*/
typedef bool (*rmt_tx_done_callback_t)(rmt_channel_handle_t tx_chan, const rmt_tx_done_event_data_t *edata, void *user_ctx);
/**
* @brief Type of RMT RX done event data
*/
typedef struct {
rmt_symbol_word_t *received_symbols; /*!< Point to the received RMT symbols */
size_t num_symbols; /*!< The number of received RMT symbols */
} rmt_rx_done_event_data_t;
/**
* @brief Prototype of RMT event callback
*
* @param[in] rx_chan RMT channel handle, created from `rmt_new_rx_channel()`
* @param[in] edata Point to RMT event data. The lifecycle of this pointer memory is inside this function,
* user should copy it into static memory if used outside this funcion.
* @param[in] user_ctx User registered context, passed from `rmt_rx_register_event_callbacks()`
* @return Whether a high priority task has been waken up by this function
*/
typedef bool (*rmt_rx_done_callback_t)(rmt_channel_handle_t rx_chan, const rmt_rx_done_event_data_t *edata, void *user_ctx);
#ifdef __cplusplus
}
#endif
-297
View File
@@ -1,297 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "hal/rtc_io_types.h"
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Determine if the specified GPIO is a valid RTC GPIO.
*
* @param gpio_num GPIO number
* @return true if GPIO is valid for RTC GPIO use. false otherwise.
*/
bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num);
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num)
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
/**
* @brief Get RTC IO index number by gpio number.
*
* @param gpio_num GPIO number
* @return
* >=0: Index of rtcio.
* -1 : The gpio is not rtcio.
*/
int rtc_io_number_get(gpio_num_t gpio_num);
/**
* @brief Init a GPIO as RTC GPIO
*
* This function must be called when initializing a pad for an analog function.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_init(gpio_num_t gpio_num);
/**
* @brief Init a GPIO as digital GPIO
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num);
/**
* @brief Get the RTC IO input level
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - 1 High level
* - 0 Low level
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
uint32_t rtc_gpio_get_level(gpio_num_t gpio_num);
/**
* @brief Set the RTC IO output level
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
* @param level output level
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level);
/**
* @brief RTC GPIO set direction
*
* Configure RTC GPIO direction, such as output only, input only,
* output and input.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
* @param mode GPIO direction
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode);
/**
* @brief RTC GPIO set direction in deep sleep mode or disable sleep status (default).
* In some application scenarios, IO needs to have another states during deep sleep.
*
* NOTE: ESP32 support INPUT_ONLY mode.
* ESP32S2 support INPUT_ONLY, OUTPUT_ONLY, INPUT_OUTPUT mode.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
* @param mode GPIO direction
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t mode);
/**
* @brief RTC GPIO pullup enable
*
* This function only works for RTC IOs. In general, call gpio_pullup_en,
* which will work both for normal GPIOs and RTC IOs.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num);
/**
* @brief RTC GPIO pulldown enable
*
* This function only works for RTC IOs. In general, call gpio_pulldown_en,
* which will work both for normal GPIOs and RTC IOs.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num);
/**
* @brief RTC GPIO pullup disable
*
* This function only works for RTC IOs. In general, call gpio_pullup_dis,
* which will work both for normal GPIOs and RTC IOs.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num);
/**
* @brief RTC GPIO pulldown disable
*
* This function only works for RTC IOs. In general, call gpio_pulldown_dis,
* which will work both for normal GPIOs and RTC IOs.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num);
/**
* @brief Set RTC GPIO pad drive capability
*
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Drive capability of the pad
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength);
/**
* @brief Get RTC GPIO pad drive capability
*
* @param gpio_num GPIO number, only support output GPIOs
* @param strength Pointer to accept drive capability of the pad
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t* strength);
#endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
#if SOC_RTCIO_HOLD_SUPPORTED
/**
* @brief Enable hold function on an RTC IO pad
*
* Enabling HOLD function will cause the pad to latch current values of
* input enable, output enable, output value, function, drive strength values.
* This function is useful when going into light or deep sleep mode to prevent
* the pin configuration from changing.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num);
/**
* @brief Disable hold function on an RTC IO pad
*
* Disabling hold function will allow the pad receive the values of
* input enable, output enable, output value, function, drive strength from
* RTC_IO peripheral.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12)
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num);
/**
* @brief Helper function to disconnect internal circuits from an RTC IO
* This function disables input, output, pullup, pulldown, and enables
* hold feature for an RTC IO.
* Use this function if an RTC IO needs to be disconnected from internal
* circuits in deep sleep, to minimize leakage current.
*
* In particular, for ESP32-WROVER module, call
* rtc_gpio_isolate(GPIO_NUM_12) before entering deep sleep, to reduce
* deep sleep current.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12).
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num);
/**
* @brief Enable force hold signal for all RTC IOs
*
* Each RTC pad has a "force hold" input signal from the RTC controller.
* If this signal is set, pad latches current values of input enable,
* function, output enable, and other signals which come from the RTC mux.
* Force hold signal is enabled before going into deep sleep for pins which
* are used for EXT1 wakeup.
*/
esp_err_t rtc_gpio_force_hold_en_all(void);
/**
* @brief Disable force hold signal for all RTC IOs
*/
esp_err_t rtc_gpio_force_hold_dis_all(void);
#endif // SOC_RTCIO_HOLD_SUPPORTED
#if SOC_RTCIO_WAKE_SUPPORTED
/**
* @brief Enable wakeup from sleep mode using specific GPIO
* @param gpio_num GPIO number
* @param intr_type Wakeup on high level (GPIO_INTR_HIGH_LEVEL) or low level
* (GPIO_INTR_LOW_LEVEL)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if gpio_num is not an RTC IO, or intr_type is not
* one of GPIO_INTR_HIGH_LEVEL, GPIO_INTR_LOW_LEVEL.
*/
esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
/**
* @brief Disable wakeup from sleep mode using specific GPIO
* @param gpio_num GPIO number
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if gpio_num is not an RTC IO
*/
esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num);
#endif // SOC_RTCIO_WAKE_SUPPORTED
#ifdef __cplusplus
}
#endif
@@ -1,288 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "freertos/FreeRTOS.h" // for TickType_t
#include "hal/sdio_slave_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SDIO_SLAVE_RECV_MAX_BUFFER (4096-4)
typedef void(*sdio_event_cb_t)(uint8_t event);
/// Configuration of SDIO slave
typedef struct {
sdio_slave_timing_t timing; ///< timing of sdio_slave. see `sdio_slave_timing_t`.
sdio_slave_sending_mode_t sending_mode; ///< mode of sdio_slave. `SDIO_SLAVE_MODE_STREAM` if the data needs to be sent as much as possible; `SDIO_SLAVE_MODE_PACKET` if the data should be sent in packets.
int send_queue_size; ///< max buffers that can be queued before sending.
size_t recv_buffer_size;
///< If buffer_size is too small, it costs more CPU time to handle larger number of buffers.
///< If buffer_size is too large, the space larger than the transaction length is left blank but still counts a buffer, and the buffers are easily run out.
///< Should be set according to length of data really transferred.
///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer.
///< Buffer size of the slave pre-defined between host and slave before communication. All receive buffer given to the driver should be larger than this.
sdio_event_cb_t event_cb; ///< when the host interrupts slave, this callback will be called with interrupt number (0-7).
uint32_t flags; ///< Features to be enabled for the slave, combinations of ``SDIO_SLAVE_FLAG_*``.
#define SDIO_SLAVE_FLAG_DAT2_DISABLED BIT(0) /**< It is required by the SD specification that all 4 data
lines should be used and pulled up even in 1-bit mode or SPI mode. However, as a feature, the user can specify
this flag to make use of DAT2 pin in 1-bit mode. Note that the host cannot read CCCR registers to know we don't
support 4-bit mode anymore, please do this at your own risk.
*/
#define SDIO_SLAVE_FLAG_HOST_INTR_DISABLED BIT(1) /**< The DAT1 line is used as the interrupt line in SDIO
protocol. However, as a feature, the user can specify this flag to make use of DAT1 pin of the slave in 1-bit
mode. Note that the host has to do polling to the interrupt registers to know whether there are interrupts from
the slave. And it cannot read CCCR registers to know we don't support 4-bit mode anymore, please do this at
your own risk.
*/
#define SDIO_SLAVE_FLAG_INTERNAL_PULLUP BIT(2) /**< Enable internal pullups for enabled pins. It is required
by the SD specification that all the 4 data lines should be pulled up even in 1-bit mode or SPI mode. Note that
the internal pull-ups are not sufficient for stable communication, please do connect external pull-ups on the
bus. This is only for example and debug use.
*/
#define SDIO_SLAVE_FLAG_DEFAULT_SPEED BIT(3) /**< Disable the highspeed support of the hardware. */
#define SDIO_SLAVE_FLAG_HIGH_SPEED 0 /**< Enable the highspeed support of the hardware. This is the
default option. The host will see highspeed capability, but the mode actually used is determined by the host. */
} sdio_slave_config_t;
/** Handle of a receive buffer, register a handle by calling ``sdio_slave_recv_register_buf``. Use the handle to load the buffer to the
* driver, or call ``sdio_slave_recv_unregister_buf`` if it is no longer used.
*/
typedef void *sdio_slave_buf_handle_t;
/** Initialize the sdio slave driver
*
* @param config Configuration of the sdio slave driver.
*
* @return
* - ESP_ERR_NOT_FOUND if no free interrupt found.
* - ESP_ERR_INVALID_STATE if already initialized.
* - ESP_ERR_NO_MEM if fail due to memory allocation failed.
* - ESP_OK if success
*/
esp_err_t sdio_slave_initialize(sdio_slave_config_t *config);
/** De-initialize the sdio slave driver to release the resources.
*/
void sdio_slave_deinit(void);
/** Start hardware for sending and receiving, as well as set the IOREADY1 to 1.
*
* @note The driver will continue sending from previous data and PKT_LEN counting, keep data received as well as start receiving from current TOKEN1 counting.
* See ``sdio_slave_reset``.
*
* @return
* - ESP_ERR_INVALID_STATE if already started.
* - ESP_OK otherwise.
*/
esp_err_t sdio_slave_start(void);
/** Stop hardware from sending and receiving, also set IOREADY1 to 0.
*
* @note this will not clear the data already in the driver, and also not reset the PKT_LEN and TOKEN1 counting. Call ``sdio_slave_reset`` to do that.
*/
void sdio_slave_stop(void);
/** Clear the data still in the driver, as well as reset the PKT_LEN and TOKEN1 counting.
*
* @return always return ESP_OK.
*/
esp_err_t sdio_slave_reset(void);
/*---------------------------------------------------------------------------
* Receive
*--------------------------------------------------------------------------*/
/** Register buffer used for receiving. All buffers should be registered before used, and then can be used (again) in the driver by the handle returned.
*
* @param start The start address of the buffer.
*
* @note The driver will use and only use the amount of space specified in the `recv_buffer_size` member set in the `sdio_slave_config_t`.
* All buffers should be larger than that. The buffer is used by the DMA, so it should be DMA capable and 32-bit aligned.
*
* @return The buffer handle if success, otherwise NULL.
*/
sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start);
/** Unregister buffer from driver, and free the space used by the descriptor pointing to the buffer.
*
* @param handle Handle to the buffer to release.
*
* @return ESP_OK if success, ESP_ERR_INVALID_ARG if the handle is NULL or the buffer is being used.
*/
esp_err_t sdio_slave_recv_unregister_buf(sdio_slave_buf_handle_t handle);
/** Load buffer to the queue waiting to receive data. The driver takes ownership of the buffer until the buffer is returned by
* ``sdio_slave_send_get_finished`` after the transaction is finished.
*
* @param handle Handle to the buffer ready to receive data.
*
* @return
* - ESP_ERR_INVALID_ARG if invalid handle or the buffer is already in the queue. Only after the buffer is returened by
* ``sdio_slave_recv`` can you load it again.
* - ESP_OK if success
*/
esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle);
/** Get buffer of received data if exist with packet information. The driver returns the ownership of the buffer to the app.
*
* When you see return value is ``ESP_ERR_NOT_FINISHED``, you should call this API iteratively until the return value is ``ESP_OK``.
* All the continuous buffers returned with ``ESP_ERR_NOT_FINISHED``, together with the last buffer returned with ``ESP_OK``, belong to one packet from the host.
*
* You can call simpler ``sdio_slave_recv`` instead, if the host never send data longer than the Receiving buffer size,
* or you don't care about the packet boundary (e.g. the data is only a byte stream).
*
* @param handle_ret Handle of the buffer holding received data. Use this handle in ``sdio_slave_recv_load_buf()`` to receive in the same buffer again.
* @param wait Time to wait before data received.
*
* @note Call ``sdio_slave_load_buf`` with the handle to re-load the buffer onto the link list, and receive with the same buffer again.
* The address and length of the buffer got here is the same as got from `sdio_slave_get_buffer`.
*
* @return
* - ESP_ERR_INVALID_ARG if handle_ret is NULL
* - ESP_ERR_TIMEOUT if timeout before receiving new data
* - ESP_ERR_NOT_FINISHED if returned buffer is not the end of a packet from the host, should call this API again until the end of a packet
* - ESP_OK if success
*/
esp_err_t sdio_slave_recv_packet(sdio_slave_buf_handle_t* handle_ret, TickType_t wait);
/** Get received data if exist. The driver returns the ownership of the buffer to the app.
*
* @param handle_ret Handle to the buffer holding received data. Use this handle in ``sdio_slave_recv_load_buf`` to receive in the same buffer again.
* @param[out] out_addr Output of the start address, set to NULL if not needed.
* @param[out] out_len Actual length of the data in the buffer, set to NULL if not needed.
* @param wait Time to wait before data received.
*
* @note Call ``sdio_slave_load_buf`` with the handle to re-load the buffer onto the link list, and receive with the same buffer again.
* The address and length of the buffer got here is the same as got from `sdio_slave_get_buffer`.
*
* @return
* - ESP_ERR_INVALID_ARG if handle_ret is NULL
* - ESP_ERR_TIMEOUT if timeout before receiving new data
* - ESP_OK if success
*/
esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **out_addr, size_t *out_len, TickType_t wait);
/** Retrieve the buffer corresponding to a handle.
*
* @param handle Handle to get the buffer.
* @param len_o Output of buffer length
*
* @return buffer address if success, otherwise NULL.
*/
uint8_t* sdio_slave_recv_get_buf(sdio_slave_buf_handle_t handle, size_t *len_o);
/*---------------------------------------------------------------------------
* Send
*--------------------------------------------------------------------------*/
/** Put a new sending transfer into the send queue. The driver takes ownership of the buffer until the buffer is returned by
* ``sdio_slave_send_get_finished`` after the transaction is finished.
*
* @param addr Address for data to be sent. The buffer should be DMA capable and 32-bit aligned.
* @param len Length of the data, should not be longer than 4092 bytes (may support longer in the future).
* @param arg Argument to returned in ``sdio_slave_send_get_finished``. The argument can be used to indicate which transaction is done,
* or as a parameter for a callback. Set to NULL if not needed.
* @param wait Time to wait if the buffer is full.
*
* @return
* - ESP_ERR_INVALID_ARG if the length is not greater than 0.
* - ESP_ERR_TIMEOUT if the queue is still full until timeout.
* - ESP_OK if success.
*/
esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait);
/** Return the ownership of a finished transaction.
* @param out_arg Argument of the finished transaction. Set to NULL if unused.
* @param wait Time to wait if there's no finished sending transaction.
*
* @return ESP_ERR_TIMEOUT if no transaction finished, or ESP_OK if succeed.
*/
esp_err_t sdio_slave_send_get_finished(void** out_arg, TickType_t wait);
/** Start a new sending transfer, and wait for it (blocked) to be finished.
*
* @param addr Start address of the buffer to send
* @param len Length of buffer to send.
*
* @return
* - ESP_ERR_INVALID_ARG if the length of descriptor is not greater than 0.
* - ESP_ERR_TIMEOUT if the queue is full or host do not start a transfer before timeout.
* - ESP_OK if success.
*/
esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len);
/*---------------------------------------------------------------------------
* Host
*--------------------------------------------------------------------------*/
/** Read the spi slave register shared with host.
*
* @param pos register address, 0-27 or 32-63.
*
* @note register 28 to 31 are reserved for interrupt vector.
*
* @return value of the register.
*/
uint8_t sdio_slave_read_reg(int pos);
/** Write the spi slave register shared with host.
*
* @param pos register address, 0-11, 14-15, 18-19, 24-27 and 32-63, other address are reserved.
* @param reg the value to write.
*
* @note register 29 and 31 are used for interrupt vector.
*
* @return ESP_ERR_INVALID_ARG if address wrong, otherwise ESP_OK.
*/
esp_err_t sdio_slave_write_reg(int pos, uint8_t reg);
/** Get the interrupt enable for host.
*
* @return the interrupt mask.
*/
sdio_slave_hostint_t sdio_slave_get_host_intena(void);
/** Set the interrupt enable for host.
*
* @param mask Enable mask for host interrupt.
*/
void sdio_slave_set_host_intena(sdio_slave_hostint_t mask);
/** Interrupt the host by general purpose interrupt.
*
* @param pos Interrupt num, 0-7.
*
* @return
* - ESP_ERR_INVALID_ARG if interrupt num error
* - ESP_OK otherwise
*/
esp_err_t sdio_slave_send_host_int(uint8_t pos);
/** Clear general purpose interrupt to host.
*
* @param mask Interrupt bits to clear, by bit mask.
*/
void sdio_slave_clear_host_int(sdio_slave_hostint_t mask);
/** Wait for general purpose interrupt from host.
*
* @param pos Interrupt source number to wait for.
* is set.
* @param wait Time to wait before interrupt triggered.
*
* @note this clears the interrupt at the same time.
*
* @return ESP_OK if success, ESP_ERR_TIMEOUT if timeout.
*/
esp_err_t sdio_slave_wait_int(int pos, TickType_t wait);
#ifdef __cplusplus
}
#endif
-127
View File
@@ -1,127 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "hal/sdm_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of Sigma Delta channel handle
*/
typedef struct sdm_channel_t *sdm_channel_handle_t;
/**
* @brief Sigma Delta channel configuration
*/
typedef struct {
int gpio_num; /*!< GPIO number */
sdm_clock_source_t clk_src; /*!< Clock source */
uint32_t sample_rate_hz; /*!< Over sample rate in Hz, it determines the frequency of the carrier pulses */
struct {
uint32_t invert_out: 1; /*!< Whether to invert the output signal */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
} flags; /*!< Extra flags */
} sdm_config_t;
/**
* @brief Create a new Sigma Delta channel
*
* @param[in] config SDM configuration
* @param[out] ret_chan Returned SDM channel handle
* @return
* - ESP_OK: Create SDM channel successfully
* - ESP_ERR_INVALID_ARG: Create SDM channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create SDM channel failed because out of memory
* - ESP_ERR_NOT_FOUND: Create SDM channel failed because all channels are used up and no more free one
* - ESP_FAIL: Create SDM channel failed because of other error
*/
esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_chan);
/**
* @brief Delete the Sigma Delta channel
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Delete the SDM channel successfully
* - ESP_ERR_INVALID_ARG: Delete the SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete the SDM channel failed because the channel is not in init state
* - ESP_FAIL: Delete the SDM channel failed because of other error
*/
esp_err_t sdm_del_channel(sdm_channel_handle_t chan);
/**
* @brief Enable the Sigma Delta channel
*
* @note This function will transit the channel state from init to enable.
* @note This function will acquire a PM lock, if a specific source clock (e.g. APB) is selected in the `sdm_config_t`, while `CONFIG_PM_ENABLE` is enabled.
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Enable SDM channel successfully
* - ESP_ERR_INVALID_ARG: Enable SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable SDM channel failed because the channel is already enabled
* - ESP_FAIL: Enable SDM channel failed because of other error
*/
esp_err_t sdm_channel_enable(sdm_channel_handle_t chan);
/**
* @brief Disable the Sigma Delta channel
*
* @note This function will do the opposite work to the `sdm_channel_enable()`
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Disable SDM channel successfully
* - ESP_ERR_INVALID_ARG: Disable SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable SDM channel failed because the channel is not enabled yet
* - ESP_FAIL: Disable SDM channel failed because of other error
*/
esp_err_t sdm_channel_disable(sdm_channel_handle_t chan);
/**
* @brief Set the pulse density of the PDM output signal.
*
* @note The raw output signal requires a low-pass filter to restore it into analog voltage,
* the restored analog output voltage could be Vout = VDD_IO / 256 * density + VDD_IO / 2
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_SDM_CTRL_FUNC_IN_IRAM` is on,
* so that it's allowed to be executed when Cache is disabled
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @param[in] density Quantized pulse density of the PDM output signal, ranges from -128 to 127.
* But the range of [-90, 90] can provide a better randomness.
* @return
* - ESP_OK: Set pulse density successfully
* - ESP_ERR_INVALID_ARG: Set pulse density failed because of invalid argument
* - ESP_FAIL: Set pulse density failed because of other error
*/
esp_err_t sdm_channel_set_pulse_density(sdm_channel_handle_t chan, int8_t density);
/**
* @brief The alias function of `sdm_channel_set_pulse_density`, it decides the pulse density of the output signal
*
* @note `sdm_channel_set_pulse_density` has a more appropriate name compare this
* alias function, suggest to turn to `sdm_channel_set_pulse_density` instead
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @param[in] duty Actually it's the quantized pulse density of the PDM output signal
*
* @return
* - ESP_OK: Set duty cycle successfully
* - ESP_ERR_INVALID_ARG: Set duty cycle failed because of invalid argument
* - ESP_FAIL: Set duty cycle failed because of other error
*/
esp_err_t sdm_channel_set_duty(sdm_channel_handle_t chan, int8_t duty);
#ifdef __cplusplus
}
#endif
@@ -1,539 +0,0 @@
/*
* SPDX-FileCopyrightText: 2006 Uwe Stuehler <uwe@openbsd.org>
*
* SPDX-License-Identifier: ISC
*
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
*/
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include <limits.h>
#ifdef __cplusplus
extern "C" {
#endif
/* MMC commands */ /* response type */
#define MMC_GO_IDLE_STATE 0 /* R0 */
#define MMC_SEND_OP_COND 1 /* R3 */
#define MMC_ALL_SEND_CID 2 /* R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
#define MMC_SWITCH 6 /* R1B */
#define MMC_SELECT_CARD 7 /* R1 */
#define MMC_SEND_EXT_CSD 8 /* R1 */
#define MMC_SEND_CSD 9 /* R2 */
#define MMC_SEND_CID 10 /* R1 */
#define MMC_READ_DAT_UNTIL_STOP 11 /* R1 */
#define MMC_STOP_TRANSMISSION 12 /* R1B */
#define MMC_SEND_STATUS 13 /* R1 */
#define MMC_SET_BLOCKLEN 16 /* R1 */
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* R1 */
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
#define MMC_ERASE_GROUP_START 35 /* R1 */
#define MMC_ERASE_GROUP_END 36 /* R1 */
#define MMC_ERASE 38 /* R1B */
#define MMC_APP_CMD 55 /* R1 */
/* SD commands */ /* response type */
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_SWITCH_FUNC 6 /* R1 */
#define SD_SEND_IF_COND 8 /* R7 */
#define SD_ERASE_GROUP_START 32 /* R1 */
#define SD_ERASE_GROUP_END 33 /* R1 */
#define SD_READ_OCR 58 /* R3 */
#define SD_CRC_ON_OFF 59 /* R1 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
#define SD_APP_SD_STATUS 13 /* R2 */
#define SD_APP_OP_COND 41 /* R3 */
#define SD_APP_SEND_SCR 51 /* R1 */
/* SD IO commands */
#define SD_IO_SEND_OP_COND 5 /* R4 */
#define SD_IO_RW_DIRECT 52 /* R5 */
#define SD_IO_RW_EXTENDED 53 /* R5 */
/* OCR bits */
#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */
#define MMC_OCR_ACCESS_MODE_MASK 0x60000000 /* bits 30:29 */
#define MMC_OCR_SECTOR_MODE (1<<30)
#define MMC_OCR_BYTE_MODE (1<<29)
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
#define MMC_OCR_3_2V_3_3V (1<<20)
#define MMC_OCR_3_1V_3_2V (1<<19)
#define MMC_OCR_3_0V_3_1V (1<<18)
#define MMC_OCR_2_9V_3_0V (1<<17)
#define MMC_OCR_2_8V_2_9V (1<<16)
#define MMC_OCR_2_7V_2_8V (1<<15)
#define MMC_OCR_2_6V_2_7V (1<<14)
#define MMC_OCR_2_5V_2_6V (1<<13)
#define MMC_OCR_2_4V_2_5V (1<<12)
#define MMC_OCR_2_3V_2_4V (1<<11)
#define MMC_OCR_2_2V_2_3V (1<<10)
#define MMC_OCR_2_1V_2_2V (1<<9)
#define MMC_OCR_2_0V_2_1V (1<<8)
#define MMC_OCR_1_65V_1_95V (1<<7)
#define SD_OCR_SDHC_CAP (1<<30)
#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
/* SD mode R1 response type bits */
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
#define MMC_R1_SWITCH_ERROR (1<<7) /* switch command did not succeed */
#define MMC_R1_CURRENT_STATE_POS (9)
#define MMC_R1_CURRENT_STATE_MASK (0x1E00)/* card current state */
#define MMC_R1_CURRENT_STATE_TRAN (4)
/* SPI mode R1 response type bits */
#define SD_SPI_R1_IDLE_STATE (1<<0)
#define SD_SPI_R1_ERASE_RST (1<<1)
#define SD_SPI_R1_ILLEGAL_CMD (1<<2)
#define SD_SPI_R1_CMD_CRC_ERR (1<<3)
#define SD_SPI_R1_ERASE_SEQ_ERR (1<<4)
#define SD_SPI_R1_ADDR_ERR (1<<5)
#define SD_SPI_R1_PARAM_ERR (1<<6)
#define SD_SPI_R1_NO_RESPONSE (1<<7)
#define SDIO_R1_FUNC_NUM_ERR (1<<4)
/* SPI mode R2 response type bits.
* The first byte is the same as for R1.
* The bits below belong to the second byte.
* Bits 10, 11, 12, 15 can also be reported in data error token of a read command response.
*/
#define SD_SPI_R2_CARD_LOCKED (1<<8) /* Set when the card is locked by the user */
#define SD_SPI_R2_UNLOCK_FAILED (1<<9) /* Host attempts to erase a write-protected sector or makes an error during card lock/unlock operation */
#define SD_SPI_R2_ERROR (1<<10) /* A general or an unknown error occurred during the operation */
#define SD_SPI_R2_CC_ERROR (1<<11) /* Internal card controller error */
#define SD_SPI_R2_ECC_FAILED (1<<12) /* Card internal ECC was applied but failed to correct the data */
#define SD_SPI_R2_WP_VIOLATION (1<<13) /* The command tried to write a write-protected block */
#define SD_SPI_R2_ERASE_PARAM (1<<14) /* An invalid selection for erase, sectors or groups */
#define SD_SPI_R2_OUT_OF_RANGE (1<<15) /* The command argument was out of the allowed range for this card */
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R1(resp) ((resp)[0])
#define MMC_R3(resp) ((resp)[0])
#define MMC_R4(resp) ((resp)[0])
#define MMC_R5(resp) ((resp)[0])
#define SD_R6(resp) ((resp)[0])
#define MMC_R1_CURRENT_STATE(resp) (((resp)[0] >> 9) & 0xf)
/* SPI mode response decoding */
#define SD_SPI_R1(resp) ((resp)[0] & 0xff)
#define SD_SPI_R2(resp) ((resp)[0] & 0xffff)
#define SD_SPI_R3(resp) ((resp)[0])
#define SD_SPI_R7(resp) ((resp)[0])
/* SPI mode data response decoding */
#define SD_SPI_DATA_RSP_VALID(resp_byte) (((resp_byte)&0x11)==0x1)
#define SD_SPI_DATA_RSP(resp_byte) (((resp_byte)>>1)&0x7)
#define SD_SPI_DATA_ACCEPTED 0x2
#define SD_SPI_DATA_CRC_ERROR 0x5
#define SD_SPI_DATA_WR_ERROR 0x6
/* RCA argument and response */
#define MMC_ARG_RCA(rca) ((rca) << 16)
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
/* bus width argument */
#define SD_ARG_BUS_WIDTH_1 0
#define SD_ARG_BUS_WIDTH_4 2
/* EXT_CSD fields */
#define EXT_CSD_SANITIZE_START 165 /* WO */
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
#define EXT_CSD_BUS_WIDTH 183 /* WO */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_POWER_CLASS 187 /* R/W */
#define EXT_CSD_CMD_SET 191 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
#define EXT_CSD_SEC_COUNT 212 /* RO */
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
#define EXT_CSD_S_CMD_SET 504 /* RO */
/* EXT_CSD field definitions */
#define EXT_CSD_REV_1_6 6 /* Revision 1.6 (for MMC v4.5, v4.51) */
#define EXT_CSD_CMD_SET_NORMAL (1U << 0)
#define EXT_CSD_CMD_SET_SECURE (1U << 1)
#define EXT_CSD_CMD_SET_CPSECURE (1U << 2)
/* EXT_CSD_HS_TIMING */
#define EXT_CSD_HS_TIMING_BC 0
#define EXT_CSD_HS_TIMING_HS 1
#define EXT_CSD_HS_TIMING_HS200 2
#define EXT_CSD_HS_TIMING_HS400 3
/* EXT_CSD_BUS_WIDTH */
#define EXT_CSD_BUS_WIDTH_1 0
#define EXT_CSD_BUS_WIDTH_4 1
#define EXT_CSD_BUS_WIDTH_8 2
#define EXT_CSD_BUS_WIDTH_4_DDR 5
#define EXT_CSD_BUS_WIDTH_8_DDR 6
/* EXT_CSD_CARD_TYPE */
/* The only currently valid values for this field are 0x01, 0x03, 0x07,
* 0x0B and 0x0F. */
#define EXT_CSD_CARD_TYPE_F_26M (1 << 0) /* SDR at "rated voltages */
#define EXT_CSD_CARD_TYPE_F_52M (1 << 1) /* SDR at "rated voltages */
#define EXT_CSD_CARD_TYPE_F_52M_1_8V (1 << 2) /* DDR, 1.8V or 3.3V I/O */
#define EXT_CSD_CARD_TYPE_F_52M_1_2V (1 << 3) /* DDR, 1.2V I/O */
#define EXT_CSD_CARD_TYPE_26M 0x01
#define EXT_CSD_CARD_TYPE_52M 0x03
#define EXT_CSD_CARD_TYPE_52M_V18 0x07
#define EXT_CSD_CARD_TYPE_52M_V12 0x0b
#define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f
/* EXT_CSD_SEC_FEATURE_SUPPORT */
#define EXT_CSD_SECURE_ER_EN (uint8_t)(1 << 0)
#define EXT_CSD_SEC_BD_BLK_EN (uint8_t)(1 << 2)
#define EXT_CSD_SEC_GB_CL_EN (uint8_t)(1 << 4)
#define EXT_CSD_SEC_SANITIZE (uint8_t)(1 << 6)
/* EXT_CSD MMC */
#define EXT_CSD_MMC_SIZE 512
/* MMC_SWITCH access mode */
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/* MMC R2 response (CSD) */
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define MMC_CSD_CSDVER_1_0 1
#define MMC_CSD_CSDVER_2_0 2
#define MMC_CSD_CSDVER_EXT_CSD 3
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
(MMC_CSD_C_SIZE_MULT((resp))+2))
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
/* MMC v1 R2 response (CID) */
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
(pnm)[7] = '\0'; \
} while (0)
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
/* MMC v2 R2 response (CID) */
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = '\0'; \
} while (0)
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
/* SD R2 response (CSD) */
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define SD_CSD_CSDVER_1_0 0
#define SD_CSD_CSDVER_2_0 1
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define SD_CSD_TAAC_1_5_MSEC 0x26
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define SD_CSD_SPEED_25_MHZ 0x32
#define SD_CSD_SPEED_50_MHZ 0x5a
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
#define SD_CSD_CCC_BASIC (1 << 0) /* basic */
#define SD_CSD_CCC_BR (1 << 2) /* block read */
#define SD_CSD_CCC_BW (1 << 4) /* block write */
#define SD_CSD_CCC_ERASE (1 << 5) /* erase */
#define SD_CSD_CCC_WP (1 << 6) /* write protection */
#define SD_CSD_CCC_LC (1 << 7) /* lock card */
#define SD_CSD_CCC_AS (1 << 8) /*application specific*/
#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */
#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
(SD_CSD_C_SIZE_MULT((resp))+2))
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
#define SD_CSD_VDD_RW_CURR_100mA 0x7
#define SD_CSD_VDD_RW_CURR_80mA 0x6
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
#define SD_CSD_RW_BL_LEN_2G 0xa
#define SD_CSD_RW_BL_LEN_1G 0x9
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
/* SD R2 response (CID) */
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
#define SD_CID_PNM_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = '\0'; \
} while (0)
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
/* SCR (SD Configuration Register) */
#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4)
#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */
#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4)
#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */
#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */
#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */
#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1)
#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3)
#define SCR_SD_SECURITY_NONE 0 /* no security */
#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */
#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */
#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4)
#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */
#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */
#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1)
#define SCR_EX_SECURITY(scr) MMC_RSP_BITS((scr), 43, 4)
#define SCR_SD_SPEC4(scr) MMC_RSP_BITS((scr), 42, 1)
#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 34, 8)
#define SCR_CMD_SUPPORT_CMD23(scr) MMC_RSP_BITS((scr), 33, 1)
#define SCR_CMD_SUPPORT_CMD20(scr) MMC_RSP_BITS((scr), 32, 1)
#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32)
/* SSR (SD Status Register) */
#define SSR_DAT_BUS_WIDTH(ssr) MMC_RSP_BITS((ssr), 510, 2)
#define SSR_AU_SIZE(ssr) MMC_RSP_BITS((ssr), 428, 4)
#define SSR_ERASE_SIZE(ssr) MMC_RSP_BITS((ssr), 408, 16)
#define SSR_ERASE_TIMEOUT(ssr) MMC_RSP_BITS((ssr), 402, 6)
#define SSR_ERASE_OFFSET(ssr) MMC_RSP_BITS((ssr), 400, 2)
#define SSR_DISCARD_SUPPORT(ssr) MMC_RSP_BITS((ssr), 313, 1)
#define SSR_FULE_SUPPORT(ssr) MMC_RSP_BITS((ssr), 312, 1)
/* Max supply current in SWITCH_FUNC response (in mA) */
#define SD_SFUNC_I_MAX(status) (MMC_RSP_BITS((uint32_t *)(status), 496, 16))
/* Supported flags in SWITCH_FUNC response */
#define SD_SFUNC_SUPPORTED(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 400 + (group - 1) * 16, 16))
/* Selected function in SWITCH_FUNC response */
#define SD_SFUNC_SELECTED(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 376 + (group - 1) * 4, 4))
/* Busy flags in SWITCH_FUNC response */
#define SD_SFUNC_BUSY(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 272 + (group - 1) * 16, 16))
/* Version of SWITCH_FUNC response */
#define SD_SFUNC_VER(status) (MMC_RSP_BITS((uint32_t *)(status), 368, 8))
#define SD_SFUNC_GROUP_MAX 6
#define SD_SFUNC_FUNC_MAX 15
#define SD_ACCESS_MODE 1 /* Function group 1, Access Mode */
#define SD_ACCESS_MODE_SDR12 0 /* 25 MHz clock */
#define SD_ACCESS_MODE_SDR25 1 /* 50 MHz clock */
#define SD_ACCESS_MODE_SDR50 2 /* UHS-I, 100 MHz clock */
#define SD_ACCESS_MODE_SDR104 3 /* UHS-I, 208 MHz clock */
#define SD_ACCESS_MODE_DDR50 4 /* UHS-I, 50 MHz clock, DDR */
#define SD_SSR_SIZE 64 /* SD status register */
/**
* @brief Extract up to 32 sequential bits from an array of 32-bit words
*
* Bits within the word are numbered in the increasing order from LSB to MSB.
*
* As an example, consider 2 32-bit words:
*
* 0x01234567 0x89abcdef
*
* On a little-endian system, the bytes are stored in memory as follows:
*
* 67 45 23 01 ef cd ab 89
*
* MMC_RSP_BITS will extact bits as follows:
*
* start=0 len=4 -> result=0x00000007
* start=0 len=12 -> result=0x00000567
* start=28 len=8 -> result=0x000000f0
* start=59 len=5 -> result=0x00000011
*
* @param src array of words to extract bits from
* @param start index of the first bit to extract
* @param len number of bits to extract, 1 to 32
* @return 32-bit word where requested bits start from LSB
*/
static inline uint32_t MMC_RSP_BITS(uint32_t *src, int start, int len)
{
uint32_t mask = (len % 32 == 0) ? UINT_MAX : UINT_MAX >> (32 - (len % 32));
size_t word = start / 32;
size_t shift = start % 32;
uint32_t right = src[word] >> shift;
uint32_t left = (len + shift <= 32) ? 0 : src[word + 1] << ((32 - shift) % 32);
return (left | right) & mask;
}
/* SD R4 response (IO OCR) */
#define SD_IO_OCR_MEM_READY (1<<31)
#define SD_IO_OCR_NUM_FUNCTIONS(ocr) (((ocr) >> 28) & 0x7)
#define SD_IO_OCR_MEM_PRESENT (1<<27)
#define SD_IO_OCR_MASK 0x00fffff0
/* CMD52 arguments */
#define SD_ARG_CMD52_READ (0<<31)
#define SD_ARG_CMD52_WRITE (1<<31)
#define SD_ARG_CMD52_FUNC_SHIFT 28
#define SD_ARG_CMD52_FUNC_MASK 0x7
#define SD_ARG_CMD52_EXCHANGE (1<<27)
#define SD_ARG_CMD52_REG_SHIFT 9
#define SD_ARG_CMD52_REG_MASK 0x1ffff
#define SD_ARG_CMD52_DATA_SHIFT 0
#define SD_ARG_CMD52_DATA_MASK 0xff
#define SD_R5_DATA(resp) ((resp)[0] & 0xff)
/* CMD53 arguments */
#define SD_ARG_CMD53_READ (0<<31)
#define SD_ARG_CMD53_WRITE (1<<31)
#define SD_ARG_CMD53_FUNC_SHIFT 28
#define SD_ARG_CMD53_FUNC_MASK 0x7
#define SD_ARG_CMD53_BLOCK_MODE (1<<27)
#define SD_ARG_CMD53_INCREMENT (1<<26)
#define SD_ARG_CMD53_REG_SHIFT 9
#define SD_ARG_CMD53_REG_MASK 0x1ffff
#define SD_ARG_CMD53_LENGTH_SHIFT 0
#define SD_ARG_CMD53_LENGTH_MASK 0x1ff
#define SD_ARG_CMD53_LENGTH_MAX 512
/* Card Common Control Registers (CCCR) */
#define SD_IO_CCCR_START 0x00000
#define SD_IO_CCCR_SIZE 0x100
#define SD_IO_CCCR_FN_ENABLE 0x02
#define SD_IO_CCCR_FN_READY 0x03
#define SD_IO_CCCR_INT_ENABLE 0x04
#define SD_IO_CCCR_INT_PENDING 0x05
#define SD_IO_CCCR_CTL 0x06
#define CCCR_CTL_RES (1<<3)
#define SD_IO_CCCR_BUS_WIDTH 0x07
#define CCCR_BUS_WIDTH_1 (0<<0)
#define CCCR_BUS_WIDTH_4 (2<<0)
#define CCCR_BUS_WIDTH_8 (3<<0)
#define CCCR_BUS_WIDTH_ECSI (1<<5)
#define SD_IO_CCCR_CARD_CAP 0x08
#define CCCR_CARD_CAP_LSC BIT(6)
#define CCCR_CARD_CAP_4BLS BIT(7)
#define SD_IO_CCCR_CISPTR 0x09
#define SD_IO_CCCR_BLKSIZEL 0x10
#define SD_IO_CCCR_BLKSIZEH 0x11
#define SD_IO_CCCR_HIGHSPEED 0x13
#define CCCR_HIGHSPEED_SUPPORT BIT(0)
#define CCCR_HIGHSPEED_ENABLE BIT(1)
/* Function Basic Registers (FBR) */
#define SD_IO_FBR_START 0x00100
#define SD_IO_FBR_SIZE 0x00700
/* Card Information Structure (CIS) */
#define SD_IO_CIS_START 0x01000
#define SD_IO_CIS_SIZE 0x17000
/* CIS tuple codes (based on PC Card 16) */
#define CISTPL_CODE_NULL 0x00
#define CISTPL_CODE_DEVICE 0x01
#define CISTPL_CODE_CHKSUM 0x10
#define CISTPL_CODE_VERS1 0x15
#define CISTPL_CODE_ALTSTR 0x16
#define CISTPL_CODE_CONFIG 0x1A
#define CISTPL_CODE_CFTABLE_ENTRY 0x1B
#define CISTPL_CODE_MANFID 0x20
#define CISTPL_CODE_FUNCID 0x21
#define TPLFID_FUNCTION_SDIO 0x0c
#define CISTPL_CODE_FUNCE 0x22
#define CISTPL_CODE_VENDER_BEGIN 0x80
#define CISTPL_CODE_VENDER_END 0x8F
#define CISTPL_CODE_SDIO_STD 0x91
#define CISTPL_CODE_SDIO_EXT 0x92
#define CISTPL_CODE_END 0xFF
/* Timing */
#define SDMMC_TIMING_LEGACY 0
#define SDMMC_TIMING_HIGHSPEED 1
#define SDMMC_TIMING_MMC_DDR52 2
#ifdef __cplusplus
}
#endif
@@ -1,284 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#if SOC_SDMMC_HOST_SUPPORTED
#include <stdint.h>
#include <stddef.h>
#include "esp_err.h"
#include "sdmmc_types.h"
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SDMMC_HOST_SLOT_0 0 ///< SDMMC slot 0
#define SDMMC_HOST_SLOT_1 1 ///< SDMMC slot 1
/**
* @brief Default sdmmc_host_t structure initializer for SDMMC peripheral
*
* Uses SDMMC peripheral, with 4-bit mode enabled, and max frequency set to 20MHz
*/
#define SDMMC_HOST_DEFAULT() {\
.flags = SDMMC_HOST_FLAG_8BIT | \
SDMMC_HOST_FLAG_4BIT | \
SDMMC_HOST_FLAG_1BIT | \
SDMMC_HOST_FLAG_DDR, \
.slot = SDMMC_HOST_SLOT_1, \
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
.io_voltage = 3.3f, \
.init = &sdmmc_host_init, \
.set_bus_width = &sdmmc_host_set_bus_width, \
.get_bus_width = &sdmmc_host_get_slot_width, \
.set_bus_ddr_mode = &sdmmc_host_set_bus_ddr_mode, \
.set_card_clk = &sdmmc_host_set_card_clk, \
.do_transaction = &sdmmc_host_do_transaction, \
.deinit = &sdmmc_host_deinit, \
.io_int_enable = sdmmc_host_io_int_enable, \
.io_int_wait = sdmmc_host_io_int_wait, \
.command_timeout_ms = 0, \
.get_real_freq = &sdmmc_host_get_real_freq \
}
/**
* Extra configuration for SDMMC peripheral slot
*/
typedef struct {
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
gpio_num_t clk; ///< GPIO number of CLK signal.
gpio_num_t cmd; ///< GPIO number of CMD signal.
gpio_num_t d0; ///< GPIO number of D0 signal.
gpio_num_t d1; ///< GPIO number of D1 signal.
gpio_num_t d2; ///< GPIO number of D2 signal.
gpio_num_t d3; ///< GPIO number of D3 signal.
gpio_num_t d4; ///< GPIO number of D4 signal. Ignored in 1- or 4- line mode.
gpio_num_t d5; ///< GPIO number of D5 signal. Ignored in 1- or 4- line mode.
gpio_num_t d6; ///< GPIO number of D6 signal. Ignored in 1- or 4- line mode.
gpio_num_t d7; ///< GPIO number of D7 signal. Ignored in 1- or 4- line mode.
#endif // SOC_SDMMC_USE_GPIO_MATRIX
union {
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
gpio_num_t cd; ///< GPIO number of card detect signal; shorter name.
};
union {
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
gpio_num_t wp; ///< GPIO number of write protect signal; shorter name.
};
uint8_t width; ///< Bus width used by the slot (might be less than the max width supported)
uint32_t flags; ///< Features used by this slot
#define SDMMC_SLOT_FLAG_INTERNAL_PULLUP BIT(0)
/**< Enable internal pullups on enabled pins. The internal pullups
are insufficient however, please make sure external pullups are
connected on the bus. This is for debug / example purpose only.
*/
} sdmmc_slot_config_t;
#define SDMMC_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used
#define SDMMC_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used
#define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the maximum possible width for the slot
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
/**
* Macro defining default configuration of SDMMC host slot
*/
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
.clk = GPIO_NUM_14, \
.cmd = GPIO_NUM_15, \
.d0 = GPIO_NUM_2, \
.d1 = GPIO_NUM_4, \
.d2 = GPIO_NUM_12, \
.d3 = GPIO_NUM_13, \
.d4 = GPIO_NUM_33, \
.d5 = GPIO_NUM_34, \
.d6 = GPIO_NUM_35, \
.d7 = GPIO_NUM_36, \
.cd = SDMMC_SLOT_NO_CD, \
.wp = SDMMC_SLOT_NO_WP, \
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
.flags = 0, \
}
#else // SOC_SDMMC_USE_GPIO_MATRIX
/**
* Macro defining default configuration of SDMMC host slot
*/
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
.cd = SDMMC_SLOT_NO_CD, \
.wp = SDMMC_SLOT_NO_WP, \
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
.flags = 0, \
}
#endif // SOC_SDMMC_USE_GPIO_MATRIX
/**
* @brief Initialize SDMMC host peripheral
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if sdmmc_host_init was already called
* - ESP_ERR_NO_MEM if memory can not be allocated
*/
esp_err_t sdmmc_host_init(void);
/**
* @brief Initialize given slot of SDMMC peripheral
*
* On the ESP32, SDMMC peripheral has two slots:
* - Slot 0: 8-bit wide, maps to HS1_* signals in PIN MUX
* - Slot 1: 4-bit wide, maps to HS2_* signals in PIN MUX
*
* Card detect and write protect signals can be routed to
* arbitrary GPIOs using GPIO matrix.
*
* @note This function is not thread safe
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param slot_config additional configuration for the slot
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if host has not been initialized using sdmmc_host_init
*/
esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config);
/**
* @brief Select bus width to be used for data transfer
*
* SD/MMC card must be initialized prior to this command, and a command to set
* bus width has to be sent to the card (e.g. SD_APP_SET_BUS_WIDTH)
*
* @note This function is not thread safe
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param width bus width (1, 4, or 8 for slot 0; 1 or 4 for slot 1)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if slot number or width is not valid
*/
esp_err_t sdmmc_host_set_bus_width(int slot, size_t width);
/**
* @brief Get bus width configured in ``sdmmc_host_init_slot`` to be used for data transfer
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @return configured bus width of the specified slot.
*/
size_t sdmmc_host_get_slot_width(int slot);
/**
* @brief Set card clock frequency
*
* Currently only integer fractions of 40MHz clock can be used.
* For High Speed cards, 40MHz can be used.
* For Default Speed cards, 20MHz can be used.
*
* @note This function is not thread safe
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param freq_khz card clock frequency, in kHz
* @return
* - ESP_OK on success
* - other error codes may be returned in the future
*/
esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz);
/**
* @brief Enable or disable DDR mode of SD interface
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param ddr_enabled enable or disable DDR mode
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if DDR mode is not supported on this slot
*/
esp_err_t sdmmc_host_set_bus_ddr_mode(int slot, bool ddr_enabled);
/**
* @brief Send command to the card and get response
*
* This function returns when command is sent and response is received,
* or data is transferred, or timeout occurs.
*
* @note This function is not thread safe w.r.t. init/deinit functions,
* and bus width/clock speed configuration functions. Multiple tasks
* can call sdmmc_host_do_transaction as long as other sdmmc_host_*
* functions are not called.
*
* @attention Data buffer passed in cmdinfo->data must be in DMA capable memory
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param cmdinfo pointer to structure describing command and data to transfer
* @return
* - ESP_OK on success
* - ESP_ERR_TIMEOUT if response or data transfer has timed out
* - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
* - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
* - ESP_ERR_INVALID_SIZE if the size of data transfer is not valid in SD protocol
* - ESP_ERR_INVALID_ARG if the data buffer is not in DMA capable memory
*/
esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo);
/**
* @brief Enable IO interrupts
*
* This function configures the host to accept SDIO interrupts.
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @return returns ESP_OK, other errors possible in the future
*/
esp_err_t sdmmc_host_io_int_enable(int slot);
/**
* @brief Block until an SDIO interrupt is received, or timeout occurs
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param timeout_ticks number of RTOS ticks to wait for the interrupt
* @return
* - ESP_OK on success (interrupt received)
* - ESP_ERR_TIMEOUT if the interrupt did not occur within timeout_ticks
*/
esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks);
/**
* @brief Disable SDMMC host and release allocated resources
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if sdmmc_host_init function has not been called
*/
esp_err_t sdmmc_host_deinit(void);
/**
* @brief Provides a real frequency used for an SD card installed on specific slot
* of SD/MMC host controller
*
* This function calculates real working frequency given by current SD/MMC host
* controller setup for required slot: it reads associated host and card dividers
* from corresponding SDMMC registers, calculates respective frequency and stores
* the value into the 'real_freq_khz' parameter
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param[out] real_freq_khz output parameter for the result frequency (in kHz)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG on real_freq_khz == NULL or invalid slot number used
*/
esp_err_t sdmmc_host_get_real_freq(int slot, int* real_freq_khz);
#ifdef __cplusplus
}
#endif
#endif //SOC_SDMMC_HOST_SUPPORTED
@@ -1,242 +0,0 @@
/*
* SPDX-FileCopyrightText: 2006 Uwe Stuehler <uwe@openbsd.org>
*
* SPDX-License-Identifier: ISC
*
* SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
*/
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Decoded values from SD card Card Specific Data register
*/
typedef struct {
int csd_ver; /*!< CSD structure format */
int mmc_ver; /*!< MMC version (for CID format) */
int capacity; /*!< total number of sectors */
int sector_size; /*!< sector size in bytes */
int read_block_len; /*!< block length for reads */
int card_command_class; /*!< Card Command Class for SD */
int tr_speed; /*!< Max transfer speed */
} sdmmc_csd_t;
/**
* Decoded values from SD card Card IDentification register
*/
typedef struct {
int mfg_id; /*!< manufacturer identification number */
int oem_id; /*!< OEM/product identification number */
char name[8]; /*!< product name (MMC v1 has the longest) */
int revision; /*!< product revision */
int serial; /*!< product serial number */
int date; /*!< manufacturing date */
} sdmmc_cid_t;
/**
* Decoded values from SD Configuration Register
* Note: When new member is added, update reserved bits accordingly
*/
typedef struct {
uint32_t sd_spec: 4; /*!< SD Physical layer specification version, reported by card */
uint32_t erase_mem_state: 1; /*!< data state on card after erase whether 0 or 1 (card vendor dependent) */
uint32_t bus_width: 4; /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */
uint32_t reserved: 23; /*!< reserved for future expansion */
uint32_t rsvd_mnf; /*!< reserved for manufacturer usage */
} sdmmc_scr_t;
/**
* Decoded values from SD Status Register
* Note: When new member is added, update reserved bits accordingly
*/
typedef struct {
uint32_t alloc_unit_kb: 16; /*!< Allocation unit of the card, in multiples of kB (1024 bytes) */
uint32_t erase_size_au: 16; /*!< Erase size for the purpose of timeout calculation, in multiples of allocation unit */
uint32_t cur_bus_width: 2; /*!< SD current bus width */
uint32_t discard_support: 1; /*!< SD discard feature support */
uint32_t fule_support: 1; /*!< SD FULE (Full User Area Logical Erase) feature support */
uint32_t erase_timeout: 6; /*!< Timeout (in seconds) for erase of a single allocation unit */
uint32_t erase_offset: 2; /*!< Constant timeout offset (in seconds) for any erase operation */
uint32_t reserved: 20; /*!< reserved for future expansion */
} sdmmc_ssr_t;
/**
* Decoded values of Extended Card Specific Data
*/
typedef struct {
uint8_t rev; /*!< Extended CSD Revision */
uint8_t power_class; /*!< Power class used by the card */
uint8_t erase_mem_state; /*!< data state on card after erase whether 0 or 1 (card vendor dependent) */
uint8_t sec_feature; /*!< secure data management features supported by the card */
} sdmmc_ext_csd_t;
/**
* SD/MMC command response buffer
*/
typedef uint32_t sdmmc_response_t[4];
/**
* SD SWITCH_FUNC response buffer
*/
typedef struct {
uint32_t data[512 / 8 / sizeof(uint32_t)]; /*!< response data */
} sdmmc_switch_func_rsp_t;
/**
* SD/MMC command information
*/
typedef struct {
uint32_t opcode; /*!< SD or MMC command index */
uint32_t arg; /*!< SD/MMC command argument */
sdmmc_response_t response; /*!< response buffer */
void* data; /*!< buffer to send or read into */
size_t datalen; /*!< length of data buffer */
size_t blklen; /*!< block length */
int flags; /*!< see below */
/** @cond */
#define SCF_ITSDONE 0x0001 /*!< command is complete */
#define SCF_CMD(flags) ((flags) & 0x00f0)
#define SCF_CMD_AC 0x0000
#define SCF_CMD_ADTC 0x0010
#define SCF_CMD_BC 0x0020
#define SCF_CMD_BCR 0x0030
#define SCF_CMD_READ 0x0040 /*!< read command (data expected) */
#define SCF_RSP_BSY 0x0100
#define SCF_RSP_136 0x0200
#define SCF_RSP_CRC 0x0400
#define SCF_RSP_IDX 0x0800
#define SCF_RSP_PRESENT 0x1000
/* response types */
#define SCF_RSP_R0 0 /*!< none */
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
/* special flags */
#define SCF_WAIT_BUSY 0x2000 /*!< Wait for completion of card busy signal before returning */
/** @endcond */
esp_err_t error; /*!< error returned from transfer */
uint32_t timeout_ms; /*!< response timeout, in milliseconds */
} sdmmc_command_t;
/**
* SD/MMC Host description
*
* This structure defines properties of SD/MMC host and functions
* of SD/MMC host which can be used by upper layers.
*/
typedef struct {
uint32_t flags; /*!< flags defining host properties */
#define SDMMC_HOST_FLAG_1BIT BIT(0) /*!< host supports 1-line SD and MMC protocol */
#define SDMMC_HOST_FLAG_4BIT BIT(1) /*!< host supports 4-line SD and MMC protocol */
#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */
#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */
#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */
#define SDMMC_HOST_FLAG_DEINIT_ARG BIT(5) /*!< host `deinit` function called with the slot argument */
int slot; /*!< slot number, to be passed to host functions */
int max_freq_khz; /*!< max frequency supported by the host */
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
#define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */
#define SDMMC_FREQ_PROBING 400 /*!< SD/MMC probing speed */
#define SDMMC_FREQ_52M 52000 /*!< MMC 52MHz speed */
#define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */
float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */
esp_err_t (*init)(void); /*!< Host function to initialize the driver */
esp_err_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */
size_t (*get_bus_width)(int slot); /*!< host function to get bus width */
esp_err_t (*set_bus_ddr_mode)(int slot, bool ddr_enable); /*!< host function to set DDR mode */
esp_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
esp_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
union {
esp_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
esp_err_t (*deinit_p)(int slot); /*!< host function to deinitialize the driver, called with the `slot` */
};
esp_err_t (*io_int_enable)(int slot); /*!< Host function to enable SDIO interrupt line */
esp_err_t (*io_int_wait)(int slot, TickType_t timeout_ticks); /*!< Host function to wait for SDIO interrupt line to be active */
int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
esp_err_t (*get_real_freq)(int slot, int* real_freq); /*!< Host function to provide real working freq, based on SDMMC controller setup */
} sdmmc_host_t;
/**
* SD/MMC card information structure
*/
typedef struct {
sdmmc_host_t host; /*!< Host with which the card is associated */
uint32_t ocr; /*!< OCR (Operation Conditions Register) value */
union {
sdmmc_cid_t cid; /*!< decoded CID (Card IDentification) register value */
sdmmc_response_t raw_cid; /*!< raw CID of MMC card to be decoded
after the CSD is fetched in the data transfer mode*/
};
sdmmc_csd_t csd; /*!< decoded CSD (Card-Specific Data) register value */
sdmmc_scr_t scr; /*!< decoded SCR (SD card Configuration Register) value */
sdmmc_ssr_t ssr; /*!< decoded SSR (SD Status Register) value */
sdmmc_ext_csd_t ext_csd; /*!< decoded EXT_CSD (Extended Card Specific Data) register value */
uint16_t rca; /*!< RCA (Relative Card Address) */
uint16_t max_freq_khz; /*!< Maximum frequency, in kHz, supported by the card */
int real_freq_khz; /*!< Real working frequency, in kHz, configured on the host controller */
uint32_t is_mem : 1; /*!< Bit indicates if the card is a memory card */
uint32_t is_sdio : 1; /*!< Bit indicates if the card is an IO card */
uint32_t is_mmc : 1; /*!< Bit indicates if the card is MMC */
uint32_t num_io_functions : 3; /*!< If is_sdio is 1, contains the number of IO functions on the card */
uint32_t log_bus_width : 2; /*!< log2(bus width supported by card) */
uint32_t is_ddr : 1; /*!< Card supports DDR mode */
uint32_t reserved : 23; /*!< Reserved for future expansion */
} sdmmc_card_t;
/**
* SD/MMC erase command(38) arguments
* SD:
* ERASE: Erase the write blocks, physical/hard erase.
*
* DISCARD: Card may deallocate the discarded blocks partially or completely.
* After discard operation the previously written data may be partially or
* fully read by the host depending on card implementation.
*
* MMC:
* ERASE: Does TRIM, applies erase operation to write blocks instead of Erase Group.
*
* DISCARD: The Discard function allows the host to identify data that is no
* longer required so that the device can erase the data if necessary during
* background erase events. Applies to write blocks instead of Erase Group
* After discard operation, the original data may be remained partially or
* fully accessible to the host dependent on device.
*
*/
typedef enum {
SDMMC_ERASE_ARG = 0, /*!< Erase operation on SD, Trim operation on MMC */
SDMMC_DISCARD_ARG = 1, /*!< Discard operation for SD/MMC */
} sdmmc_erase_arg_t;
#ifdef __cplusplus
}
#endif
@@ -1,206 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "esp_err.h"
#include "sdmmc_types.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#ifdef __cplusplus
extern "C" {
#endif
/// Handle representing an SD SPI device
typedef int sdspi_dev_handle_t;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define SDSPI_DEFAULT_HOST HSPI_HOST
#define SDSPI_DEFAULT_DMA SDSPI_DEFAULT_HOST
#else
#define SDSPI_DEFAULT_HOST SPI2_HOST
#define SDSPI_DEFAULT_DMA SPI_DMA_CH_AUTO
#endif
/**
* @brief Default sdmmc_host_t structure initializer for SD over SPI driver
*
* Uses SPI mode and max frequency set to 20MHz
*
* 'slot' should be set to an sdspi device initialized by `sdspi_host_init_device()`.
*/
#define SDSPI_HOST_DEFAULT() {\
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
.slot = SDSPI_DEFAULT_HOST, \
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
.io_voltage = 3.3f, \
.init = &sdspi_host_init, \
.set_bus_width = NULL, \
.get_bus_width = NULL, \
.set_bus_ddr_mode = NULL, \
.set_card_clk = &sdspi_host_set_card_clk, \
.do_transaction = &sdspi_host_do_transaction, \
.deinit_p = &sdspi_host_remove_device, \
.io_int_enable = &sdspi_host_io_int_enable, \
.io_int_wait = &sdspi_host_io_int_wait, \
.command_timeout_ms = 0, \
.get_real_freq = &sdspi_host_get_real_freq \
}
/**
* Extra configuration for SD SPI device.
*/
typedef struct {
spi_host_device_t host_id; ///< SPI host to use, SPIx_HOST (see spi_types.h).
gpio_num_t gpio_cs; ///< GPIO number of CS signal
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card.
} sdspi_device_config_t;
#define SDSPI_SLOT_NO_CS GPIO_NUM_NC ///< indicates that card select line is not used
#define SDSPI_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used
#define SDSPI_SLOT_NO_WP GPIO_NUM_NC ///< indicates that write protect line is not used
#define SDSPI_SLOT_NO_INT GPIO_NUM_NC ///< indicates that interrupt line is not used
/**
* Macro defining default configuration of SD SPI device.
*/
#define SDSPI_DEVICE_CONFIG_DEFAULT() {\
.host_id = SDSPI_DEFAULT_HOST, \
.gpio_cs = GPIO_NUM_13, \
.gpio_cd = SDSPI_SLOT_NO_CD, \
.gpio_wp = SDSPI_SLOT_NO_WP, \
.gpio_int = GPIO_NUM_NC, \
}
/**
* @brief Initialize SD SPI driver
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - other error codes may be returned in future versions
*/
esp_err_t sdspi_host_init(void);
/**
* @brief Attach and initialize an SD SPI device on the specific SPI bus
*
* @note This function is not thread safe
*
* @note Initialize the SPI bus by `spi_bus_initialize()` before calling this function.
*
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
*
* @param dev_config pointer to device configuration structure
* @param out_handle Output of the handle to the sdspi device.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if sdspi_host_init_device has invalid arguments
* - ESP_ERR_NO_MEM if memory can not be allocated
* - other errors from the underlying spi_master and gpio drivers
*/
esp_err_t sdspi_host_init_device(const sdspi_device_config_t* dev_config, sdspi_dev_handle_t* out_handle);
/**
* @brief Remove an SD SPI device
*
* @param handle Handle of the SD SPI device
* @return Always ESP_OK
*/
esp_err_t sdspi_host_remove_device(sdspi_dev_handle_t handle);
/**
* @brief Send command to the card and get response
*
* This function returns when command is sent and response is received,
* or data is transferred, or timeout occurs.
*
* @note This function is not thread safe w.r.t. init/deinit functions,
* and bus width/clock speed configuration functions. Multiple tasks
* can call sdspi_host_do_transaction as long as other sdspi_host_*
* functions are not called.
*
* @param handle Handle of the sdspi device
* @param cmdinfo pointer to structure describing command and data to transfer
* @return
* - ESP_OK on success
* - ESP_ERR_TIMEOUT if response or data transfer has timed out
* - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
* - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
*/
esp_err_t sdspi_host_do_transaction(sdspi_dev_handle_t handle, sdmmc_command_t *cmdinfo);
/**
* @brief Set card clock frequency
*
* Currently only integer fractions of 40MHz clock can be used.
* For High Speed cards, 40MHz can be used.
* For Default Speed cards, 20MHz can be used.
*
* @note This function is not thread safe
*
* @param host Handle of the sdspi device
* @param freq_khz card clock frequency, in kHz
* @return
* - ESP_OK on success
* - other error codes may be returned in the future
*/
esp_err_t sdspi_host_set_card_clk(sdspi_dev_handle_t host, uint32_t freq_khz);
/**
* @brief Calculate working frequency for specific device
*
* @param handle SDSPI device handle
* @param[out] real_freq_khz output parameter to hold the calculated frequency (in kHz)
*
* @return
* - ESP_ERR_INVALID_ARG : ``handle`` is NULL or invalid or ``real_freq_khz`` parameter is NULL
* - ESP_OK : Success
*/
esp_err_t sdspi_host_get_real_freq(sdspi_dev_handle_t handle, int* real_freq_khz);
/**
* @brief Release resources allocated using sdspi_host_init
*
* @note This function is not thread safe
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if sdspi_host_init function has not been called
*/
esp_err_t sdspi_host_deinit(void);
/**
* @brief Enable SDIO interrupt.
*
* @param handle Handle of the sdspi device
*
* @return
* - ESP_OK on success
*/
esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle);
/**
* @brief Wait for SDIO interrupt until timeout.
*
* @param handle Handle of the sdspi device
* @param timeout_ticks Ticks to wait before timeout.
*
* @return
* - ESP_OK on success
*/
esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks);
#ifdef __cplusplus
}
#endif
@@ -1,172 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_ipc.h"
#include "intr_types.h"
#include "hal/spi_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
//Maximum amount of bytes that can be put in one DMA descriptor
#define SPI_MAX_DMA_LEN (4096-4)
/**
* Transform unsigned integer of length <= 32 bits to the format which can be
* sent by the SPI driver directly.
*
* E.g. to send 9 bits of data, you can:
*
* uint16_t data = SPI_SWAP_DATA_TX(0x145, 9);
*
* Then points tx_buffer to ``&data``.
*
* @param DATA Data to be sent, can be uint8_t, uint16_t or uint32_t.
* @param LEN Length of data to be sent, since the SPI peripheral sends from
* the MSB, this helps to shift the data to the MSB.
*/
#define SPI_SWAP_DATA_TX(DATA, LEN) __builtin_bswap32((uint32_t)(DATA)<<(32-(LEN)))
/**
* Transform received data of length <= 32 bits to the format of an unsigned integer.
*
* E.g. to transform the data of 15 bits placed in a 4-byte array to integer:
*
* uint16_t data = SPI_SWAP_DATA_RX(*(uint32_t*)t->rx_data, 15);
*
* @param DATA Data to be rearranged, can be uint8_t, uint16_t or uint32_t.
* @param LEN Length of data received, since the SPI peripheral writes from
* the MSB, this helps to shift the data to the LSB.
*/
#define SPI_SWAP_DATA_RX(DATA, LEN) (__builtin_bswap32(DATA)>>(32-(LEN)))
#define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode
#define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode
#define SPICOMMON_BUSFLAG_IOMUX_PINS (1<<1) ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix.
#define SPICOMMON_BUSFLAG_GPIO_PINS (1<<2) ///< Force the signals to be routed through GPIO matrix. Or indicates the pins are routed through the GPIO matrix.
#define SPICOMMON_BUSFLAG_SCLK (1<<3) ///< Check existing of SCLK pin. Or indicates CLK line initialized.
#define SPICOMMON_BUSFLAG_MISO (1<<4) ///< Check existing of MISO pin. Or indicates MISO line initialized.
#define SPICOMMON_BUSFLAG_MOSI (1<<5) ///< Check existing of MOSI pin. Or indicates MOSI line initialized.
#define SPICOMMON_BUSFLAG_DUAL (1<<6) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
#define SPICOMMON_BUSFLAG_WPHD (1<<7) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
#define SPICOMMON_BUSFLAG_QUAD (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD) ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode.
#define SPICOMMON_BUSFLAG_IO4_IO7 (1<<8) ///< Check existing of IO4~IO7 pins. Or indicates IO4~IO7 pins initialized.
#define SPICOMMON_BUSFLAG_OCTAL (SPICOMMON_BUSFLAG_QUAD|SPICOMMON_BUSFLAG_IO4_IO7) ///< Check existing of MOSI/MISO/WP/HD/SPIIO4/SPIIO5/SPIIO6/SPIIO7 pins as output. Or indicates bus able to work under octal mode.
#define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS
/**
* @brief SPI DMA channels
*/
typedef enum {
SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
#if CONFIG_IDF_TARGET_ESP32
SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
#endif
SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
} spi_common_dma_t;
#if __cplusplus
/* Needed for C++ backwards compatibility with earlier ESP-IDF where this argument is a bare 'int'. Can be removed in ESP-IDF 5 */
typedef int spi_dma_chan_t;
#else
typedef spi_common_dma_t spi_dma_chan_t;
#endif
/**
* @brief This is a configuration structure for a SPI bus.
*
* You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the
* GPIO matrix to route the signals. An exception is made when all signals either can be routed through
* the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
*
* @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized.
*/
typedef struct {
union {
int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
int data0_io_num; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
};
union {
int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
int data1_io_num; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
};
int sclk_io_num; ///< GPIO pin for SPI Clock signal, or -1 if not used.
union {
int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
int data2_io_num; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
};
union {
int quadhd_io_num; ///< GPIO pin for HD (Hold) signal, or -1 if not used.
int data3_io_num; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
};
int data4_io_num; ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used.
int data5_io_num; ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used.
int data6_io_num; ///< GPIO pin for spi data6 signal in octal mode, or -1 if not used.
int data7_io_num; ///< GPIO pin for spi data7 signal in octal mode, or -1 if not used.
int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled.
uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
intr_cpu_id_t isr_cpu_id; ///< Select cpu core to register SPI ISR.
int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see
* ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored
* by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of
* the driver, and their callee functions, should be put in the IRAM.
*/
} spi_bus_config_t;
/**
* @brief Initialize a SPI bus
*
* @warning SPI0/1 is not supported
*
* @param host_id SPI peripheral that controls this bus
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory.
* - Selecting SPI_DMA_DISABLED limits the size of transactions.
* - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus.
* - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel.
*
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
* DMA-capable memory.
*
* @warning The ISR of SPI is always executed on the core which calls this
* function. Never starve the ISR on this core or the SPI transactions will not
* be handled.
*
* @return
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan);
/**
* @brief Free a SPI bus
*
* @warning In order for this to succeed, all devices have to be removed first.
*
* @param host_id SPI peripheral to free
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_INVALID_STATE if bus hasn't been initialized before, or not all devices on the bus are freed
* - ESP_OK on success
*/
esp_err_t spi_bus_free(spi_host_device_t host_id);
#ifdef __cplusplus
}
#endif
@@ -1,395 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "hal/spi_types.h"
//for spi_bus_initialization functions. to be back-compatible
#include "driver/spi_common.h"
/**
* @brief SPI common used frequency (in Hz)
* @note SPI peripheral only has an integer divider, and the default clock source can be different on other targets,
* so the actual frequency may be slightly different from the desired frequency.
*/
#define SPI_MASTER_FREQ_8M (80 * 1000 * 1000 / 10) ///< 8MHz
#define SPI_MASTER_FREQ_9M (80 * 1000 * 1000 / 9) ///< 8.89MHz
#define SPI_MASTER_FREQ_10M (80 * 1000 * 1000 / 8) ///< 10MHz
#define SPI_MASTER_FREQ_11M (80 * 1000 * 1000 / 7) ///< 11.43MHz
#define SPI_MASTER_FREQ_13M (80 * 1000 * 1000 / 6) ///< 13.33MHz
#define SPI_MASTER_FREQ_16M (80 * 1000 * 1000 / 5) ///< 16MHz
#define SPI_MASTER_FREQ_20M (80 * 1000 * 1000 / 4) ///< 20MHz
#define SPI_MASTER_FREQ_26M (80 * 1000 * 1000 / 3) ///< 26.67MHz
#define SPI_MASTER_FREQ_40M (80 * 1000 * 1000 / 2) ///< 40MHz
#define SPI_MASTER_FREQ_80M (80 * 1000 * 1000 / 1) ///< 80MHz
#ifdef __cplusplus
extern "C"
{
#endif
#define SPI_DEVICE_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
#define SPI_DEVICE_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
#define SPI_DEVICE_BIT_LSBFIRST (SPI_DEVICE_TXBIT_LSBFIRST|SPI_DEVICE_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
#define SPI_DEVICE_3WIRE (1<<2) ///< Use MOSI (=spid) for both sending and receiving data
#define SPI_DEVICE_POSITIVE_CS (1<<3) ///< Make CS positive during a transaction instead of negative
#define SPI_DEVICE_HALFDUPLEX (1<<4) ///< Transmit data before receiving it, instead of simultaneously
#define SPI_DEVICE_CLK_AS_CS (1<<5) ///< Output clock on CS line if CS is active
/** There are timing issue when reading at high frequency (the frequency is related to whether iomux pins are used, valid time after slave sees the clock).
* - In half-duplex mode, the driver automatically inserts dummy bits before reading phase to fix the timing issue. Set this flag to disable this feature.
* - In full-duplex mode, however, the hardware cannot use dummy bits, so there is no way to prevent data being read from getting corrupted.
* Set this flag to confirm that you're going to work with output only, or read without dummy bits at your own risk.
*/
#define SPI_DEVICE_NO_DUMMY (1<<6)
#define SPI_DEVICE_DDRCLK (1<<7)
#define SPI_DEVICE_NO_RETURN_RESULT (1<<8) ///< Don't return the descriptor to the host on completion (use post_cb to notify instead)
/** @cond */
typedef struct spi_transaction_t spi_transaction_t;
/** @endcond */
typedef void(*transaction_cb_t)(spi_transaction_t *trans);
/**
* @brief This is a configuration for a SPI slave device that is connected to one of the SPI buses.
*/
typedef struct {
uint8_t command_bits; ///< Default amount of bits in command phase (0-16), used when ``SPI_TRANS_VARIABLE_CMD`` is not used, otherwise ignored.
uint8_t address_bits; ///< Default amount of bits in address phase (0-64), used when ``SPI_TRANS_VARIABLE_ADDR`` is not used, otherwise ignored.
uint8_t dummy_bits; ///< Amount of dummy bits to insert between address and data phase
uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration:
- 0: (0, 0)
- 1: (0, 1)
- 2: (1, 0)
- 3: (1, 1)
*/
spi_clock_source_t clock_source;///< Select SPI clock source, `SPI_CLK_SRC_DEFAULT` by default.
uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
int clock_speed_hz; ///< Clock speed, divisors of the SPI `clock_source`, in Hz
int input_delay_ns; /**< Maximum data valid time of slave. The time required between SCLK and MISO
valid, including the possible clock delay from slave to master. The driver uses this value to give an extra
delay before the MISO is ready on the line. Leave at 0 unless you know you need a delay. For better timing
performance at high frequency (over 8MHz), it's suggest to have the right value.
*/
int spics_io_num; ///< CS GPIO pin for this device, or -1 if not used
uint32_t flags; ///< Bitwise OR of SPI_DEVICE_* flags
int queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_device_queue_trans but not yet finished using spi_device_get_trans_result) at the same time
transaction_cb_t pre_cb; /**< Callback to be called before a transmission is started.
*
* This callback is called within interrupt
* context should be in IRAM for best
* performance, see "Transferring Speed"
* section in the SPI Master documentation for
* full details. If not, the callback may crash
* during flash operation when the driver is
* initialized with ESP_INTR_FLAG_IRAM.
*/
transaction_cb_t post_cb; /**< Callback to be called after a transmission has completed.
*
* This callback is called within interrupt
* context should be in IRAM for best
* performance, see "Transferring Speed"
* section in the SPI Master documentation for
* full details. If not, the callback may crash
* during flash operation when the driver is
* initialized with ESP_INTR_FLAG_IRAM.
*/
} spi_device_interface_config_t;
#define SPI_TRANS_MODE_DIO (1<<0) ///< Transmit/receive data in 2-bit mode
#define SPI_TRANS_MODE_QIO (1<<1) ///< Transmit/receive data in 4-bit mode
#define SPI_TRANS_USE_RXDATA (1<<2) ///< Receive into rx_data member of spi_transaction_t instead into memory at rx_buffer.
#define SPI_TRANS_USE_TXDATA (1<<3) ///< Transmit tx_data member of spi_transaction_t instead of data at tx_buffer. Do not set tx_buffer when using this.
#define SPI_TRANS_MODE_DIOQIO_ADDR (1<<4) ///< Also transmit address in mode selected by SPI_MODE_DIO/SPI_MODE_QIO
#define SPI_TRANS_VARIABLE_CMD (1<<5) ///< Use the ``command_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_VARIABLE_ADDR (1<<6) ///< Use the ``address_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_VARIABLE_DUMMY (1<<7) ///< Use the ``dummy_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_CS_KEEP_ACTIVE (1<<8) ///< Keep CS active after data transfer
#define SPI_TRANS_MULTILINE_CMD (1<<9) ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase)
#define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode
#define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase)
/**
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
*/
struct spi_transaction_t {
uint32_t flags; ///< Bitwise OR of SPI_TRANS_* flags
uint16_t cmd; /**< Command data, of which the length is set in the ``command_bits`` of spi_device_interface_config_t.
*
* <b>NOTE: this field, used to be "command" in ESP-IDF 2.1 and before, is re-written to be used in a new way in ESP-IDF 3.0.</b>
*
* Example: write 0x0123 and command_bits=12 to send command 0x12, 0x3_ (in previous version, you may have to write 0x3_12).
*/
uint64_t addr; /**< Address data, of which the length is set in the ``address_bits`` of spi_device_interface_config_t.
*
* <b>NOTE: this field, used to be "address" in ESP-IDF 2.1 and before, is re-written to be used in a new way in ESP-IDF3.0.</b>
*
* Example: write 0x123400 and address_bits=24 to send address of 0x12, 0x34, 0x00 (in previous version, you may have to write 0x12340000).
*/
size_t length; ///< Total data length, in bits
size_t rxlength; ///< Total data length received, should be not greater than ``length`` in full-duplex mode (0 defaults this to the value of ``length``).
void *user; ///< User-defined variable. Can be used to store eg transaction ID.
union {
const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase
uint8_t tx_data[4]; ///< If SPI_TRANS_USE_TXDATA is set, data set here is sent directly from this variable.
};
union {
void *rx_buffer; ///< Pointer to receive buffer, or NULL for no MISO phase. Written by 4 bytes-unit if DMA is used.
uint8_t rx_data[4]; ///< If SPI_TRANS_USE_RXDATA is set, data is received directly to this variable
};
} ; //the rx data should start from a 32-bit aligned address to get around dma issue.
/**
* This struct is for SPI transactions which may change their address and command length.
* Please do set the flags in base to ``SPI_TRANS_VARIABLE_CMD_ADR`` to use the bit length here.
*/
typedef struct {
struct spi_transaction_t base; ///< Transaction data, so that pointer to spi_transaction_t can be converted into spi_transaction_ext_t
uint8_t command_bits; ///< The command length in this transaction, in bits.
uint8_t address_bits; ///< The address length in this transaction, in bits.
uint8_t dummy_bits; ///< The dummy length in this transaction, in bits.
} spi_transaction_ext_t ;
typedef struct spi_device_t *spi_device_handle_t; ///< Handle for a device on a SPI bus
/**
* @brief Allocate a device on a SPI bus
*
* This initializes the internal structures for a device, plus allocates a CS pin on the indicated SPI master
* peripheral and routes it to the indicated GPIO. All SPI master devices have three CS pins and can thus control
* up to three devices.
*
* @note While in general, speeds up to 80MHz on the dedicated SPI pins and 40MHz on GPIO-matrix-routed pins are
* supported, full-duplex transfers routed over the GPIO matrix only support speeds up to 26MHz.
*
* @param host_id SPI peripheral to allocate device on
* @param dev_config SPI interface protocol config for the device
* @param handle Pointer to variable to hold the device handle
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid or configuration combination is not supported (e.g.
* `dev_config->post_cb` isn't set while flag `SPI_DEVICE_NO_RETURN_RESULT` is enabled)
* - ESP_ERR_NOT_FOUND if host doesn't have any free CS slots
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interface_config_t *dev_config, spi_device_handle_t *handle);
/**
* @brief Remove a device from the SPI bus
*
* @param handle Device handle to free
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_INVALID_STATE if device already is freed
* - ESP_OK on success
*/
esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
/**
* @brief Queue a SPI transaction for interrupt transaction execution. Get the result by ``spi_device_get_trans_result``.
*
* @note Normally a device cannot start (queue) polling and interrupt
* transactions simultaneously.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param trans_desc Description of transaction to execute
* @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to
* never time out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
* the bus was not acquired (`spi_device_acquire_bus()` should be called first)
* - ESP_ERR_TIMEOUT if there was no room in the queue before ticks_to_wait expired
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
* - ESP_ERR_INVALID_STATE if previous transactions are not finished
* - ESP_OK on success
*/
esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Get the result of a SPI transaction queued earlier by ``spi_device_queue_trans``.
*
* This routine will wait until a transaction to the given device
* succesfully completed. It will then return the description of the
* completed transaction so software can inspect the result and e.g. free the memory or
* re-use the buffers.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param trans_desc Pointer to variable able to contain a pointer to the description of the transaction
that is executed. The descriptor should not be modified until the descriptor is returned by
spi_device_get_trans_result.
* @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time
out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_NOT_SUPPORTED if flag `SPI_DEVICE_NO_RETURN_RESULT` is set
* - ESP_ERR_TIMEOUT if there was no completed transaction before ticks_to_wait expired
* - ESP_OK on success
*/
esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait);
/**
* @brief Send a SPI transaction, wait for it to complete, and return the result
*
* This function is the equivalent of calling spi_device_queue_trans() followed by spi_device_get_trans_result().
* Do not use this when there is still a transaction separately queued (started) from spi_device_queue_trans() or polling_start/transmit that hasn't been finalized.
*
* @note This function is not thread safe when multiple tasks access the same SPI device.
* Normally a device cannot start (queue) polling and interrupt
* transactions simutanuously.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param trans_desc Description of transaction to execute
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc);
/**
* @brief Immediately start a polling transaction.
*
* @note Normally a device cannot start (queue) polling and interrupt
* transactions simutanuously. Moreover, a device cannot start a new polling
* transaction if another polling transaction is not finished.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param trans_desc Description of transaction to execute
* @param ticks_to_wait Ticks to wait until there's room in the queue;
* currently only portMAX_DELAY is supported.
*
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_TRANS_CS_KEEP_ACTIVE flag is specified while
* the bus was not acquired (`spi_device_acquire_bus()` should be called first)
* - ESP_ERR_TIMEOUT if the device cannot get control of the bus before ``ticks_to_wait`` expired
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
* - ESP_ERR_INVALID_STATE if previous transactions are not finished
* - ESP_OK on success
*/
esp_err_t spi_device_polling_start(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Poll until the polling transaction ends.
*
* This routine will not return until the transaction to the given device has
* succesfully completed. The task is not blocked, but actively busy-spins for
* the transaction to be completed.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time
out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_TIMEOUT if the transaction cannot finish before ticks_to_wait expired
* - ESP_OK on success
*/
esp_err_t spi_device_polling_end(spi_device_handle_t handle, TickType_t ticks_to_wait);
/**
* @brief Send a polling transaction, wait for it to complete, and return the result
*
* This function is the equivalent of calling spi_device_polling_start() followed by spi_device_polling_end().
* Do not use this when there is still a transaction that hasn't been finalized.
*
* @note This function is not thread safe when multiple tasks access the same SPI device.
* Normally a device cannot start (queue) polling and interrupt
* transactions simutanuously.
*
* @param handle Device handle obtained using spi_host_add_dev
* @param trans_desc Description of transaction to execute
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
esp_err_t spi_device_polling_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc);
/**
* @brief Occupy the SPI bus for a device to do continuous transactions.
*
* Transactions to all other devices will be put off until ``spi_device_release_bus`` is called.
*
* @note The function will wait until all the existing transactions have been sent.
*
* @param device The device to occupy the bus.
* @param wait Time to wait before the the bus is occupied by the device. Currently MUST set to portMAX_DELAY.
*
* @return
* - ESP_ERR_INVALID_ARG : ``wait`` is not set to portMAX_DELAY.
* - ESP_OK : Success.
*/
esp_err_t spi_device_acquire_bus(spi_device_handle_t device, TickType_t wait);
/**
* @brief Release the SPI bus occupied by the device. All other devices can start sending transactions.
*
* @param dev The device to release the bus.
*/
void spi_device_release_bus(spi_device_handle_t dev);
/**
* @brief Calculate working frequency for specific device
*
* @param handle SPI device handle
* @param[out] freq_khz output parameter to hold calculated frequency in kHz
*
* @return
* - ESP_ERR_INVALID_ARG : ``handle`` or ``freq_khz`` parameter is NULL
* - ESP_OK : Success
*/
esp_err_t spi_device_get_actual_freq(spi_device_handle_t handle, int *freq_khz);
/**
* @brief Calculate the working frequency that is most close to desired frequency.
*
* @param fapb The frequency of apb clock, should be ``APB_CLK_FREQ``.
* @param hz Desired working frequency
* @param duty_cycle Duty cycle of the spi clock
*
* @return Actual working frequency that most fit.
*/
int spi_get_actual_clock(int fapb, int hz, int duty_cycle) __attribute__((deprecated("Please use spi_device_get_actual_freq instead")));
/**
* @brief Calculate the timing settings of specified frequency and settings.
*
* @param gpio_is_used True if using GPIO matrix, or False if iomux pins are used.
* @param input_delay_ns Input delay from SCLK launch edge to MISO data valid.
* @param eff_clk Effective clock frequency (in Hz) from `spi_get_actual_clock()`.
* @param dummy_o Address of dummy bits used output. Set to NULL if not needed.
* @param cycles_remain_o Address of cycles remaining (after dummy bits are used) output.
* - -1 If too many cycles remaining, suggest to compensate half a clock.
* - 0 If no remaining cycles or dummy bits are not used.
* - positive value: cycles suggest to compensate.
*
* @note If **dummy_o* is not zero, it means dummy bits should be applied in half duplex mode, and full duplex mode may not work.
*/
void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int *dummy_o, int *cycles_remain_o);
/**
* @brief Get the frequency limit of current configurations.
* SPI master working at this limit is OK, while above the limit, full duplex mode and DMA will not work,
* and dummy bits will be aplied in the half duplex mode.
*
* @param gpio_is_used True if using GPIO matrix, or False if native pins are used.
* @param input_delay_ns Input delay from SCLK launch edge to MISO data valid.
* @return Frequency limit of current configurations.
*/
int spi_get_freq_limit(bool gpio_is_used, int input_delay_ns);
#ifdef __cplusplus
}
#endif
@@ -1,193 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _DRIVER_SPI_SLAVE_H_
#define _DRIVER_SPI_SLAVE_H_
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "driver/spi_common.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define SPI_SLAVE_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
#define SPI_SLAVE_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
#define SPI_SLAVE_BIT_LSBFIRST (SPI_SLAVE_TXBIT_LSBFIRST|SPI_SLAVE_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
#define SPI_SLAVE_NO_RETURN_RESULT (1<<2) ///< Don't return the descriptor to the host on completion (use `post_trans_cb` to notify instead)
/** @cond */
typedef struct spi_slave_transaction_t spi_slave_transaction_t;
/** @endcond */
typedef void(*slave_transaction_cb_t)(spi_slave_transaction_t *trans);
/**
* @brief This is a configuration for a SPI host acting as a slave device.
*/
typedef struct {
int spics_io_num; ///< CS GPIO pin for this device
uint32_t flags; ///< Bitwise OR of SPI_SLAVE_* flags
int queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_slave_queue_trans but not yet finished using spi_slave_get_trans_result) at the same time
uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration:
- 0: (0, 0)
- 1: (0, 1)
- 2: (1, 0)
- 3: (1, 1)
*/
slave_transaction_cb_t post_setup_cb; /**< Callback called after the SPI registers are loaded with new data.
*
* This callback is called within interrupt
* context should be in IRAM for best
* performance, see "Transferring Speed"
* section in the SPI Master documentation for
* full details. If not, the callback may crash
* during flash operation when the driver is
* initialized with ESP_INTR_FLAG_IRAM.
*/
slave_transaction_cb_t post_trans_cb; /**< Callback called after a transaction is done.
*
* This callback is called within interrupt
* context should be in IRAM for best
* performance, see "Transferring Speed"
* section in the SPI Master documentation for
* full details. If not, the callback may crash
* during flash operation when the driver is
* initialized with ESP_INTR_FLAG_IRAM.
*/
} spi_slave_interface_config_t;
/**
* This structure describes one SPI transaction
*/
struct spi_slave_transaction_t {
size_t length; ///< Total data length, in bits
size_t trans_len; ///< Transaction data length, in bits
const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase
void *rx_buffer; /**< Pointer to receive buffer, or NULL for no MISO phase.
* When the DMA is anabled, must start at WORD boundary (``rx_buffer%4==0``),
* and has length of a multiple of 4 bytes.
*/
void *user; ///< User-defined variable. Can be used to store eg transaction ID.
};
/**
* @brief Initialize a SPI bus as a slave interface
*
* @warning SPI0/1 is not supported
*
* @param host SPI peripheral to use as a SPI slave interface
* @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
* @param slave_config Pointer to a spi_slave_interface_config_t struct specifying the details for the slave interface
* @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory.
* - Selecting SPI_DMA_DISABLED limits the size of transactions.
* - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus.
* - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel.
*
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
* DMA-capable memory.
*
* @warning The ISR of SPI is always executed on the core which calls this
* function. Never starve the ISR on this core or the SPI transactions will not
* be handled.
*
* @return
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, spi_dma_chan_t dma_chan);
/**
* @brief Free a SPI bus claimed as a SPI slave interface
*
* @param host SPI peripheral to free
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_INVALID_STATE if not all devices on the bus are freed
* - ESP_OK on success
*/
esp_err_t spi_slave_free(spi_host_device_t host);
/**
* @brief Queue a SPI transaction for execution
*
* Queues a SPI transaction to be executed by this slave device. (The transaction queue size was specified when the slave
* device was initialised via spi_slave_initialize.) This function may block if the queue is full (depending on the
* ticks_to_wait parameter). No SPI operation is directly initiated by this function, the next queued transaction
* will happen when the master initiates a SPI transaction by pulling down CS and sending out clock signals.
*
* This function hands over ownership of the buffers in ``trans_desc`` to the SPI slave driver; the application is
* not to access this memory until ``spi_slave_queue_trans`` is called to hand ownership back to the application.
*
* @param host SPI peripheral that is acting as a slave
* @param trans_desc Description of transaction to execute. Not const because we may want to write status back
* into the transaction description.
* @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to
* never time out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Get the result of a SPI transaction queued earlier
*
* This routine will wait until a transaction to the given device (queued earlier with
* spi_slave_queue_trans) has succesfully completed. It will then return the description of the
* completed transaction so software can inspect the result and e.g. free the memory or
* re-use the buffers.
*
* It is mandatory to eventually use this function for any transaction queued by ``spi_slave_queue_trans``.
*
* @param host SPI peripheral to that is acting as a slave
* @param[out] trans_desc Pointer to variable able to contain a pointer to the description of the
* transaction that is executed
* @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time
* out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_ERR_NOT_SUPPORTED if flag `SPI_SLAVE_NO_RETURN_RESULT` is set
* - ESP_OK on success
*/
esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait);
/**
* @brief Do a SPI transaction
*
* Essentially does the same as spi_slave_queue_trans followed by spi_slave_get_trans_result. Do
* not use this when there is still a transaction queued that hasn't been finalized
* using spi_slave_get_trans_result.
*
* @param host SPI peripheral to that is acting as a slave
* @param trans_desc Pointer to variable able to contain a pointer to the description of the
* transaction that is executed. Not const because we may want to write status back
* into the transaction description.
* @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time
* out.
* @return
* - ESP_ERR_INVALID_ARG if parameter is invalid
* - ESP_OK on success
*/
esp_err_t spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
#ifdef __cplusplus
}
#endif
#endif
@@ -1,208 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_types.h"
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "hal/spi_types.h"
#include "driver/spi_common.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C"
{
#endif
#if !SOC_SPI_SUPPORT_SLAVE_HD_VER2 && !CI_HEADER_CHECK
#error The SPI peripheral does not support this feature
#endif
/// Descriptor of data to send/receive
typedef struct {
uint8_t* data; ///< Buffer to send, must be DMA capable
size_t len; ///< Len of data to send/receive. For receiving the buffer length should be multiples of 4 bytes, otherwise the extra part will be truncated.
size_t trans_len; ///< For RX direction, it indicates the data actually received. For TX direction, it is meaningless.
void* arg; ///< Extra argument indiciating this data
} spi_slave_hd_data_t;
/// Information of SPI Slave HD event
typedef struct {
spi_event_t event; ///< Event type
spi_slave_hd_data_t* trans; ///< Corresponding transaction for SPI_EV_SEND and SPI_EV_RECV events
} spi_slave_hd_event_t;
/// Callback for SPI Slave HD
typedef bool (*slave_cb_t)(void* arg, spi_slave_hd_event_t* event, BaseType_t* awoken);
/// Channel of SPI Slave HD to do data transaction
typedef enum {
SPI_SLAVE_CHAN_TX = 0, ///< The output channel (RDDMA)
SPI_SLAVE_CHAN_RX = 1, ///< The input channel (WRDMA)
} spi_slave_chan_t;
/// Callback configuration structure for SPI Slave HD
typedef struct {
slave_cb_t cb_buffer_tx; ///< Callback when master reads from shared buffer
slave_cb_t cb_buffer_rx; ///< Callback when master writes to shared buffer
slave_cb_t cb_send_dma_ready; ///< Callback when TX data buffer is loaded to the hardware (DMA)
slave_cb_t cb_sent; ///< Callback when data are sent
slave_cb_t cb_recv_dma_ready; ///< Callback when RX data buffer is loaded to the hardware (DMA)
slave_cb_t cb_recv; ///< Callback when data are received
slave_cb_t cb_cmd9; ///< Callback when CMD9 received
slave_cb_t cb_cmdA; ///< Callback when CMDA received
void* arg; ///< Argument indicating this SPI Slave HD peripheral instance
} spi_slave_hd_callback_config_t;
//flags for ``spi_slave_hd_slot_config_t`` to use
#define SPI_SLAVE_HD_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
#define SPI_SLAVE_HD_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
#define SPI_SLAVE_HD_BIT_LSBFIRST (SPI_SLAVE_HD_TXBIT_LSBFIRST|SPI_SLAVE_HD_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
#define SPI_SLAVE_HD_APPEND_MODE (1<<2) ///< Adopt DMA append mode for transactions. In this mode, users can load(append) DMA descriptors without stopping the DMA
/// Configuration structure for the SPI Slave HD driver
typedef struct {
uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration:
- 0: (0, 0)
- 1: (0, 1)
- 2: (1, 0)
- 3: (1, 1)
*/
uint32_t spics_io_num; ///< CS GPIO pin for this device
uint32_t flags; ///< Bitwise OR of SPI_SLAVE_HD_* flags
uint32_t command_bits; ///< command field bits, multiples of 8 and at least 8.
uint32_t address_bits; ///< address field bits, multiples of 8 and at least 8.
uint32_t dummy_bits; ///< dummy field bits, multiples of 8 and at least 8.
uint32_t queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_slave_hd_queue_trans but not yet finished using spi_slave_hd_get_trans_result) at the same time
spi_dma_chan_t dma_chan; ///< DMA channel to used.
spi_slave_hd_callback_config_t cb_config; ///< Callback configuration
} spi_slave_hd_slot_config_t;
/**
* @brief Initialize the SPI Slave HD driver.
*
* @param host_id The host to use
* @param bus_config Bus configuration for the bus used
* @param config Configuration for the SPI Slave HD driver
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: invalid argument given
* - ESP_ERR_INVALID_STATE: function called in invalid state, may be some resources are already in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
* - ESP_ERR_NO_MEM: memory allocation failed
* - or other return value from `esp_intr_alloc`
*/
esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *bus_config,
const spi_slave_hd_slot_config_t *config);
/**
* @brief Deinitialize the SPI Slave HD driver
*
* @param host_id The host to deinitialize the driver
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: if the host_id is not correct
*/
esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id);
/**
* @brief Queue transactions (segment mode)
*
* @param host_id Host to queue the transaction
* @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
* @param trans Transaction descriptors
* @param timeout Timeout before the data is queued
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason:
* - The buffer given is not DMA capable
* - The length of data is invalid (not larger than 0, or exceed the max transfer length)
* - The transaction direction is invalid
* - ESP_ERR_TIMEOUT: Cannot queue the data before timeout. Master is still processing previous transaction.
* - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode.
*/
esp_err_t spi_slave_hd_queue_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t* trans, TickType_t timeout);
/**
* @brief Get the result of a data transaction (segment mode)
*
* @note This API should be called successfully the same times as the ``spi_slave_hd_queue_trans``.
*
* @param host_id Host to queue the transaction
* @param chan Channel to get the result, SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
* @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX.
* @param timeout Timeout before the result is got
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: Function is not valid
* - ESP_ERR_TIMEOUT: There's no transaction done before timeout
* - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode.
*/
esp_err_t spi_slave_hd_get_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout);
/**
* @brief Read the shared registers
*
* @param host_id Host to read the shared registers
* @param addr Address of register to read, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1``
* @param[out] out_data Output buffer to store the read data
* @param len Length to read, not larger than ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr``
*/
void spi_slave_hd_read_buffer(spi_host_device_t host_id, int addr, uint8_t *out_data, size_t len);
/**
* @brief Write the shared registers
*
* @param host_id Host to write the shared registers
* @param addr Address of register to write, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1``
* @param data Buffer holding the data to write
* @param len Length to write, ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr``
*/
void spi_slave_hd_write_buffer(spi_host_device_t host_id, int addr, uint8_t *data, size_t len);
/**
* @brief Load transactions (append mode)
*
* @note In this mode, user transaction descriptors will be appended to the DMA and the DMA will keep processing the data without stopping
*
* @param host_id Host to load transactions
* @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
* @param trans Transaction descriptor
* @param timeout Timeout before the transaction is loaded
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason:
* - The buffer given is not DMA capable
* - The length of data is invalid (not larger than 0, or exceed the max transfer length)
* - The transaction direction is invalid
* - ESP_ERR_TIMEOUT: Master is still processing previous transaction. There is no available transaction for slave to load
* - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode.
*/
esp_err_t spi_slave_hd_append_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t *trans, TickType_t timeout);
/**
* @brief Get the result of a data transaction (append mode)
*
* @note This API should be called the same times as the ``spi_slave_hd_append_trans``
*
* @param host_id Host to load the transaction
* @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX
* @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX.
* @param timeout Timeout before the result is got
* @return
* - ESP_OK: on success
* - ESP_ERR_INVALID_ARG: Function is not valid
* - ESP_ERR_TIMEOUT: There's no transaction done before timeout
* - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode.
*/
esp_err_t spi_slave_hd_get_append_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout);
#ifdef __cplusplus
}
#endif
@@ -1,99 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#include "hal/temperature_sensor_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of temperature sensor driver handle
*/
typedef struct temperature_sensor_obj_t *temperature_sensor_handle_t;
/**
* @brief Configuration of measurement range for the temperature sensor.
*
* @note If you see the log `the boundary you gave cannot meet the range of internal temperature sensor`. You may need to refer to
* predefined range listed doc ``api-reference/peripherals/Temperature sensor``.
*/
typedef struct {
int range_min; /**< the minimum value of the temperature you want to test */
int range_max; /**< the maximum value of the temperature you want to test */
temperature_sensor_clk_src_t clk_src; /**< the clock source of the temperature sensor. */
} temperature_sensor_config_t;
/**
* @brief temperature_sensor_config_t default constructure
*/
#define TEMPERATURE_SENSOR_CONFIG_DEFAULT(min, max) \
{ \
.range_min = min, \
.range_max = max, \
.clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, \
}
/**
* @brief Install temperature sensor driver
*
* @param tsens_config Pointer to config structure.
* @param ret_tsens Return the pointer of temperature sensor handle.
* @return
* - ESP_OK if succeed
*/
esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens);
/**
* @brief Uninstall the temperature sensor driver
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @return
* - ESP_OK if succeed.
*/
esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens);
/**
* @brief Enable the temperature sensor
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE if temperature sensor is enabled already.
*/
esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens);
/**
* @brief Disable temperature sensor
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE if temperature sensor is not enabled yet.
*/
esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens);
/**
* @brief Read temperature sensor data that is converted to degrees Celsius.
* @note Should not be called from interrupt.
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @param out_celsius The measure output value.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG invalid arguments
* - ESP_ERR_INVALID_STATE Temperature sensor is not enabled yet.
* - ESP_FAIL Parse the sensor data into ambient temperature failed (e.g. out of the range).
*/
esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius);
#ifdef __cplusplus
}
#endif
@@ -1,13 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#if SOC_TOUCH_SENSOR_SUPPORTED
#include "driver/touch_sensor.h"
#endif
@@ -1,163 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "hal/touch_sensor_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize touch module.
* @note If default parameter don't match the usage scenario, it can be changed after this function.
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM Touch pad init error
* - ESP_ERR_NOT_SUPPORTED Touch pad is providing current to external XTAL
*/
esp_err_t touch_pad_init(void);
/**
* @brief Un-install touch pad driver.
* @note After this function is called, other touch functions are prohibited from being called.
* @return
* - ESP_OK Success
* - ESP_FAIL Touch pad driver not initialized
*/
esp_err_t touch_pad_deinit(void);
/**
* @brief Initialize touch pad GPIO
* @param touch_num touch pad index
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_io_init(touch_pad_t touch_num);
/**
* @brief Set touch sensor high voltage threshold of chanrge.
* The touch sensor measures the channel capacitance value by charging and discharging the channel.
* So the high threshold should be less than the supply voltage.
* @param refh the value of DREFH
* @param refl the value of DREFL
* @param atten the attenuation on DREFH
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten);
/**
* @brief Get touch sensor reference voltage,
* @param refh pointer to accept DREFH value
* @param refl pointer to accept DREFL value
* @param atten pointer to accept the attenuation on DREFH
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten);
/**
* @brief Set touch sensor charge/discharge speed for each pad.
* If the slope is 0, the counter would always be zero.
* If the slope is 1, the charging and discharging would be slow, accordingly.
* If the slope is set 7, which is the maximum value, the charging and discharging would be fast.
* @note The higher the charge and discharge current, the greater the immunity of the touch channel,
* but it will increase the system power consumption.
* @param touch_num touch pad index
* @param slope touch pad charge/discharge speed
* @param opt the initial voltage
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt);
/**
* @brief Get touch sensor charge/discharge speed for each pad
* @param touch_num touch pad index
* @param slope pointer to accept touch pad charge/discharge slope
* @param opt pointer to accept the initial voltage
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt);
/**
* @brief Deregister the handler previously registered using touch_pad_isr_handler_register
* @param fn handler function to call (as passed to touch_pad_isr_handler_register)
* @param arg argument of the handler (as passed to touch_pad_isr_handler_register)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_STATE if a handler matching both fn and
* arg isn't registered
*/
esp_err_t touch_pad_isr_deregister(void(*fn)(void *), void *arg);
/**
* @brief Get the touch pad which caused wakeup from deep sleep.
* @param pad_num pointer to touch pad which caused wakeup
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG parameter is NULL
*/
esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num);
/**
* @brief Set touch sensor FSM mode, the test action can be triggered by the timer,
* as well as by the software.
* @param mode FSM mode
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode);
/**
* @brief Get touch sensor FSM mode
* @param mode pointer to accept FSM mode
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode);
/**
* @brief To clear the touch sensor channel active status.
*
* @note The FSM automatically updates the touch sensor status. It is generally not necessary to call this API to clear the status.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_clear_status(void);
/**
* @brief Get the touch sensor channel active status mask.
* The bit position represents the channel number. The 0/1 status of the bit represents the trigger status.
*
* @return
* - The touch sensor status. e.g. Touch1 trigger status is `status_mask & (BIT1)`.
*/
uint32_t touch_pad_get_status(void);
/**
* @brief Check touch sensor measurement status.
*
* @return
* - True measurement is under way
* - False measurement done
*/
bool touch_pad_meas_is_done(void);
#ifdef __cplusplus
}
#endif
-340
View File
@@ -1,340 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "freertos/FreeRTOS.h"
#include "esp_types.h"
#include "esp_intr_alloc.h"
#include "esp_err.h"
#include "driver/gpio.h"
#include "hal/twai_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------- Default initializers and flags ---------------------- */
/** @cond */ //Doxy command to hide preprocessor definitions from docs
/**
* @brief Initializer macro for general configuration structure.
*
* This initializer macros allows the TX GPIO, RX GPIO, and operating mode to be
* configured. The other members of the general configuration structure are
* assigned default values.
*/
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num, \
.clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED, \
.tx_queue_len = 5, .rx_queue_len = 5, \
.alerts_enabled = TWAI_ALERT_NONE, .clkout_divider = 0, \
.intr_flags = ESP_INTR_FLAG_LEVEL1}
/**
* @brief Alert flags
*
* The following flags represents the various kind of alerts available in
* the TWAI driver. These flags can be used when configuring/reconfiguring
* alerts, or when calling twai_read_alerts().
*
* @note The TWAI_ALERT_AND_LOG flag is not an actual alert, but will configure
* the TWAI driver to log to UART when an enabled alert occurs.
*/
#define TWAI_ALERT_TX_IDLE 0x00000001 /**< Alert(1): No more messages to transmit */
#define TWAI_ALERT_TX_SUCCESS 0x00000002 /**< Alert(2): The previous transmission was successful */
#define TWAI_ALERT_RX_DATA 0x00000004 /**< Alert(4): A frame has been received and added to the RX queue */
#define TWAI_ALERT_BELOW_ERR_WARN 0x00000008 /**< Alert(8): Both error counters have dropped below error warning limit */
#define TWAI_ALERT_ERR_ACTIVE 0x00000010 /**< Alert(16): TWAI controller has become error active */
#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000020 /**< Alert(32): TWAI controller is undergoing bus recovery */
#define TWAI_ALERT_BUS_RECOVERED 0x00000040 /**< Alert(64): TWAI controller has successfully completed bus recovery */
#define TWAI_ALERT_ARB_LOST 0x00000080 /**< Alert(128): The previous transmission lost arbitration */
#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000100 /**< Alert(256): One of the error counters have exceeded the error warning limit */
#define TWAI_ALERT_BUS_ERROR 0x00000200 /**< Alert(512): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
#define TWAI_ALERT_TX_FAILED 0x00000400 /**< Alert(1024): The previous transmission has failed (for single shot transmission) */
#define TWAI_ALERT_RX_QUEUE_FULL 0x00000800 /**< Alert(2048): The RX queue is full causing a frame to be lost */
#define TWAI_ALERT_ERR_PASS 0x00001000 /**< Alert(4096): TWAI controller has become error passive */
#define TWAI_ALERT_BUS_OFF 0x00002000 /**< Alert(8192): Bus-off condition occurred. TWAI controller can no longer influence bus */
#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00004000 /**< Alert(16384): An RX FIFO overrun has occurred */
#define TWAI_ALERT_TX_RETRIED 0x00008000 /**< Alert(32768): An message transmission was cancelled and retried due to an errata workaround */
#define TWAI_ALERT_PERIPH_RESET 0x00010000 /**< Alert(65536): The TWAI controller was reset */
#define TWAI_ALERT_ALL 0x0001FFFF /**< Bit mask to enable all alerts during configuration */
#define TWAI_ALERT_NONE 0x00000000 /**< Bit mask to disable all alerts during configuration */
#define TWAI_ALERT_AND_LOG 0x00020000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
/** @endcond */
#define TWAI_IO_UNUSED ((gpio_num_t) -1) /**< Marks GPIO as unused in TWAI configuration */
/* ----------------------- Enum and Struct Definitions ---------------------- */
/**
* @brief TWAI driver states
*/
typedef enum {
TWAI_STATE_STOPPED, /**< Stopped state. The TWAI controller will not participate in any TWAI bus activities */
TWAI_STATE_RUNNING, /**< Running state. The TWAI controller can transmit and receive messages */
TWAI_STATE_BUS_OFF, /**< Bus-off state. The TWAI controller cannot participate in bus activities until it has recovered */
TWAI_STATE_RECOVERING, /**< Recovering state. The TWAI controller is undergoing bus recovery */
} twai_state_t;
/**
* @brief Structure for general configuration of the TWAI driver
*
* @note Macro initializers are available for this structure
*/
typedef struct {
twai_mode_t mode; /**< Mode of TWAI controller */
gpio_num_t tx_io; /**< Transmit GPIO number */
gpio_num_t rx_io; /**< Receive GPIO number */
gpio_num_t clkout_io; /**< CLKOUT GPIO number (optional, set to -1 if unused) */
gpio_num_t bus_off_io; /**< Bus off indicator GPIO number (optional, set to -1 if unused) */
uint32_t tx_queue_len; /**< Number of messages TX queue can hold (set to 0 to disable TX Queue) */
uint32_t rx_queue_len; /**< Number of messages RX queue can hold */
uint32_t alerts_enabled; /**< Bit field of alerts to enable (see documentation) */
uint32_t clkout_divider; /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */
int intr_flags; /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */
} twai_general_config_t;
/**
* @brief Structure to store status information of TWAI driver
*/
typedef struct {
twai_state_t state; /**< Current state of TWAI controller (Stopped/Running/Bus-Off/Recovery) */
uint32_t msgs_to_tx; /**< Number of messages queued for transmission or awaiting transmission completion */
uint32_t msgs_to_rx; /**< Number of messages in RX queue waiting to be read */
uint32_t tx_error_counter; /**< Current value of Transmit Error Counter */
uint32_t rx_error_counter; /**< Current value of Receive Error Counter */
uint32_t tx_failed_count; /**< Number of messages that failed transmissions */
uint32_t rx_missed_count; /**< Number of messages that were lost due to a full RX queue (or errata workaround if enabled) */
uint32_t rx_overrun_count; /**< Number of messages that were lost due to a RX FIFO overrun */
uint32_t arb_lost_count; /**< Number of instances arbitration was lost */
uint32_t bus_error_count; /**< Number of instances a bus error has occurred */
} twai_status_info_t;
/* ------------------------------ Public API -------------------------------- */
/**
* @brief Install TWAI driver
*
* This function installs the TWAI driver using three configuration structures.
* The required memory is allocated and the TWAI driver is placed in the stopped
* state after running this function.
*
* @param[in] g_config General configuration structure
* @param[in] t_config Timing configuration structure
* @param[in] f_config Filter configuration structure
*
* @note Macro initializers are available for the configuration structures (see documentation)
*
* @note To reinstall the TWAI driver, call twai_driver_uninstall() first
*
* @return
* - ESP_OK: Successfully installed TWAI driver
* - ESP_ERR_INVALID_ARG: Arguments are invalid, e.g. invalid clock source, invalid quanta resolution
* - ESP_ERR_NO_MEM: Insufficient memory
* - ESP_ERR_INVALID_STATE: Driver is already installed
*/
esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config);
/**
* @brief Uninstall the TWAI driver
*
* This function uninstalls the TWAI driver, freeing the memory utilized by the
* driver. This function can only be called when the driver is in the stopped
* state or the bus-off state.
*
* @warning The application must ensure that no tasks are blocked on TX/RX
* queues or alerts when this function is called.
*
* @return
* - ESP_OK: Successfully uninstalled TWAI driver
* - ESP_ERR_INVALID_STATE: Driver is not in stopped/bus-off state, or is not installed
*/
esp_err_t twai_driver_uninstall(void);
/**
* @brief Start the TWAI driver
*
* This function starts the TWAI driver, putting the TWAI driver into the running
* state. This allows the TWAI driver to participate in TWAI bus activities such
* as transmitting/receiving messages. The TX and RX queue are reset in this function,
* clearing any messages that are unread or pending transmission. This function
* can only be called when the TWAI driver is in the stopped state.
*
* @return
* - ESP_OK: TWAI driver is now running
* - ESP_ERR_INVALID_STATE: Driver is not in stopped state, or is not installed
*/
esp_err_t twai_start(void);
/**
* @brief Stop the TWAI driver
*
* This function stops the TWAI driver, preventing any further message from being
* transmitted or received until twai_start() is called. Any messages in the TX
* queue are cleared. Any messages in the RX queue should be read by the
* application after this function is called. This function can only be called
* when the TWAI driver is in the running state.
*
* @warning A message currently being transmitted/received on the TWAI bus will
* be ceased immediately. This may lead to other TWAI nodes interpreting
* the unfinished message as an error.
*
* @return
* - ESP_OK: TWAI driver is now Stopped
* - ESP_ERR_INVALID_STATE: Driver is not in running state, or is not installed
*/
esp_err_t twai_stop(void);
/**
* @brief Transmit a TWAI message
*
* This function queues a TWAI message for transmission. Transmission will start
* immediately if no other messages are queued for transmission. If the TX queue
* is full, this function will block until more space becomes available or until
* it times out. If the TX queue is disabled (TX queue length = 0 in configuration),
* this function will return immediately if another message is undergoing
* transmission. This function can only be called when the TWAI driver is in the
* running state and cannot be called under Listen Only Mode.
*
* @param[in] message Message to transmit
* @param[in] ticks_to_wait Number of FreeRTOS ticks to block on the TX queue
*
* @note This function does not guarantee that the transmission is successful.
* The TX_SUCCESS/TX_FAILED alert can be enabled to alert the application
* upon the success/failure of a transmission.
*
* @note The TX_IDLE alert can be used to alert the application when no other
* messages are awaiting transmission.
*
* @return
* - ESP_OK: Transmission successfully queued/initiated
* - ESP_ERR_INVALID_ARG: Arguments are invalid
* - ESP_ERR_TIMEOUT: Timed out waiting for space on TX queue
* - ESP_FAIL: TX queue is disabled and another message is currently transmitting
* - ESP_ERR_INVALID_STATE: TWAI driver is not in running state, or is not installed
* - ESP_ERR_NOT_SUPPORTED: Listen Only Mode does not support transmissions
*/
esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait);
/**
* @brief Receive a TWAI message
*
* This function receives a message from the RX queue. The flags field of the
* message structure will indicate the type of message received. This function
* will block if there are no messages in the RX queue
*
* @param[out] message Received message
* @param[in] ticks_to_wait Number of FreeRTOS ticks to block on RX queue
*
* @warning The flags field of the received message should be checked to determine
* if the received message contains any data bytes.
*
* @return
* - ESP_OK: Message successfully received from RX queue
* - ESP_ERR_TIMEOUT: Timed out waiting for message
* - ESP_ERR_INVALID_ARG: Arguments are invalid
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed
*/
esp_err_t twai_receive(twai_message_t *message, TickType_t ticks_to_wait);
/**
* @brief Read TWAI driver alerts
*
* This function will read the alerts raised by the TWAI driver. If no alert has
* been issued when this function is called, this function will block until an alert
* occurs or until it timeouts.
*
* @param[out] alerts Bit field of raised alerts (see documentation for alert flags)
* @param[in] ticks_to_wait Number of FreeRTOS ticks to block for alert
*
* @note Multiple alerts can be raised simultaneously. The application should
* check for all alerts that have been enabled.
*
* @return
* - ESP_OK: Alerts read
* - ESP_ERR_TIMEOUT: Timed out waiting for alerts
* - ESP_ERR_INVALID_ARG: Arguments are invalid
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed
*/
esp_err_t twai_read_alerts(uint32_t *alerts, TickType_t ticks_to_wait);
/**
* @brief Reconfigure which alerts are enabled
*
* This function reconfigures which alerts are enabled. If there are alerts
* which have not been read whilst reconfiguring, this function can read those
* alerts.
*
* @param[in] alerts_enabled Bit field of alerts to enable (see documentation for alert flags)
* @param[out] current_alerts Bit field of currently raised alerts. Set to NULL if unused
*
* @return
* - ESP_OK: Alerts reconfigured
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed
*/
esp_err_t twai_reconfigure_alerts(uint32_t alerts_enabled, uint32_t *current_alerts);
/**
* @brief Start the bus recovery process
*
* This function initiates the bus recovery process when the TWAI driver is in
* the bus-off state. Once initiated, the TWAI driver will enter the recovering
* state and wait for 128 occurrences of the bus-free signal on the TWAI bus
* before returning to the stopped state. This function will reset the TX queue,
* clearing any messages pending transmission.
*
* @note The BUS_RECOVERED alert can be enabled to alert the application when
* the bus recovery process completes.
*
* @return
* - ESP_OK: Bus recovery started
* - ESP_ERR_INVALID_STATE: TWAI driver is not in the bus-off state, or is not installed
*/
esp_err_t twai_initiate_recovery(void);
/**
* @brief Get current status information of the TWAI driver
*
* @param[out] status_info Status information
*
* @return
* - ESP_OK: Status information retrieved
* - ESP_ERR_INVALID_ARG: Arguments are invalid
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed
*/
esp_err_t twai_get_status_info(twai_status_info_t *status_info);
/**
* @brief Clear the transmit queue
*
* This function will clear the transmit queue of all messages.
*
* @note The transmit queue is automatically cleared when twai_stop() or
* twai_initiate_recovery() is called.
*
* @return
* - ESP_OK: Transmit queue cleared
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed or TX queue is disabled
*/
esp_err_t twai_clear_transmit_queue(void);
/**
* @brief Clear the receive queue
*
* This function will clear the receive queue of all messages.
*
* @note The receive queue is automatically cleared when twai_start() is
* called.
*
* @return
* - ESP_OK: Transmit queue cleared
* - ESP_ERR_INVALID_STATE: TWAI driver is not installed
*/
esp_err_t twai_clear_receive_queue(void);
#ifdef __cplusplus
}
#endif
-842
View File
@@ -1,842 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/ringbuf.h"
#include "hal/uart_types.h"
// Valid UART port number
#define UART_NUM_0 (0) /*!< UART port 0 */
#define UART_NUM_1 (1) /*!< UART port 1 */
#if SOC_UART_NUM > 2
#define UART_NUM_2 (2) /*!< UART port 2 */
#endif
#define UART_NUM_MAX (SOC_UART_NUM) /*!< UART port max */
/* @brief When calling `uart_set_pin`, instead of GPIO number, `UART_PIN_NO_CHANGE`
* can be provided to keep the currently allocated pin.
*/
#define UART_PIN_NO_CHANGE (-1)
#define UART_FIFO_LEN SOC_UART_FIFO_LEN ///< Length of the UART HW FIFO
#define UART_BITRATE_MAX SOC_UART_BITRATE_MAX ///< Maximum configurable bitrate
/**
* @brief UART interrupt configuration parameters for uart_intr_config function
*/
typedef struct {
uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/
uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold (unit: time of sending one byte)*/
uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/
uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/
} uart_intr_config_t;
/**
* @brief UART event types used in the ring buffer
*/
typedef enum {
UART_DATA, /*!< UART data event*/
UART_BREAK, /*!< UART break event*/
UART_BUFFER_FULL, /*!< UART RX buffer full event*/
UART_FIFO_OVF, /*!< UART FIFO overflow event*/
UART_FRAME_ERR, /*!< UART RX frame error event*/
UART_PARITY_ERR, /*!< UART RX parity event*/
UART_DATA_BREAK, /*!< UART TX data and break event*/
UART_PATTERN_DET, /*!< UART pattern detected */
#if SOC_UART_SUPPORT_WAKEUP_INT
UART_WAKEUP, /*!< UART wakeup event */
#endif
UART_EVENT_MAX, /*!< UART event max index*/
} uart_event_type_t;
/**
* @brief Event structure used in UART event queue
*/
typedef struct {
uart_event_type_t type; /*!< UART event type */
size_t size; /*!< UART data size for UART_DATA event*/
bool timeout_flag; /*!< UART data read timeout flag for UART_DATA event (no new data received during configured RX TOUT)*/
/*!< If the event is caused by FIFO-full interrupt, then there will be no event with the timeout flag before the next byte coming.*/
} uart_event_t;
typedef intr_handle_t uart_isr_handle_t;
/**
* @brief Install UART driver and set the UART to the default configuration.
*
* UART ISR handler will be attached to the same CPU core that this function is running on.
*
* @note Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param rx_buffer_size UART RX ring buffer size.
* @param tx_buffer_size UART TX ring buffer size.
* If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.
* @param queue_size UART event queue size/depth.
* @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide
* access to UART events. If set to NULL, driver will not use an event queue.
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here
* (the driver's ISR handler is not located in IRAM)
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags);
/**
* @brief Uninstall UART driver.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_driver_delete(uart_port_t uart_num);
/**
* @brief Checks whether the driver is installed or not
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - true driver is installed
* - false driver is not installed
*/
bool uart_is_driver_installed(uart_port_t uart_num);
/**
* @brief Set UART data bits.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param data_bit UART data bits
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit);
/**
* @brief Get the UART data bit configuration.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param data_bit Pointer to accept value of UART data bits.
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success, result will be put in (*data_bit)
*/
esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit);
/**
* @brief Set UART stop bits.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param stop_bits UART stop bits
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits);
/**
* @brief Get the UART stop bit configuration.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param stop_bits Pointer to accept value of UART stop bits.
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success, result will be put in (*stop_bit)
*/
esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bits);
/**
* @brief Set UART parity mode.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param parity_mode the enum of uart parity configuration
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success
*/
esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode);
/**
* @brief Get the UART parity mode configuration.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param parity_mode Pointer to accept value of UART parity mode.
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success, result will be put in (*parity_mode)
*
*/
esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode);
/**
* @brief Get the frequency of a clock source for the UART
*
* @param sclk Clock source
* @param[out] out_freq_hz Output of frequency, in Hz
*
* @return
* - ESP_ERR_INVALID_ARG: if the clock source is not supported
* - otherwise ESP_OK
*/
esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t* out_freq_hz);
/**
* @brief Set UART baud rate.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param baudrate UART baud rate.
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success
*/
esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate);
/**
* @brief Get the UART baud rate configuration.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param baudrate Pointer to accept value of UART baud rate
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success, result will be put in (*baudrate)
*
*/
esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate);
/**
* @brief Set UART line inverse mode
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param inverse_mask Choose the wires that need to be inverted. Using the ORred mask of `uart_signal_inv_t`
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask);
/**
* @brief Set hardware flow control.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param flow_ctrl Hardware flow control mode
* @param rx_thresh Threshold of Hardware RX flow control (0 ~ UART_FIFO_LEN).
* Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh);
/**
* @brief Set software flow control.
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param enable switch on or off
* @param rx_thresh_xon low water mark
* @param rx_thresh_xoff high water mark
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_sw_flow_ctrl(uart_port_t uart_num, bool enable, uint8_t rx_thresh_xon, uint8_t rx_thresh_xoff);
/**
* @brief Get the UART hardware flow control configuration.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param flow_ctrl Option for different flow control mode.
*
* @return
* - ESP_FAIL Parameter error
* - ESP_OK Success, result will be put in (*flow_ctrl)
*/
esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl);
/**
* @brief Clear UART interrupt status
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param clr_mask Bit mask of the interrupt status to be cleared.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask);
/**
* @brief Set UART interrupt enable
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param enable_mask Bit mask of the enable bits.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask);
/**
* @brief Clear UART interrupt enable bits
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param disable_mask Bit mask of the disable bits.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask);
/**
* @brief Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_rx_intr(uart_port_t uart_num);
/**
* @brief Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_disable_rx_intr(uart_port_t uart_num);
/**
* @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
*
* @param uart_num UART port number
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_disable_tx_intr(uart_port_t uart_num);
/**
* @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param enable 1: enable; 0: disable
* @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
/**
* @brief Assign signals of a UART peripheral to GPIO pins
*
* @note If the GPIO number configured for a UART signal matches one of the
* IOMUX signals for that GPIO, the signal will be connected directly
* via the IOMUX. Otherwise the GPIO and signal will be connected via
* the GPIO Matrix. For example, if on an ESP32 the call
* `uart_set_pin(0, 1, 3, -1, -1)` is performed, as GPIO1 is UART0's
* default TX pin and GPIO3 is UART0's default RX pin, both will be
* connected to respectively U0TXD and U0RXD through the IOMUX, totally
* bypassing the GPIO matrix.
* The check is performed on a per-pin basis. Thus, it is possible to have
* RX pin binded to a GPIO through the GPIO matrix, whereas TX is binded
* to its GPIO through the IOMUX.
*
* @note Internal signal can be output to multiple GPIO pads.
* Only one GPIO pad can connect with input signal.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param tx_io_num UART TX pin GPIO number.
* @param rx_io_num UART RX pin GPIO number.
* @param rts_io_num UART RTS pin GPIO number.
* @param cts_io_num UART CTS pin GPIO number.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);
/**
* @brief Manually set the UART RTS pin level.
* @note UART must be configured with hardware flow control disabled.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param level 1: RTS output low (active); 0: RTS output high (block)
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_rts(uart_port_t uart_num, int level);
/**
* @brief Manually set the UART DTR pin level.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param level 1: DTR output low; 0: DTR output high
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_dtr(uart_port_t uart_num, int level);
/**
* @brief Set UART idle interval after tx FIFO is empty
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param idle_num idle interval after tx FIFO is empty(unit: the time it takes to send one bit
* under current baudrate)
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_set_tx_idle_num(uart_port_t uart_num, uint16_t idle_num);
/**
* @brief Set UART configuration parameters.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param uart_config UART parameter settings
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
/**
* @brief Configure UART interrupts.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param intr_conf UART interrupt settings
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf);
/**
* @brief Wait until UART TX FIFO is empty.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param ticks_to_wait Timeout, count in RTOS ticks
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
* - ESP_ERR_TIMEOUT Timeout
*/
esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait);
/**
* @brief Send data to the UART port from a given buffer and length.
*
* This function will not wait for enough space in TX FIFO. It will just fill the available TX FIFO and return when the FIFO is full.
* @note This function should only be used when UART TX buffer is not enabled.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param buffer data buffer address
* @param len data length to send
*
* @return
* - (-1) Parameter error
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
*/
int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);
/**
* @brief Send data to the UART port from a given buffer and length,
*
* If the UART driver's parameter 'tx_buffer_size' is set to zero:
* This function will not return until all the data have been sent out, or at least pushed into TX FIFO.
*
* Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
* UART ISR will then move data from the ring buffer to TX FIFO gradually.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param src data buffer address
* @param size data length to send
*
* @return
* - (-1) Parameter error
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
*/
int uart_write_bytes(uart_port_t uart_num, const void* src, size_t size);
/**
* @brief Send data to the UART port from a given buffer and length,
*
* If the UART driver's parameter 'tx_buffer_size' is set to zero:
* This function will not return until all the data and the break signal have been sent out.
* After all data is sent out, send a break signal.
*
* Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
* UART ISR will then move data from the ring buffer to TX FIFO gradually.
* After all data sent out, send a break signal.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param src data buffer address
* @param size data length to send
* @param brk_len break signal duration(unit: the time it takes to send one bit at current baudrate)
*
* @return
* - (-1) Parameter error
* - OTHERS (>=0) The number of bytes pushed to the TX FIFO
*/
int uart_write_bytes_with_break(uart_port_t uart_num, const void* src, size_t size, int brk_len);
/**
* @brief UART read bytes from UART buffer
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param buf pointer to the buffer.
* @param length data length
* @param ticks_to_wait sTimeout, count in RTOS ticks
*
* @return
* - (-1) Error
* - OTHERS (>=0) The number of bytes read from UART buffer
*/
int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t ticks_to_wait);
/**
* @brief Alias of uart_flush_input.
* UART ring buffer flush. This will discard all data in the UART RX buffer.
* @note Instead of waiting the data sent out, this function will clear UART rx buffer.
* In order to send all the data in tx FIFO, we can use uart_wait_tx_done function.
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_flush(uart_port_t uart_num);
/**
* @brief Clear input buffer, discard all the data is in the ring-buffer.
* @note In order to send all the data in tx FIFO, we can use uart_wait_tx_done function.
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_flush_input(uart_port_t uart_num);
/**
* @brief UART get RX ring buffer cached data length
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param size Pointer of size_t to accept cached data length
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
/**
* @brief UART get TX ring buffer free space size
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param size Pointer of size_t to accept the free space size
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t uart_get_tx_buffer_free_size(uart_port_t uart_num, size_t *size);
/**
* @brief UART disable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detects a series of one same character, the interrupt will be triggered.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num);
/**
* @brief UART enable pattern detect function.
* Designed for applications like 'AT commands'.
* When the hardware detect a series of one same character, the interrupt will be triggered.
*
* @param uart_num UART port number.
* @param pattern_chr character of the pattern.
* @param chr_num number of the character, 8bit value.
* @param chr_tout timeout of the interval between each pattern characters, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is more than this value, it will not take this data as at_cmd char.
* @param post_idle idle time after the last pattern character, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is less than this value, it will not take the previous data as the last at_cmd char
* @param pre_idle idle time before the first pattern character, 16bit value, unit is the baud-rate cycle you configured.
* When the duration is less than this value, it will not take this data as the first at_cmd char.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Parameter error
*/
esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
/**
* @brief Return the nearest detected pattern position in buffer.
* The positions of the detected pattern are saved in a queue,
* this function will dequeue the first pattern position and move the pointer to next pattern position.
* @note If the RX buffer is full and flow control is not enabled,
* the detected pattern may not be found in the rx buffer due to overflow.
*
* The following APIs will modify the pattern position info:
* uart_flush_input, uart_read_bytes, uart_driver_delete, uart_pop_pattern_pos
* It is the application's responsibility to ensure atomic access to the pattern queue and the rx data buffer
* when using pattern detect feature.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @return
* - (-1) No pattern found for current index or parameter error
* - others the pattern position in rx buffer.
*/
int uart_pattern_pop_pos(uart_port_t uart_num);
/**
* @brief Return the nearest detected pattern position in buffer.
* The positions of the detected pattern are saved in a queue,
* This function do nothing to the queue.
* @note If the RX buffer is full and flow control is not enabled,
* the detected pattern may not be found in the rx buffer due to overflow.
*
* The following APIs will modify the pattern position info:
* uart_flush_input, uart_read_bytes, uart_driver_delete, uart_pop_pattern_pos
* It is the application's responsibility to ensure atomic access to the pattern queue and the rx data buffer
* when using pattern detect feature.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @return
* - (-1) No pattern found for current index or parameter error
* - others the pattern position in rx buffer.
*/
int uart_pattern_get_pos(uart_port_t uart_num);
/**
* @brief Allocate a new memory with the given length to save record the detected pattern position in rx buffer.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param queue_length Max queue length for the detected pattern.
* If the queue length is not large enough, some pattern positions might be lost.
* Set this value to the maximum number of patterns that could be saved in data buffer at the same time.
* @return
* - ESP_ERR_NO_MEM No enough memory
* - ESP_ERR_INVALID_STATE Driver not installed
* - ESP_FAIL Parameter error
* - ESP_OK Success
*/
esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length);
/**
* @brief UART set communication mode
*
* @note This function must be executed after uart_driver_install(), when the driver object is initialized.
* @param uart_num Uart number to configure, the max port number is (UART_NUM_MAX -1).
* @param mode UART UART mode to set
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode);
/**
* @brief Set uart threshold value for RX fifo full
* @note If application is using higher baudrate and it is observed that bytes
* in hardware RX fifo are overwritten then this threshold can be reduced
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param threshold Threshold value above which RX fifo full interrupt is generated
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Driver is not installed
*/
esp_err_t uart_set_rx_full_threshold(uart_port_t uart_num, int threshold);
/**
* @brief Set uart threshold values for TX fifo empty
*
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
* @param threshold Threshold value below which TX fifo empty interrupt is generated
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Driver is not installed
*/
esp_err_t uart_set_tx_empty_threshold(uart_port_t uart_num, int threshold);
/**
* @brief UART set threshold timeout for TOUT feature
*
* @param uart_num Uart number to configure, the max port number is (UART_NUM_MAX -1).
* @param tout_thresh This parameter defines timeout threshold in uart symbol periods. The maximum value of threshold is 126.
* tout_thresh = 1, defines TOUT interrupt timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
* If the time is expired the UART_RXFIFO_TOUT_INT interrupt is triggered. If tout_thresh == 0,
* the TOUT feature is disabled.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Driver is not installed
*/
esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh);
/**
* @brief Returns collision detection flag for RS485 mode
* Function returns the collision detection flag into variable pointed by collision_flag.
* *collision_flag = true, if collision detected else it is equal to false.
* This function should be executed when actual transmission is completed (after uart_write_bytes()).
*
* @param uart_num Uart number to configure the max port number is (UART_NUM_MAX -1).
* @param collision_flag Pointer to variable of type bool to return collision flag.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag);
/**
* @brief Set the number of RX pin signal edges for light sleep wakeup
*
* UART can be used to wake up the system from light sleep. This feature works
* by counting the number of positive edges on RX pin and comparing the count to
* the threshold. When the count exceeds the threshold, system is woken up from
* light sleep. This function allows setting the threshold value.
*
* Stop bit and parity bits (if enabled) also contribute to the number of edges.
* For example, letter 'a' with ASCII code 97 is encoded as 0100001101 on the wire
* (with 8n1 configuration), start and stop bits included. This sequence has 3
* positive edges (transitions from 0 to 1). Therefore, to wake up the system
* when 'a' is sent, set wakeup_threshold=3.
*
* The character that triggers wakeup is not received by UART (i.e. it can not
* be obtained from UART FIFO). Depending on the baud rate, a few characters
* after that will also not be received. Note that when the chip enters and exits
* light sleep mode, APB frequency will be changing. To make sure that UART has
* correct baud rate all the time, select UART_SCLK_REF_TICK or UART_SCLK_XTAL as UART clock source in uart_config_t::source_clk.
*
* @note in ESP32, the wakeup signal can only be input via IO_MUX (i.e.
* GPIO3 should be configured as function_1 to wake up UART0,
* GPIO9 should be configured as function_5 to wake up UART1), UART2
* does not support light sleep wakeup feature.
*
* @param uart_num UART number, the max port number is (UART_NUM_MAX -1).
* @param wakeup_threshold number of RX edges for light sleep wakeup, value is 3 .. 0x3ff.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if uart_num is incorrect or wakeup_threshold is
* outside of [3, 0x3ff] range.
*/
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold);
/**
* @brief Get the number of RX pin signal edges for light sleep wakeup.
*
* See description of uart_set_wakeup_threshold for the explanation of UART
* wakeup feature.
*
* @param uart_num UART number, the max port number is (UART_NUM_MAX -1).
* @param[out] out_wakeup_threshold output, set to the current value of wakeup
* threshold for the given UART.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if out_wakeup_threshold is NULL
*/
esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int* out_wakeup_threshold);
/**
* @brief Wait until UART tx memory empty and the last char send ok (polling mode).
*
* @param uart_num UART number
*
* * @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Driver not installed
*/
esp_err_t uart_wait_tx_idle_polling(uart_port_t uart_num);
/**
* @brief Configure TX signal loop back to RX module, just for the test usage.
*
* @param uart_num UART number
* @param loop_back_en Set ture to enable the loop back function, else set it false.
*
* * @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Driver not installed
*/
esp_err_t uart_set_loop_back(uart_port_t uart_num, bool loop_back_en);
/**
* @brief Configure behavior of UART RX timeout interrupt.
*
* When always_rx_timeout is true, timeout interrupt is triggered even if FIFO is full.
* This function can cause extra timeout interrupts triggered only to send the timeout event.
* Call this function only if you want to ensure timeout interrupt will always happen after a byte stream.
*
* @param uart_num UART number
* @param always_rx_timeout_en Set to false enable the default behavior of timeout interrupt,
* set it to true to always trigger timeout interrupt.
*
*/
void uart_set_always_rx_timeout(uart_port_t uart_num, bool always_rx_timeout_en);
#ifdef __cplusplus
}
#endif
@@ -1,41 +0,0 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _UART_SELECT_H_
#define _UART_SELECT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "driver/uart.h"
typedef enum {
UART_SELECT_READ_NOTIF,
UART_SELECT_WRITE_NOTIF,
UART_SELECT_ERROR_NOTIF,
} uart_select_notif_t;
typedef void (*uart_select_notif_callback_t)(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken);
/**
* @brief Set notification callback function for select() events
* @param uart_num UART port number
* @param uart_select_notif_callback callback function
*/
void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback);
/**
* @brief Get mutex guarding select() notifications
*/
portMUX_TYPE *uart_get_selectlock(void);
#ifdef __cplusplus
}
#endif
#endif //_UART_SELECT_H_
@@ -1,85 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configuration structure for the usb-serial-jtag-driver. Can be expanded in the future
*
* @note tx_buffer_size and rx_buffer_size must be > 0
*/
typedef struct {
uint32_t tx_buffer_size; /* Size of the buffer (in bytes) for the TX direction */
uint32_t rx_buffer_size; /* Size of the buffer (in bytes) for the RX direction */
} usb_serial_jtag_driver_config_t;
#define USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT() (usb_serial_jtag_driver_config_t) {\
.tx_buffer_size = 256,\
.rx_buffer_size = 256,\
}
/**
* @brief Install USB-SERIAL-JTAG driver and set the USB-SERIAL-JTAG to the default configuration.
*
* USB-SERIAL-JTAG driver's ISR will be attached to the same CPU core that calls this function. Thus, users
* should ensure that the same core is used when calling `usb_serial_jtag_driver_uninstall()`.
*
* @note Blocking mode will result in usb_serial_jtag_write_bytes() blocking until all bytes have been written to the TX FIFO.
*
* @param usb_serial_jtag_driver_config_t Configuration for usb_serial_jtag driver.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Failed for some reason.
*/
esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_serial_jtag_config);
/**
* @brief USB_SERIAL_JTAG read bytes from USB_SERIAL_JTAG buffer
*
* @param buf pointer to the buffer.
* @param length data length
* @param ticks_to_wait Timeout in RTOS ticks
*
* @return
* - The number of bytes read from USB_SERIAL FIFO
*/
int usb_serial_jtag_read_bytes(void* buf, uint32_t length, TickType_t ticks_to_wait);
/**
* @brief Send data to the USB-UART port from a given buffer and length,
*
* Please ensure the `tx_buffer_size is larger than 0`, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer,
* USB_SERIAL_JTAG ISR will then move data from the ring buffer to TX FIFO gradually.
*
* @param src data buffer address
* @param size data length to send
* @param ticks_to_wait Timeout in RTOS ticks
*
* @return
* - The number of bytes pushed to the TX FIFO
*/
int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t ticks_to_wait);
/**
* @brief Uninstall USB-SERIAL-JTAG driver.
*
* @return
* - ESP_OK Success
*/
esp_err_t usb_serial_jtag_driver_uninstall(void);
#ifdef __cplusplus
}
#endif