summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDyyt587 <[email protected]>2024-03-08 11:59:47 +0800
committerGitHub <[email protected]>2024-03-07 22:59:47 -0500
commit4e1626703f59e763e4ccc96f2176a67e7cde51d9 (patch)
tree6f87d670c38bba0367c8f81233b852281d54fd5e
parent384a370c9a0bd92ff984d6ecfc077ba54a1f538a (diff)
[bsp][stm32] add hardware i2c driver
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/SConscript4
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c726
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.h66
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/i2c_hard_config.h137
4 files changed, 933 insertions, 0 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
index 8e5cc4efa3..e4958d30bf 100644
--- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
@@ -35,6 +35,10 @@ if GetDepend('RT_USING_SPI_BITOPS'):
if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
if GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3') or GetDepend('BSP_USING_I2C4'):
src += ['drv_soft_i2c.c']
+
+if GetDepend(['RT_USING_I2C']):
+ if GetDepend('BSP_USING_HARD_I2C1') or GetDepend('BSP_USING_HARD_I2C2') or GetDepend('BSP_USING_HARD_I2C3') or GetDepend('BSP_USING_HARD_I2C4'):
+ src += ['drv_hard_i2c.c']
if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']):
src += ['drv_eth.c']
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c
new file mode 100644
index 0000000000..38b08efb66
--- /dev/null
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-02-17 Dyyt587 first version
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <board.h>
+#include <rtconfig.h>
+#include "drv_hard_i2c.h"
+#include "drv_config.h"
+#include "i2c_hard_config.h"
+#include <string.h>
+
+#ifdef (RT_USING_I2C && BSP_USING_I2C)
+/* not fully support for I2C4 */
+#if defined(BSP_USING_HARD_I2C1) || defined(BSP_USING_HARD_I2C2) || defined(BSP_USING_HARD_I2C3)
+
+//#define DRV_DEBUG
+#define LOG_TAG "drv.i2c"
+#include <drv_log.h>
+
+enum
+{
+#ifdef BSP_USING_HARD_I2C1
+ I2C1_INDEX,
+#endif /* BSP_USING_HARD_I2C1 */
+#ifdef BSP_USING_HARD_I2C2
+ I2C2_INDEX,
+#endif /* BSP_USING_HARD_I2C2 */
+#ifdef BSP_USING_HARD_I2C3
+ I2C3_INDEX,
+#endif /* BSP_USING_HARD_I2C3 */
+
+};
+
+static struct stm32_i2c_config i2c_config[] =
+ {
+#ifdef BSP_USING_HARD_I2C1
+ I2C1_BUS_CONFIG,
+#endif /* BSP_USING_HARD_I2C1 */
+#ifdef BSP_USING_HARD_I2C2
+ I2C2_BUS_CONFIG,
+#endif /* BSP_USING_HARD_I2C2 */
+#ifdef BSP_USING_HARD_I2C3
+ I2C3_BUS_CONFIG,
+#endif /* BSP_USING_HARD_I2C3 */
+
+};
+
+static struct stm32_i2c i2c_objs[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};
+
+
+static rt_err_t stm32_i2c_init(struct stm32_i2c *i2c_drv)
+{
+ RT_ASSERT(i2c_drv != RT_NULL);
+
+ I2C_HandleTypeDef *i2c_handle = &i2c_drv->handle;
+ rt_memset(i2c_handle, 0, sizeof(I2C_HandleTypeDef));
+ struct stm32_i2c_config *cfg = i2c_drv->config;
+ i2c_handle->Instance = cfg->Instance;
+ i2c_handle->Init.Timing = cfg->timing;
+ i2c_handle->Init.OwnAddress1 = 0;
+ i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ i2c_handle->Init.OwnAddress2 = 0;
+ i2c_handle->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
+ i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ if (HAL_I2C_DeInit(i2c_handle) != HAL_OK)
+ {
+ return -RT_EFAULT;
+ }
+
+ if (HAL_I2C_Init(i2c_handle) != HAL_OK)
+ {
+ return -RT_EFAULT;
+ }
+
+ /* Configure Analogue filter */
+ if (HAL_I2CEx_ConfigAnalogFilter(i2c_handle, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
+ {
+ return -RT_EFAULT;
+ }
+
+ /* Configure Digital filter */
+ if (HAL_I2CEx_ConfigDigitalFilter(i2c_handle, 0) != HAL_OK)
+ {
+ return -RT_EFAULT;
+ }
+
+ /* I2C2 DMA Init */
+ if (i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG)
+ {
+ HAL_DMA_Init(&i2c_drv->dma.handle_rx);
+
+ __HAL_LINKDMA(&i2c_drv->handle, hdmarx, i2c_drv->dma.handle_rx);
+
+ /* NVIC configuration for DMA transfer complete interrupt */
+ HAL_NVIC_SetPriority(i2c_drv->config->dma_rx->dma_irq, 0, 0);
+ HAL_NVIC_EnableIRQ(i2c_drv->config->dma_rx->dma_irq);
+ }
+
+ if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG)
+ {
+ HAL_DMA_Init(&i2c_drv->dma.handle_tx);
+
+ __HAL_LINKDMA(&i2c_drv->handle, hdmatx, i2c_drv->dma.handle_tx);
+
+ /* NVIC configuration for DMA transfer complete interrupt */
+ HAL_NVIC_SetPriority(i2c_drv->config->dma_tx->dma_irq, 1, 0);
+ HAL_NVIC_EnableIRQ(i2c_drv->config->dma_tx->dma_irq);
+ }
+
+ if (i2c_drv->i2c_dma_flag & I2C_USING_TX_DMA_FLAG || i2c_drv->i2c_dma_flag & I2C_USING_RX_DMA_FLAG)
+ {
+ HAL_NVIC_SetPriority(i2c_drv->config->evirq_type, 2, 0);
+ HAL_NVIC_EnableIRQ(i2c_drv->config->evirq_type);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t stm32_i2c_configure(struct rt_i2c_bus_device *bus)
+{
+ int ret = -RT_ERROR;
+ RT_ASSERT(RT_NULL != bus);
+ struct stm32_i2c *i2c_drv = rt_container_of(bus, struct stm32_i2c, i2c_bus);
+
+ return stm32_i2c_init(i2c_drv);
+}
+/**
+ * @brief Hardware I2C driver transfer
+ *
+ * @param bus Device bus
+ * @param msgs Data to be transferred
+ * @param num Number of data
+ * @return rt_ssize_t Transfer status
+ */
+static rt_ssize_t stm32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
+ struct rt_i2c_msg msgs[],
+ rt_uint32_t num)
+{
+ /* for stm32 dma may more stability */
+#define DMA_TRANS_MIN_LEN 2 /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */
+#define TRANS_TIMEOUT_PERSEC 8 /* per ms will trans nums bytes */
+
+ rt_int32_t i, ret;
+ struct rt_i2c_msg *msg = msgs;
+ struct rt_i2c_msg *next_msg = 0;
+ struct stm32_i2c *i2c_obj;
+ uint32_t mode = 0;
+ uint8_t next_flag = 0;
+ struct rt_completion *completion;
+ if (num == 0)
+ {
+ return 0;
+ }
+ RT_ASSERT((msgs != RT_NULL) && (bus != RT_NULL));
+ i2c_obj = rt_container_of(bus, struct stm32_i2c, i2c_bus);
+ completion = &i2c_obj->completion;
+ I2C_HandleTypeDef *handle = &i2c_obj->handle;
+ rt_uint32_t timeout;
+ LOG_D("xfer start %d mags", num);
+ for (i = 0; i < (num - 1); i++)
+ {
+ mode = 0;
+
+ msg = &msgs[i];
+ LOG_D("xfer msgs[%d] addr=0x%2x buf=0x%x len= 0x%x flags= 0x%x", i, msg->addr, msg->buf, msg->len, msg->flags);
+ next_msg = &msgs[i + 1];
+ next_flag = next_msg->flags;
+ timeout = msg->len/TRANS_TIMEOUT_PERSEC+1;
+ if (next_flag & RT_I2C_NO_START)
+ {
+ if ((next_flag & RT_I2C_RD) == (msg->flags & RT_I2C_RD))
+ { /* The same mode, can use no start */
+ mode = I2C_FIRST_AND_NEXT_FRAME;
+ }
+ else
+ {
+ /* Not allowed to use no start, sending address is required when changing direction, user setting error */
+ LOG_W("user set flags error msg[%d] flags RT_I2C_NO_START has canceled", i + 1);
+ mode = I2C_LAST_FRAME_NO_STOP;
+ }
+ }
+ else
+ {
+ mode = I2C_LAST_FRAME_NO_STOP;
+ }
+
+ if (msg->flags & RT_I2C_RD)
+ {
+ LOG_D("xfer rec msgs[%d] hal mode = %s", i, mode == I2C_FIRST_AND_NEXT_FRAME ? "I2C_FIRST_AND_NEXT_FRAME" : mode == I2C_LAST_FRAME_NO_STOP ? "I2C_FIRST_FRAME/I2C_LAST_FRAME_NO_STOP"
+ : mode == I2C_LAST_FRAME ? "I2C_LAST_FRAME"
+ : "nuknown mode");
+ if ((i2c_obj->i2c_dma_flag & I2C_USING_RX_DMA_FLAG) && (msg->len >= DMA_TRANS_MIN_LEN))
+ {
+ ret = HAL_I2C_Master_Seq_Receive_DMA(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ else
+ {
+ ret = HAL_I2C_Master_Seq_Receive_IT(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ if (ret != RT_EOK)
+ {
+ LOG_E("[%s:%d]I2C Read error(%d)!\n", __func__, __LINE__, ret);
+ goto out;
+ }
+ if (rt_completion_wait(completion, timeout) != RT_EOK)
+ {
+ LOG_D("receive time out");
+ goto out;
+
+ }
+ }
+ else
+ {
+ LOG_D("xfer trans msgs[%d] hal mode = %s", i, mode == I2C_FIRST_AND_NEXT_FRAME ? "I2C_FIRST_AND_NEXT_FRAME" : mode == I2C_LAST_FRAME_NO_STOP ? "I2C_FIRST_FRAME/I2C_LAST_FRAME_NO_STOP"
+ : mode == I2C_LAST_FRAME ? "I2C_LAST_FRAME"
+ : "nuknown mode");
+ if ((i2c_obj->i2c_dma_flag & I2C_USING_TX_DMA_FLAG) && (msg->len >= DMA_TRANS_MIN_LEN))
+ {
+ ret = HAL_I2C_Master_Seq_Transmit_DMA(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ else
+ {
+ ret = HAL_I2C_Master_Seq_Transmit_IT(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ if (ret != RT_EOK)
+ {
+ LOG_D("[%s:%d]I2C Write error(%d)!\n", __func__, __LINE__, ret);
+ goto out;
+ }
+ if (rt_completion_wait(completion, timeout) != RT_EOK)
+ {
+ LOG_D("transmit time out");
+ goto out;
+
+ }
+ }
+ LOG_D("xfer next msgs[%d] addr=0x%2x buf= 0x%x len= 0x%x flags = 0x%x\r\n", i + 1, next_msg->addr, next_msg->buf, next_msg->len, next_msg->flags);
+ }
+ /* last msg */
+ msg = &msgs[i];
+ timeout = msg->len/TRANS_TIMEOUT_PERSEC+1;
+ if (msg->flags & RT_I2C_NO_STOP)
+ mode = I2C_LAST_FRAME_NO_STOP;
+ else
+ mode = I2C_LAST_FRAME;
+ LOG_D("xfer last msgs[%d] addr=0x%2x buf= 0x%x len= 0x%x flags = 0x%x", i, msg->addr, msg->buf, msg->len, msg->flags);
+ if (msg->flags & RT_I2C_RD)
+ {
+ LOG_D("xfer rec msgs[%d] hal mode=%s", i, mode == I2C_FIRST_AND_NEXT_FRAME ? "I2C_FIRST_AND_NEXT_FRAME" : mode == I2C_LAST_FRAME_NO_STOP ? "I2C_FIRST_FRAME/I2C_LAST_FRAME_NO_STOP"
+ : mode == I2C_LAST_FRAME ? "I2C_LAST_FRAME"
+ : "nuknown mode");
+ if ((i2c_obj->i2c_dma_flag & I2C_USING_RX_DMA_FLAG) && (msg->len >= DMA_TRANS_MIN_LEN))
+ {
+ ret = HAL_I2C_Master_Seq_Receive_DMA(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ else
+ {
+ ret = HAL_I2C_Master_Seq_Receive_IT(handle,(msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ if (ret != RT_EOK)
+ {
+ LOG_D("[%s:%d]I2C Read error(%d)!\n", __func__, __LINE__, ret);
+ goto out;
+ }
+ if (rt_completion_wait(completion, timeout) != RT_EOK)
+ {
+ LOG_D("receive time out");
+ goto out;
+
+ }
+ }
+ else
+ {
+ LOG_D("xfer trans msgs[%d] hal mode = %s", i, mode == I2C_FIRST_AND_NEXT_FRAME ? "I2C_FIRST_AND_NEXT_FRAME" : mode == I2C_LAST_FRAME ? "I2C_LAST_FRAME"
+ : mode == I2C_LAST_FRAME_NO_STOP ? "I2C_FIRST_FRAME/I2C_LAST_FRAME_NO_STOP"
+ : "nuknown mode");
+ if ((i2c_obj->i2c_dma_flag & I2C_USING_TX_DMA_FLAG) && (msg->len >= DMA_TRANS_MIN_LEN))
+ {
+ ret = HAL_I2C_Master_Seq_Transmit_DMA(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ else
+ {
+ ret = HAL_I2C_Master_Seq_Transmit_IT(handle, (msg->addr<<1) , msg->buf, msg->len, mode);
+ }
+ if (ret != RT_EOK)
+ {
+ LOG_D("[%s:%d]I2C Write error(%d)!\n", __func__, __LINE__, ret);
+ goto out;
+ }
+ if (rt_completion_wait(completion, timeout) != RT_EOK)
+ {
+ LOG_D("transmit time out");
+ goto out;
+
+ }
+ }
+ ret = num;
+ LOG_D("xfer end %d mags\r\n", num);
+ return ret;
+out:
+
+ if (handle->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ LOG_D("I2C NACK Error now stoped");
+ /* Send stop signal to prevent bus lock-up */
+ handle->Instance->CR1 |= I2C_IT_STOPI;
+ }
+ if (handle->ErrorCode == HAL_I2C_ERROR_BERR)
+ {
+ LOG_D("I2C BUS Error now stoped");
+ handle->Instance->CR1 |= I2C_IT_STOPI;
+ ret=i-1;
+ return ret;
+}
+
+static const struct rt_i2c_bus_device_ops stm32_i2c_ops =
+ {
+ .master_xfer = stm32_i2c_master_xfer,
+ RT_NULL,
+ RT_NULL};
+
+int RT_hw_i2c_bus_init(void)
+{
+ int ret = -RT_ERROR;
+ rt_size_t obj_num = sizeof(i2c_objs) / sizeof(i2c_objs[0]);
+
+ for (int i = 0; i < obj_num; i++)
+ {
+ i2c_objs[i].i2c_bus.ops = &stm32_i2c_ops;
+ i2c_objs[i].config = &i2c_config[i];
+ i2c_objs[i].i2c_bus.timeout = i2c_config[i].timeout;
+
+ if (i2c_objs[i].i2c_dma_flag & I2C_USING_TX_DMA_FLAG)
+ {
+ i2c_objs[i].dma.handle_tx.Instance = i2c_config[i].dma_tx->Instance;
+#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
+ i2c_objs[i].dma.handle_tx.Init.Channel = i2c_config[i].dma_tx->channel;
+#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
+ i2c_objs[i].dma.handle_tx.Init.Request = i2c_config[i].dma_tx->request;
+#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) */
+#ifndef SOC_SERIES_STM32U5
+ i2c_objs[i].dma.handle_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ i2c_objs[i].dma.handle_tx.Init.PeriphInc = DMA_PINC_DISABLE;
+ i2c_objs[i].dma.handle_tx.Init.MemInc = DMA_MINC_ENABLE;
+ i2c_objs[i].dma.handle_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ i2c_objs[i].dma.handle_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ i2c_objs[i].dma.handle_tx.Init.Mode = DMA_NORMAL;
+ i2c_objs[i].dma.handle_tx.Init.Priority = DMA_PRIORITY_LOW;
+#endif
+#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
+
+ i2c_objs[i].dma.handle_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+ i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
+ i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
+#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */
+ }
+ if ((i2c_objs[i].i2c_dma_flag & I2C_USING_RX_DMA_FLAG))
+ {
+ i2c_objs[i].dma.handle_rx.Instance = i2c_config[i].dma_rx->Instance;
+#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
+ i2c_objs[i].dma.handle_rx.Init.Channel = i2c_config[i].dma_rx->channel;
+#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
+ i2c_objs[i].dma.handle_rx.Init.Request = i2c_config[i].dma_rx->request;
+#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) */
+#ifndef SOC_SERIES_STM32U5
+ i2c_objs[i].dma.handle_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ i2c_objs[i].dma.handle_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+ i2c_objs[i].dma.handle_rx.Init.MemInc = DMA_MINC_ENABLE;
+ i2c_objs[i].dma.handle_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ i2c_objs[i].dma.handle_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ i2c_objs[i].dma.handle_rx.Init.Mode = DMA_NORMAL;
+ i2c_objs[i].dma.handle_rx.Init.Priority = DMA_PRIORITY_LOW;
+#endif /* SOC_SERIES_STM32U5 */
+#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7)
+
+ i2c_objs[i].dma.handle_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ i2c_objs[i].dma.handle_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+ i2c_objs[i].dma.handle_tx.Init.MemBurst = DMA_MBURST_INC4;
+ i2c_objs[i].dma.handle_tx.Init.PeriphBurst = DMA_PBURST_INC4;
+ }
+#endif /* defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32H7) */
+ {
+ rt_uint32_t tmpreg = 0x00U;
+#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0)
+ /* enable DMA clock && Delay after an RCC peripheral clock enabling*/
+ SET_BIT(RCC->AHBENR, i2c_config[i].dma_tx->dma_rcc);
+ tmpreg = READ_BIT(RCC->AHBENR, i2c_config[i].dma_tx->dma_rcc);
+#elif defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32H7)
+ SET_BIT(RCC->AHB1ENR, i2c_config[i].dma_tx->dma_rcc);
+ /* Delay after an RCC peripheral clock enabling */
+ tmpreg = READ_BIT(RCC->AHB1ENR, i2c_config[i].dma_tx->dma_rcc);
+#elif defined(SOC_SERIES_STM32MP1)
+ __HAL_RCC_DMAMUX_CLK_ENABLE();
+ SET_BIT(RCC->MP_AHB2ENSETR, i2c_config[i].dma_tx->dma_rcc);
+ tmpreg = READ_BIT(RCC->MP_AHB2ENSETR, i2c_config[i].dma_tx->dma_rcc);
+#endif /* defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) */
+ UNUSED(tmpreg); /* To avoid compiler warnings */
+ }
+ rt_completion_init(&i2c_objs[i].completion);
+ stm32_i2c_configure(&i2c_objs[i].i2c_bus);
+ ret = rt_i2c_bus_device_register(&i2c_objs[i].i2c_bus, i2c_objs[i].config->name);
+ RT_ASSERT(ret == RT_EOK);
+ LOG_D("%s bus init done", i2c_config[i].name);
+ }
+ return ret;
+}
+
+static void stm32_get_dma_info(void)
+{
+#ifdef BSP_I2C1_RX_USING_DMA
+ i2c_objs[I2C1_INDEX].i2c_dma_flag |= I2C_USING_RX_DMA_FLAG;
+ static struct dma_config I2C1_dma_rx = I2C1_RX_DMA_CONFIG;
+ i2c_config[I2C1_INDEX].dma_rx = &I2C1_dma_rx;
+#endif /* BSP_I2C1_RX_USING_DMA */
+#ifdef BSP_I2C1_TX_USING_DMA
+ i2c_objs[I2C1_INDEX].i2c_dma_flag |= I2C_USING_TX_DMA_FLAG;
+ static struct dma_config I2C1_dma_tx = I2C1_TX_DMA_CONFIG;
+ i2c_config[I2C1_INDEX].dma_tx = &I2C1_dma_tx;
+#endif /* BSP_I2C1_TX_USING_DMA */
+
+#ifdef BSP_I2C2_RX_USING_DMA
+ i2c_objs[I2C2_INDEX].i2c_dma_flag |= I2C_USING_RX_DMA_FLAG;
+ static struct dma_config I2C2_dma_rx = I2C2_RX_DMA_CONFIG;
+ i2c_config[I2C2_INDEX].dma_rx = &I2C2_dma_rx;
+#endif /* BSP_I2C2_RX_USING_DMA */
+#ifdef BSP_I2C2_TX_USING_DMA
+ i2c_objs[I2C2_INDEX].i2c_dma_flag |= I2C_USING_TX_DMA_FLAG;
+ static struct dma_config I2C2_dma_tx = I2C2_TX_DMA_CONFIG;
+ i2c_config[I2C2_INDEX].dma_tx = &I2C2_dma_tx;
+#endif /* BSP_I2C2_TX_USING_DMA */
+
+#ifdef BSP_I2C3_RX_USING_DMA
+ i2c_objs[I2C3_INDEX].i2c_dma_flag |= I2C_USING_RX_DMA_FLAG;
+ static struct dma_config I2C3_dma_rx = I2C3_RX_DMA_CONFIG;
+ i2c_config[I2C3_INDEX].dma_rx = &I2C3_dma_rx;
+#endif /* BSP_I2C3_RX_USING_DMA */
+#ifdef BSP_I2C3_TX_USING_DMA
+ i2c_objs[I2C3_INDEX].i2c_dma_flag |= I2C_USING_TX_DMA_FLAG;
+ static struct dma_config I2C3_dma_tx = I2C3_TX_DMA_CONFIG;
+ i2c_config[I2C3_INDEX].dma_tx = &I2C3_dma_tx;
+#endif /* BSP_I2C3_TX_USING_DMA */
+}
+
+void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ struct stm32_i2c *i2c_drv = rt_container_of(hi2c, struct stm32_i2c, handle);
+ rt_completion_done(&i2c_drv->completion);
+}
+void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ struct stm32_i2c *i2c_drv = rt_container_of(hi2c, struct stm32_i2c, handle);
+ rt_completion_done(&i2c_drv->completion);
+}
+void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Send stop signal to prevent bus lock-up */
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ LOG_D("I2C NACK Error now stoped");
+ hi2c->Instance->CR1 |= I2C_IT_STOPI;
+ }
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_BERR)
+ {
+ LOG_D("I2C BUS Error now stoped");
+ hi2c->Instance->CR1 |= I2C_IT_STOPI;
+ }
+}
+#ifdef BSP_USING_HARD_I2C1
+/**
+ * @brief This function handles I2C2 event interrupt.
+ */
+void I2C1_EV_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_EV_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_EV_IRQn 0 */
+ HAL_I2C_EV_IRQHandler(&i2c_objs[I2C1_INDEX].handle);
+ /* USER CODE BEGIN I2C2_EV_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_EV_IRQn 1 */
+}
+
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C1_ER_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_ER_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_ER_IRQn 0 */
+ HAL_I2C_ER_IRQHandler(&i2c_objs[I2C1_INDEX].handle);
+ /* USER CODE BEGIN I2C2_ER_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_ER_IRQn 1 */
+}
+#endif /* BSP_USING_HARD_I2C1 */
+
+#ifdef BSP_USING_HARD_I2C2
+/**
+ * @brief This function handles I2C2 event interrupt.
+ */
+void I2C2_EV_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_EV_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_EV_IRQn 0 */
+ HAL_I2C_EV_IRQHandler(&i2c_objs[I2C2_INDEX].handle);
+ /* USER CODE BEGIN I2C2_EV_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_EV_IRQn 1 */
+}
+
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C2_ER_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_ER_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_ER_IRQn 0 */
+ HAL_I2C_ER_IRQHandler(&i2c_objs[I2C2_INDEX].handle);
+ /* USER CODE BEGIN I2C2_ER_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_ER_IRQn 1 */
+}
+#endif /* BSP_USING_HARD_I2C2 */
+
+#ifdef BSP_USING_HARD_I2C3
+/**
+ * @brief This function handles I2C2 event interrupt.
+ */
+void I2C3_EV_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_EV_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_EV_IRQn 0 */
+ HAL_I2C_EV_IRQHandler(&i2c_objs[I2C3_INDEX].handle);
+ /* USER CODE BEGIN I2C2_EV_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_EV_IRQn 1 */
+}
+
+/**
+ * @brief This function handles I2C2 error interrupt.
+ */
+void I2C3_ER_IRQHandler(void)
+{
+ /* USER CODE BEGIN I2C2_ER_IRQn 0 */
+ /* enter interrupt */
+ rt_interrupt_enter();
+ /* USER CODE END I2C2_ER_IRQn 0 */
+ HAL_I2C_ER_IRQHandler(&i2c_objs[I2C3_INDEX].handle);
+ /* USER CODE BEGIN I2C2_ER_IRQn 1 */
+ /* leave interrupt */
+ rt_interrupt_leave();
+ /* USER CODE END I2C2_ER_IRQn 1 */
+}
+#endif /* BSP_USING_HARD_I2C3 */
+
+#if defined(BSP_USING_HARD_I2C1) && defined(BSP_I2C1_RX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C1_DMA_RX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C1_INDEX].dma.handle_rx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C1 && BSP_I2C1_RX_USING_DMA */
+#if defined(BSP_USING_HARD_I2C1) && defined(BSP_I2C1_TX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C1_DMA_TX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C1_INDEX].dma.handle_tx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C1 && BSP_I2C1_TX_USING_DMA */
+#if defined(BSP_USING_HARD_I2C2) && defined(BSP_I2C2_RX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C2_DMA_RX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C2_INDEX].dma.handle_rx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C2 && BSP_I2C2_RX_USING_DMA */
+#if defined(BSP_USING_HARD_I2C2) && defined(BSP_I2C2_TX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C2_DMA_TX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C2_INDEX].dma.handle_tx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C2 && BSP_I2C2_TX_USING_DMA */
+#if defined(BSP_USING_HARD_I2C3) && defined(BSP_I2C3_RX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C3_DMA_RX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C3_INDEX].dma.handle_rx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C3 && BSP_I2C3_RX_USING_DMA */
+#if defined(BSP_USING_HARD_I2C3) && defined(BSP_I2C3_TX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C3_DMA_TX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C3_INDEX].dma.handle_tx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_HARD_I2C3 && BSP_I2C3_TX_USING_DMA */
+#if defined(BSP_USING_I2C4) && defined(BSP_I2C4_RX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C4_DMA_RX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C4_INDEX].dma.handle_rx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* BSP_USING_I2C4 && BSP_I2C4_RX_USING_DMA */
+#if defined(BSP_USING_I2C4) && defined(BSP_I2C4_TX_USING_DMA)
+/**
+ * @brief This function handles DMA Rx interrupt request.
+ * @param None
+ * @retval None
+ */
+void I2C4_DMA_TX_IRQHandler(void)
+{
+ /* enter interrupt */
+ rt_interrupt_enter();
+
+ HAL_DMA_IRQHandler(&i2c_objs[I2C4_INDEX].dma.handle_tx);
+
+ /* leave interrupt */
+ rt_interrupt_leave();
+}
+#endif /* defined(BSP_USING_I2C4) && defined(BSP_I2C4_TX_USING_DMA) */
+
+int rt_hw_hw_i2c_init(void)
+{
+ stm32_get_dma_info();
+ return RT_hw_i2c_bus_init();
+}
+INIT_CORE_EXPORT(rt_hw_hw_i2c_init);
+
+#endif
+#endif /* RT_USING_I2C */
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.h b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.h
new file mode 100644
index 0000000000..2d9d425cd8
--- /dev/null
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_hard_i2c.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-02-17 Dyyt587 first version
+ */
+
+#ifndef __DRV_HARD_I2C_H__
+#define __DRV_HARD_I2C_H__
+
+#include "drv_config.h"
+#include <rtthread.h>
+#include "rtdevice.h"
+#include <rthw.h>
+#include <drv_common.h>
+#include "drv_dma.h"
+#include <ipc/completion.h>
+#ifdef (RT_USING_I2C && BSP_USING_I2C)
+
+/* C binding of definitions if building with C++ compiler */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+struct stm32_i2c_config
+{
+ const char *name;
+ I2C_TypeDef *Instance;
+ rt_uint32_t timing;
+ rt_uint32_t timeout;
+ IRQn_Type evirq_type;
+ IRQn_Type erirq_type;
+
+ struct dma_config *dma_rx, *dma_tx;
+};
+
+struct stm32_i2c
+{
+ I2C_HandleTypeDef handle;
+ struct
+ {
+ DMA_HandleTypeDef handle_rx;
+ DMA_HandleTypeDef handle_tx;
+ } dma;
+ struct stm32_i2c_config *config;
+ struct rt_i2c_bus_device i2c_bus;
+ rt_uint8_t i2c_dma_flag;
+ struct rt_completion completion;
+
+};
+
+#define I2C_USING_TX_DMA_FLAG (1U)
+#define I2C_USING_RX_DMA_FLAG (1U << 1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BSP_USING_I2C */
+
+#endif /* __DRV_I2C_H__ */
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/i2c_hard_config.h b/bsp/stm32/libraries/HAL_Drivers/drivers/i2c_hard_config.h
new file mode 100644
index 0000000000..d1c35ce575
--- /dev/null
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/i2c_hard_config.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-02-06 Dyyt587 first version
+ */
+#ifndef __I2C_HARD_CONFIG_H__
+#define __I2C_HARD_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BSP_USING_HARD_I2C1
+#ifndef I2C1_BUS_CONFIG
+#define I2C1_BUS_CONFIG \
+ { \
+ .Instance = I2C1, \
+ .timing=0x10707DBC, \
+ .timeout=0x1000, \
+ .name = "i2c1", \
+ .evirq_type = I2C1_EV_IRQn, \
+ .erirq_type = I2C1_ER_IRQn, \
+ }
+#endif /* I2C1_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C1 */
+
+#ifdef BSP_I2C1_TX_USING_DMA
+#ifndef I2C1_TX_DMA_CONFIG
+#define I2C1_TX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C1_TX_DMA_RCC, \
+ .Instance = I2C1_TX_DMA_INSTANCE, \
+ .dma_irq = I2C1_TX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C1_TX \
+ }
+#endif /* I2C1_TX_DMA_CONFIG */
+#endif /* BSP_I2C1_TX_USING_DMA */
+
+#ifdef BSP_I2C1_RX_USING_DMA
+#ifndef I2C1_RX_DMA_CONFIG
+#define I2C1_RX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C1_RX_DMA_RCC, \
+ .Instance = I2C1_RX_DMA_INSTANCE, \
+ .dma_irq = I2C1_RX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C1_RX \
+ }
+#endif /* I2C1_RX_DMA_CONFIG */
+#endif /* BSP_I2C1_RX_USING_DMA */
+
+#ifdef BSP_USING_HARD_I2C2
+#ifndef I2C2_BUS_CONFIG
+#define I2C2_BUS_CONFIG \
+ { \
+ .Instance = I2C2, \
+ .timing=0x10707DBC, \
+ .timeout=0x1000, \
+ .name = "i2c2", \
+ .evirq_type = I2C2_EV_IRQn, \
+ .erirq_type = I2C2_ER_IRQn, \
+ }
+#endif /* I2C2_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C2 */
+
+#ifdef BSP_I2C2_TX_USING_DMA
+#ifndef I2C2_TX_DMA_CONFIG
+#define I2C2_TX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C2_TX_DMA_RCC, \
+ .Instance = I2C2_TX_DMA_INSTANCE, \
+ .dma_irq = I2C2_TX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C2_TX \
+ }
+#endif /* I2C2_TX_DMA_CONFIG */
+#endif /* BSP_I2C2_TX_USING_DMA */
+
+#ifdef BSP_I2C2_RX_USING_DMA
+#ifndef I2C2_RX_DMA_CONFIG
+#define I2C2_RX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C2_RX_DMA_RCC, \
+ .Instance = I2C2_RX_DMA_INSTANCE, \
+ .dma_irq = I2C2_RX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C2_RX \
+ }
+#endif /* I2C2_RX_DMA_CONFIG */
+#endif /* BSP_I2C2_RX_USING_DMA */
+
+#ifdef BSP_USING_HARD_I2C3
+#ifndef I2C3_BUS_CONFIG
+#define I2C3_BUS_CONFIG \
+ { \
+ .Instance = I2C3, \
+ .timing=0x10707DBC, \
+ .timeout=0x1000, \
+ .name = "i2c3", \
+ .evirq_type = I2C3_EV_IRQn, \
+ .erirq_type = I2C3_ER_IRQn, \
+ }
+#endif /* I2C3_BUS_CONFIG */
+#endif /* BSP_USING_HARD_I2C3 */
+
+#ifdef BSP_I2C3_TX_USING_DMA
+#ifndef I2C3_TX_DMA_CONFIG
+#define I2C3_TX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C3_TX_DMA_RCC, \
+ .Instance = I2C3_TX_DMA_INSTANCE, \
+ .dma_irq = I2C3_TX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C3_TX \
+ }
+#endif /* I2C3_TX_DMA_CONFIG */
+#endif /* BSP_I2C3_TX_USING_DMA */
+
+#ifdef BSP_I2C3_RX_USING_DMA
+#ifndef I2C3_RX_DMA_CONFIG
+#define I2C3_RX_DMA_CONFIG \
+ { \
+ .dma_rcc = I2C3_RX_DMA_RCC, \
+ .Instance = I2C3_RX_DMA_INSTANCE, \
+ .dma_irq = I2C3_RX_DMA_IRQ, \
+ .request = DMA_REQUEST_I2C3_RX \
+ }
+#endif /* I2C3_RX_DMA_CONFIG */
+#endif /* BSP_I2C3_RX_USING_DMA */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__I2C_CONFIG_H__ */