mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-15 16:34:05 +00:00
refactor(i2c): Make i2c hal layer independent
This commit is contained in:
206
components/esp_hal_i2c/include/hal/i2c_hal.h
Normal file
206
components/esp_hal_i2c/include/hal/i2c_hal.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in hal/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for I2C
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#if SOC_I2C_SUPPORTED
|
||||
#include "hal/i2c_ll.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_I2C_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief I2C hal Context definition
|
||||
*/
|
||||
typedef struct {
|
||||
i2c_dev_t *dev;
|
||||
} i2c_hal_context_t;
|
||||
|
||||
/**
|
||||
* @brief I2C hal clock configurations
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t clk_sel; // clock select
|
||||
uint8_t clk_active; // clock active
|
||||
hal_utils_clk_div_t clk_div; // clock dividers
|
||||
} i2c_hal_sclk_info_t;
|
||||
|
||||
/**
|
||||
* @brief Timing configuration structure. Used for I2C reset internally.
|
||||
*/
|
||||
typedef struct {
|
||||
int high_period; /*!< high_period time */
|
||||
int low_period; /*!< low_period time */
|
||||
int wait_high_period; /*!< wait_high_period time */
|
||||
int rstart_setup; /*!< restart setup */
|
||||
int start_hold; /*!< start hold time */
|
||||
int stop_setup; /*!< stop setup */
|
||||
int stop_hold; /*!< stop hold time */
|
||||
int sda_sample; /*!< high_period time */
|
||||
int sda_hold; /*!< sda hold time */
|
||||
int timeout; /*!< timeout value */
|
||||
i2c_hal_sclk_info_t clk_cfg; /*!< clock configuration */
|
||||
} i2c_hal_timing_config_t;
|
||||
|
||||
#if SOC_I2C_SUPPORT_SLAVE
|
||||
|
||||
/**
|
||||
* @brief Init the I2C slave.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2c_num I2C port number
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_slave_init(i2c_hal_context_t *hal);
|
||||
|
||||
#endif // SOC_I2C_SUPPORT_SLAVE
|
||||
|
||||
/**
|
||||
* @brief Init the I2C master.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param i2c_num I2C port number
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_master_init(i2c_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief Set I2C bus timing with the given frequency
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param scl_freq The scl frequency to be set
|
||||
* @param src_clk The source clock of I2C
|
||||
* @param source_freq Source clock frequency of I2C
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void _i2c_hal_set_bus_timing(i2c_hal_context_t *hal, int scl_freq, i2c_clock_source_t src_clk, int source_freq);
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define i2c_hal_set_bus_timing(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _i2c_hal_set_bus_timing(__VA_ARGS__);} while(0)
|
||||
#else
|
||||
#define i2c_hal_set_bus_timing(...) _i2c_hal_set_bus_timing(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C hardware FSM reset
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_master_fsm_rst(i2c_hal_context_t *hal);
|
||||
|
||||
/**
|
||||
* @brief I2C master handle tx interrupt event
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param event Pointer to accept the interrupt event
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event);
|
||||
|
||||
/**
|
||||
* @brief I2C master handle rx interrupt event
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param event Pointer to accept the interrupt event
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event);
|
||||
|
||||
/**
|
||||
* @brief Set scl timeout reg value according to given timeout us and source clock frequency
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param timeout_us timeout us
|
||||
* @param sclk_clock_hz source clock hz
|
||||
*/
|
||||
void i2c_hal_master_set_scl_timeout_val(i2c_hal_context_t *hal, uint32_t timeout_us, uint32_t sclk_clock_hz);
|
||||
|
||||
/**
|
||||
* @brief Init I2C hal layer
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param i2c_port I2C port number.
|
||||
*/
|
||||
void _i2c_hal_init(i2c_hal_context_t *hal, int i2c_port);
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define i2c_hal_init(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _i2c_hal_init(__VA_ARGS__);} while(0)
|
||||
#else
|
||||
#define i2c_hal_init(...) _i2c_hal_init(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Deinit I2C hal layer
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void _i2c_hal_deinit(i2c_hal_context_t *hal);
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define i2c_hal_deinit(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _i2c_hal_deinit(__VA_ARGS__);} while(0)
|
||||
#else
|
||||
#define i2c_hal_deinit(...) _i2c_hal_deinit(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Start I2C master transaction
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
*/
|
||||
void i2c_hal_master_trans_start(i2c_hal_context_t *hal);
|
||||
|
||||
#if !SOC_I2C_SUPPORT_HW_FSM_RST
|
||||
|
||||
/**
|
||||
* @brief Get timing configuration
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param timing_config Pointer to timing config structure.
|
||||
*/
|
||||
void i2c_hal_get_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config);
|
||||
|
||||
/**
|
||||
* @brief Set timing configuration
|
||||
*
|
||||
* @param hal Context of the HAL
|
||||
* @param timing_config Timing config structure.
|
||||
*/
|
||||
void i2c_hal_set_timing_config(i2c_hal_context_t *hal, i2c_hal_timing_config_t *timing_config);
|
||||
|
||||
#endif // !SOC_I2C_SUPPORT_HW_FSM_RST
|
||||
|
||||
#endif // #if SOC_I2C_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
136
components/esp_hal_i2c/include/hal/i2c_types.h
Normal file
136
components/esp_hal_i2c/include/hal/i2c_types.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/hal_utils.h"
|
||||
|
||||
/**
|
||||
* @brief I2C port number, can be I2C_NUM_0 ~ (I2C_NUM_MAX-1).
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_NUM_0 = 0, /*!< I2C port 0 */
|
||||
#if SOC_HP_I2C_NUM >= 2
|
||||
I2C_NUM_1, /*!< I2C port 1 */
|
||||
#endif /* SOC_HP_I2C_NUM >= 2 */
|
||||
#if SOC_LP_I2C_NUM >= 1
|
||||
LP_I2C_NUM_0, /*< LP_I2C port 0 */
|
||||
#endif /* SOC_LP_I2C_NUM >= 1 */
|
||||
I2C_NUM_MAX, /*!< I2C port max */
|
||||
} i2c_port_t;
|
||||
|
||||
/**
|
||||
* @brief Enumeration for I2C device address bit length
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_ADDR_BIT_LEN_7 = 0, /*!< i2c address bit length 7 */
|
||||
#if SOC_I2C_SUPPORT_10BIT_ADDR
|
||||
I2C_ADDR_BIT_LEN_10 = 1, /*!< i2c address bit length 10 */
|
||||
#endif
|
||||
} i2c_addr_bit_len_t;
|
||||
|
||||
/**
|
||||
* @brief Data structure for calculating I2C bus timing.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t clkm_div; /*!< I2C core clock divider */
|
||||
uint16_t scl_low; /*!< I2C scl low period */
|
||||
uint16_t scl_high; /*!< I2C scl high period */
|
||||
uint16_t scl_wait_high; /*!< I2C scl wait_high period */
|
||||
uint16_t sda_hold; /*!< I2C scl low period */
|
||||
uint16_t sda_sample; /*!< I2C sda sample time */
|
||||
uint16_t setup; /*!< I2C start and stop condition setup period */
|
||||
uint16_t hold; /*!< I2C start and stop condition hold period */
|
||||
uint16_t tout; /*!< I2C bus timeout period */
|
||||
} i2c_hal_clk_config_t;
|
||||
|
||||
typedef enum {
|
||||
#if SOC_I2C_SUPPORT_SLAVE
|
||||
I2C_MODE_SLAVE = 0, /*!< I2C slave mode */
|
||||
#endif
|
||||
I2C_MODE_MASTER, /*!< I2C master mode */
|
||||
I2C_MODE_MAX,
|
||||
} i2c_mode_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_MASTER_WRITE = 0, /*!< I2C write data */
|
||||
I2C_MASTER_READ, /*!< I2C read data */
|
||||
} i2c_rw_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_DATA_MODE_MSB_FIRST = 0, /*!< I2C data msb first */
|
||||
I2C_DATA_MODE_LSB_FIRST = 1, /*!< I2C data lsb first */
|
||||
I2C_DATA_MODE_MAX
|
||||
} i2c_trans_mode_t;
|
||||
|
||||
__attribute__((deprecated("please use 'i2c_addr_bit_len_t' instead")))
|
||||
typedef enum {
|
||||
I2C_ADDR_BIT_7 = 0, /*!< I2C 7bit address for slave mode */
|
||||
I2C_ADDR_BIT_10, /*!< I2C 10bit address for slave mode */
|
||||
I2C_ADDR_BIT_MAX,
|
||||
} i2c_addr_mode_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_MASTER_ACK = 0x0, /*!< I2C ack for each byte read */
|
||||
I2C_MASTER_NACK = 0x1, /*!< I2C nack for each byte read */
|
||||
I2C_MASTER_LAST_NACK = 0x2, /*!< I2C nack for the last byte*/
|
||||
I2C_MASTER_ACK_MAX,
|
||||
} i2c_ack_type_t;
|
||||
|
||||
/**
|
||||
* @brief Enum for I2C slave stretch causes
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_SLAVE_STRETCH_CAUSE_ADDRESS_MATCH = 0, /*!< Stretching SCL low when the slave is read by the master and the address just matched */
|
||||
I2C_SLAVE_STRETCH_CAUSE_TX_EMPTY = 1, /*!< Stretching SCL low when TX FIFO is empty in slave mode */
|
||||
I2C_SLAVE_STRETCH_CAUSE_RX_FULL = 2, /*!< Stretching SCL low when RX FIFO is full in slave mode */
|
||||
I2C_SLAVE_STRETCH_CAUSE_SENDING_ACK = 3, /*!< Stretching SCL low when slave sending ACK */
|
||||
} i2c_slave_stretch_cause_t;
|
||||
|
||||
typedef enum {
|
||||
I2C_SLAVE_WRITE_BY_MASTER = 0,
|
||||
I2C_SLAVE_READ_BY_MASTER = 1,
|
||||
} i2c_slave_read_write_status_t;
|
||||
|
||||
/**
|
||||
* @brief Enum for i2c working modes.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_BUS_MODE_MASTER = 0, /*!< I2C works under master mode */
|
||||
I2C_BUS_MODE_SLAVE = 1, /*!< I2C works under slave mode */
|
||||
} i2c_bus_mode_t;
|
||||
|
||||
#if SOC_I2C_SUPPORTED
|
||||
/**
|
||||
* @brief I2C group clock source
|
||||
*/
|
||||
typedef soc_periph_i2c_clk_src_t i2c_clock_source_t;
|
||||
|
||||
#if SOC_LP_I2C_SUPPORTED
|
||||
/**
|
||||
* @brief LP_UART source clock
|
||||
*/
|
||||
typedef soc_periph_lp_i2c_clk_src_t lp_i2c_clock_source_t;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief Default type
|
||||
*/
|
||||
typedef int i2c_clock_source_t;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user