Browse Source

[bsp][stm32] add hardware i2c driver

Dyyt587 1 year ago
parent
commit
4e1626703f

+ 4 - 0
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']

+ 726 - 0
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 */

+ 66 - 0
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__ */

+ 137 - 0
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__ */